使用色调和不同比例轴的 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 图中很好地制作条形图和线图?

使用 seaborn 更改直方图上的轴单位

带有日期时间轴的 Seaborn 热图

以日期为 X 轴的 Seaborn 条形图

(Python数字图像处理)彩色图像处理---色调和彩色校正以及直方图均衡化

如何在 Swift 中使用色调和一些文本向 UIImageView 添加叠加层?