熊猫中两组的箱线图

Posted

技术标签:

【中文标题】熊猫中两组的箱线图【英文标题】:Boxplot by two groups in pandas 【发布时间】:2021-10-14 11:19:38 【问题描述】:

我有以下数据集:

df_plots = pd.DataFrame('Group':['A','A','A','A','A','A','B','B','B','B','B','B'],
                         'Type':['X','X','X','Y','Y','Y','X','X','X','Y','Y','Y'],
                         'Value':[1,1.2,1.4,1.3,1.8,1.5,15,19,18,17,12,13])
df_plots
    Group   Type    Value
0   A       X       1.0
1   A       X       1.2
2   A       X       1.4
3   A       Y       1.3
4   A       Y       1.8
5   A       Y       1.5
6   B       X       15.0
7   B       X       19.0
8   B       X       18.0
9   B       Y       17.0
10  B       Y       12.0
11  B       Y       13.0

我想为每个Group 创建箱线图(示例中有两个),并在每个图中按类型显示。我试过这个:

fig, axs = plt.subplots(1,2,figsize=(8,6), sharey=False)
axs = axs.flatten()

for i, g in enumerate(df_plots[['Group','Type','Value']].groupby(['Group','Type'])):
    g[1].boxplot(ax=axs[i])
导致IndexError,因为循环尝试创建 4 个图。
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-12-8e1150950024> in <module>
      3 
      4 for i, g in enumerate(df[['Group','Type','Value']].groupby(['Group','Type'])):
----> 5     g[1].boxplot(ax=axs[i])

IndexError: index 2 is out of bounds for axis 0 with size 2

然后我尝试了这个:

fig, axs = plt.subplots(1,2,figsize=(8,6), sharey=False)
axs = axs.flatten()

for i, g in enumerate(df_plots[['Group','Type','Value']].groupby(['Group','Type'])):
    g[1].boxplot(ax=axs[i], by=['Group','Type'])

但是不,我有同样的问题。预期的结果应该只有两个图,每个图的每个类型都有一个盒须。这是这个想法的草图:

请,任何帮助将不胜感激,使用此代码,我可以控制数据的某些方面,而我无法使用 seaborn。

【问题讨论】:

【参考方案1】:

使用seaborn.catplot:

import seaborn as sns
sns.catplot(data=df, kind='box', col='Group', x='Type', y='Value', hue='Type', sharey=False, height=4)

【讨论】:

你好@mozway,我很欣赏你的回答,但我更喜欢给定的代码,没有seaborn,因为我必须在循环内进行一些计算。无论如何,谢谢。 那你不能用FacetGrid吗?它可以处理图形布局,并且仍然可以让您访问每组的原始数据。如果您真的不想这样做,请预处理您的数据并仅按“组”分组以进行绘图。 @Alexis 我必须在循环内进行一些计算 OP 中没有显示。最好将计算步骤与绘图步骤分开。【参考方案2】:

我们可以使用groupby boxplot为每个Group创建子图,然后用Type分隔每个boxplot

fig, axes = plt.subplots(1, 2, figsize=(8, 6), sharey=False)
df_plots.groupby('Group').boxplot(by='Type', ax=axes)
plt.show()

或者不用subplots直接通过函数调用传递参数:

axes = df_plots.groupby('Group').boxplot(by='Type', figsize=(8, 6),
                                         layout=(1, 2), sharey=False)
plt.show()


数据和导入:

import pandas as pd
from matplotlib import pyplot as plt

df_plots = pd.DataFrame(
    'Group': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B'],
    'Type': ['X', 'X', 'X', 'Y', 'Y', 'Y', 'X', 'X', 'X', 'Y', 'Y', 'Y'],
    'Value': [1, 1.2, 1.4, 1.3, 1.8, 1.5, 15, 19, 18, 17, 12, 13]
)

【讨论】:

我很惊讶by='Type' 似乎无法与df_plots.groupby('Group').plot(kind='box', by='Type', figsize=(8, 6), layout=(1, 2), sharey=False) 一起正常工作 在我的快速(并且绝不是对某些源代码的全面阅读)中,by 似乎被传递给不处理 bymatplotlib.pyplot.boxplot,而groupby.boxplot 传递给DataFrame.boxplot,它确实处理by,并将剩余的值传递给matplotlib.pyplot.boxplot 您好@HenryEcker,非常感谢您的回答和时间!【参考方案3】:

作为@Prune mentioned,直接的问题是您的groupby() 返回四个组(AX、AY、BX、BY),所以首先修复索引,然后再清理几个问题:

    axs[i] 更改为 axs[i//2] 以将组 0 和 1 放在 axs[0] 上,将组 2 和 3 放在 axs[1] 上。 添加positions=[i] 将箱线图并排放置,而不是堆叠放置。 在绘图后设置titlexticklabels(我不知道如何在主循环中执行此操作)。
for i, g in enumerate(df_plots.groupby(['Group', 'Type'])):
    g[1].boxplot(ax=axs[i//2], positions=[i])

for i, ax in enumerate(axs):
    ax.set_title('Group: ' + df_plots['Group'].unique()[i])
    ax.set_xticklabels(['Type: X', 'Type: Y'])


请注意,里程可能因版本而异:

matplotlib.__version__ pd.__version__
confirmed working 3.4.2 1.3.1
confirmed not working 3.0.1 1.2.4

【讨论】:

你好@tdy,我尝试了你的解决方案,但我看起来与你的图像不同(我的每边只显示 1 个箱线图)。我什至复制粘贴了你的代码,但我没有显示你有什么。我错过了什么吗? 嗯不确定。我刚刚添加了一个完整的最小示例,它给了我你预期的输出。如果那仍然没有给您相同的结果,也许是版本问题?我正在使用 matplotlib 3.4.2 和 pandas 1.3.1 那一定是问题!,我的matplotlib版本是3.0.1,pandas版本是1.2.4,我试试更新看看能不能重现你的情节。谢谢! 这就是问题所在,版本!现在已经用你的代码解决了,谢谢!【参考方案4】:

直接的问题是您的groupby 操作返回四个元素(AX、AY、BX、BY),您尝试单独绘制它们。您尝试使用ax=axs[i] ...但i 运行0-3,而您的扁平结构中只有两个元素。没有axs[2]axs[3],这会引发给定的运行时异常。

您需要以一种或另一种方式解决您的引用问题。

【讨论】:

以上是关于熊猫中两组的箱线图的主要内容,如果未能解决你的问题,请参考以下文章

使用熊猫的箱线图

组的箱线图?

如何在具有多个组的箱线图顶部创建单独的线

不同x和同一组的箱线图之间的geom_signif

如何在ggplot的箱线图中按组绘制平均值

同一图上 Pandas 数据框多列的箱线图(seaborn)