使用色调和不同比例轴的 Seaborn(时间序列)箱线图
Posted
技术标签:
【中文标题】使用色调和不同比例轴的 Seaborn(时间序列)箱线图【英文标题】:Seaborn (time series) boxplot using hue and different scale axes 【发布时间】:2018-10-23 06:42:06 【问题描述】:我有一个数据框,每个日期有多个值(日期时间字段)。这些值通过使用列 Group 分为 U (users) 和 S (session)。 Seaborn 用于可视化每个日期的两个箱线图,其中色调设置为 Group。
当考虑到对应于 U (users) 的值远大于对应于 S (session) 的值时,问题就出现了,使得 S 数据难以辨认。因此,我需要想出一个解决方案,让我能够以易于理解的方式在同一个图中绘制两个系列(U 和 S)。
我想知道是否可以为每个色调设置独立的 Y 轴(具有不同的比例),以便同时显示两个 Y 轴(就像使用 twinx
时一样,但不会失去色调可视化功能。
欢迎任何其他选择 =)
S箱线图时间序列箱线图:
使用色调的组合箱线图时间序列。显然,由于 Y 轴的比例,看不到任何关于 S 组的信息:
数据框的列:
|日期(日期时间)| n_data(数字)|组(S 或 U)|
生成组合箱线图的代码行:
seaborn.boxplot(ax=ax,x='Day', y='n_data', hue='Group', data=df,
palette='PRGn', showfliers=False)
设法通过使用 twinx 找到解决方案:
fig,ax= plt.subplots(figsize=(50,10))
tmpU = groups.copy()
tmpU.loc[tmp['Group']!='U','n_data'] = np.nan
tmpS = grupos.copy()
tmpS.loc[tmp['Group']!='S','n_data'] = np.nan
ax=seaborn.boxplot(ax=ax,x='Day', y = 'n_data', hue='Group', data=tmpU, palette = 'PRGn', showfliers=False)
ax2 = ax.twinx()
seaborn.boxplot(ax=ax2,x='Day', y = 'n_data', hue='Group', data=tmpS, palette = 'PRGn', showfliers=False)
handles,labels = ax.get_legend_handles_labels()
l= plt.legend(handles[0:2],labels[0:2],loc=1)
plt.setp(ax.get_xticklabels(),rotation=30,horizontalalignment='right')
for label in ax.get_xticklabels()[::2]:
label.set_visible(False)
plt.show()
plt.close('all')
上面的代码生成下图:
在这种情况下,结果过于密集而无法发布。因此,正如 Parfait 在他/她的回答中所暗示的那样,我将采用基于子图的可视化。
这对我来说不是一个明显的解决方案,所以我要感谢 Parfait 的回答。
【问题讨论】:
请显示代码。请包括数据样本。甚至请截图问题情节。 我添加了生成组合图的行、我所指的图像并解释了我正在绘制的熊猫数据框的头部。不要犹豫,提出任何问题或任何可能有助于解决我的问题的进一步细节。另外,我知道我所要求的可以使用 R 来完成。 【参考方案1】:因此,使用两个单独的轴进行分组箱线图的一种选择是在 sns.boxplot
的参数中使用 hue_order= ['value, np.nan]
:
fig = plt.figure(figsize=(14,8))
ax = sns.boxplot(x="lon_bucketed", y="value", data=m, hue='name', hue_order=['co2',np.nan],
width=0.75,showmeans=True,meanprops="marker":"s","markerfacecolor":"black", "markeredgecolor":"black",linewidth=0.5 ,palette = customPalette)
ax2 = ax.twinx()
ax2 = sns.boxplot(ax=ax2,x="lon_bucketed", y="value", data=m, hue='name', hue_order=[np.nan,'g_xco2'],
width=0.75,showmeans=True,meanprops="marker":"s","markerfacecolor":"black", "markeredgecolor":"black",linewidth=0.5, palette = customPalette)
ax1.grid(alpha=0.5, which = 'major')
plt.tight_layout()
ax.legend_.remove()
GW = mpatches.Patch(color='seagreen', label='$CO_2$')
WW = mpatches.Patch(color='mediumaquamarine', label='$XCO_2$')
ax, ax2.legend(handles=[GW,WW], loc='upper right',prop='size': 14, fontsize=12)
ax.set_title("$XCO_2$ vs. $CO_2$",fontsize=18)
ax.set_xlabel('Longitude [\u00b0]',fontsize=14)
ax.set_ylabel('$CO_2$ [ppm]',fontsize=14)
ax2.set_ylabel('$XCO_2$ [ppm]',fontsize=14)
ax.tick_params(labelsize=14)
【讨论】:
【参考方案2】:考虑使用针对子集数据量身定制的 y 轴范围在同一图形上构建单独的图。下面演示了为可重复性而播种的随机数据(适用于本文的读者)。
数据 (U值高于S值)
import pandas as pd
import numpy as np
import seaborn
import matplotlib.pyplot as plt
np.random.seed(2018)
u_df = pd.DataFrame('Day': pd.date_range('2016-10-01', periods=10)\
.append(pd.date_range('2016-10-01', periods=10)),
'n_data': np.random.uniform(0,800,20),
'Group': 'U')
s_df = pd.DataFrame('Day': pd.date_range('2016-10-01', periods=10)\
.append(pd.date_range('2016-10-01', periods=10)),
'n_data': np.random.uniform(0,200,20),
'Group': 'S')
df = pd.concat([u_df, s_df], ignore_index=True)
df['Day'] = df['Day'].astype('str')
情节
fig = plt.figure(figsize=(10,5))
for i,g in enumerate(df.groupby('Group')):
plt.title('N_data of '.format(g[0]))
plt.subplot(2, 1, i+1)
seaborn.boxplot(x="Day", y="n_data", data=g[1], palette="PRGn", showfliers=False)
plt.tight_layout()
plt.show()
plt.clf()
plt.close('all')
要保留原始色调和分组,请将所有非分组 n_data 渲染到np.nan
:
fig = plt.figure(figsize=(10,5))
for i,g in enumerate(df.Group.unique()):
plt.subplot(2, 1, i+1)
tmp = df.copy()
tmp.loc[tmp['Group']!=g, 'n_data'] = np.nan
seaborn.boxplot(x="Day", y="n_data", hue="Group", data=tmp,
palette="PRGn", showfliers=False)
plt.tight_layout()
plt.show()
plt.clf()
plt.close('all')
【讨论】:
以上是关于使用色调和不同比例轴的 Seaborn(时间序列)箱线图的主要内容,如果未能解决你的问题,请参考以下文章
如何在具有不同 Y 轴的同一个 seaborn 图中很好地制作条形图和线图?