为 groupby 对象绘制箱线图

Posted

技术标签:

【中文标题】为 groupby 对象绘制箱线图【英文标题】:Plotting boxplots for a groupby object 【发布时间】:2017-10-24 10:22:06 【问题描述】:

我想根据一个标准为几个数据集绘制箱线图。 想象一个类似于以下示例的数据框:

df = pd.DataFrame('Group':[1,1,1,2,3,2,2,3,1,3],'M':np.random.rand(10),'F':np.random.rand(10))
df = df[['Group','M','F']]

   Group         M         F
0      1  0.465636  0.537723
1      1  0.560537  0.727238
2      1  0.268154  0.648927
3      2  0.722644  0.115550
4      3  0.586346  0.042896
5      2  0.562881  0.369686
6      2  0.395236  0.672477
7      3  0.577949  0.358801
8      1  0.764069  0.642724
9      3  0.731076  0.302369

在这种情况下,我有三个组,所以我想为每个组制作一个箱线图,并为 M 和 F 分别制作 Y 轴上的组和 M 和 F 的列颜色编码。 This answer 非常接近我想要实现的目标,但我更喜欢更健壮的东西,适用于具有更多组数的更大数据帧。我觉得 groupby 是要走的路,但我对 groupby 对象不熟悉,我什至没有对它们进行切片。 .理想的输出如下所示:

好像几年前,有人遇到过同样的问题,但没有得到答案:(Having a boxplot as a graphical representation of the describe function of groupby

我的问题是:

    如何实现 groupby 以将所需数据输入箱线图 如果我想控制显示的内容而不仅仅是使用默认设置(我什至不知道它们是什么,我发现文档相当模糊,那么箱线图的正确语法是什么。具体来说,我可以让盒子覆盖平均值 +/- 标准差,并将垂直线保持在中值吗?)

【问题讨论】:

您尝试了一些代码吗?你遇到了什么样的问题/错误? import matplotlib.pyplot as plt 然后 df.boxplot(['M','F'],'Group') 这将根据组为男性和女性生成 2 个单独的图。 正如你所说,这会生成单独的子图,它不会将它们绘制在一起。另外,它没有解决第 2 点。但是,谢谢,对于一个更简单的情况,很高兴知道它是多么容易完成。 请试试这个,它会给你 x 轴上的 4 个四分位数 df.boxplot(by='Group',vert=False) 很难在一个图中得到所有变量我们也在同时应用 groupby 操作,但我们可以得到多个图取决于按分组变量分组的变量的基础。 【参考方案1】:

我认为您应该使用提供创建这些类型的自定义图的 Seaborn 库。在您的情况下,我首先融化了您的数据框以将其转换为正确的格式,然后创建了您选择的箱线图。

import pandas as pd
import matplotlib.pyplot as plt
Import seaborn as sns
dd=pd.melt(df,id_vars=['Group'],value_vars=['M','F'],var_name='sex')
sns.boxplot(y='Group',x='value',data=dd,orient="h",hue='sex')

情节看起来与您所需的情节相似。

【讨论】:

【参考方案2】:

最后通过对this answer稍作修改找到了解决方案。它不使用 groupby 对象,因此准备数据比较繁琐,但到目前为止,它对我来说似乎是最好的解决方案。这里是:

# here I prepare the data (group them manually and then store in lists)

Groups=[1,2,3]
Columns=df.columns.tolist()[1:]
print Columns
Mgroups=[]
Fgroups=[]

for g in Groups:
    dfgc = df[df['Group']==g]
    m=dfgc['M'].dropna()
    f=dfgc['F'].dropna()
    Mgroups.append(m.tolist())
    Fgroups.append(f.tolist())

fig=plt.figure()
ax = plt.axes()
def setBoxColors(bp,cl):
    plt.setp(bp['boxes'], color=cl, linewidth=2.)
    plt.setp(bp['whiskers'], color=cl, linewidth=2.5)
    plt.setp(bp['caps'], color=cl,linewidth=2)
    plt.setp(bp['medians'], color=cl, linewidth=3.5)

bpl = plt.boxplot(Mgroups, positions=np.array(xrange(len(Mgroups)))*3.0-0.4,vert=False,whis='range', sym='', widths=0.6)
bpr = plt.boxplot(Fgroups, positions=np.array(xrange(len(Fgroups)))*3.0+0.4,vert=False,whis='range', sym='', widths=0.6)
setBoxColors(bpr, '#D7191C') # colors are from http://colorbrewer2.org/
setBoxColors(bpl, '#2C7BB6')

# draw temporary red and blue lines and use them to create a legend
plt.plot([], c='#D7191C', label='F')
plt.plot([], c='#2C7BB6', label='M')
plt.legend()

plt.yticks(xrange(0, len(Groups) * 3, 3), Groups)
plt.ylim(-3, len(Groups)*3)
#plt.xlim(0, 8)
plt.show()

结果看起来很像我想要的(据我所知,该框的范围总是从第一四分位数到第三四分位数,因此无法将其设置为 +/- 标准差)。所以我有点失望,没有单线解决方案,但我很高兴这是可能的。然而,对于数百个团体来说,这还不够好......

【讨论】:

以上是关于为 groupby 对象绘制箱线图的主要内容,如果未能解决你的问题,请参考以下文章

使用 groupby 创建箱线图

R语言绘制箱线图分面并添加文本注释(基础知识)

Fig4-a ggplot2绘制箱线图叠加散点图2020-12-14

如何绘制混合箱线图:另一半有抖动点的半箱线图?

Python:获取所有节点的度数,然后在networkx中绘制箱线图

在一张图中绘制多个箱线图