pandas 两组的箱线图

Boxplot by two groups in pandas

我有以下数据集:

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                                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。

使用seaborn.catplot:

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

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

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

我们可以使用 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]
})

作为,眼前的问题是你的groupby()returns四组(AX,AY,BX,BY),所以先修复索引,然后清理一个更多问题:

  1. axs[i] 更改为 axs[i//2],将第 0 组和第 1 组放在 axs[0] 上,将第 2 组和第 3 组放在 axs[1] 上。
  2. 添加 positions=[i] 以并排放置箱线图而不是堆叠。
  3. 绘图后设置 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