在Python Pandas中按列分层绘制箱线图

7 投票
2 回答
18221 浏览
提问于 2025-04-18 03:51

我想为以下的 pandas 数据框画一个箱线图:

> p1.head(10)

   N0_YLDF    MAT
0     1.29  13.67
1     2.32  10.67
2     6.24  11.29
3     5.34  21.29
4     6.35  41.67
5     5.35  91.67
6     9.32  21.52
7     6.32  31.52
8     3.33  13.52
9     4.56  44.52

我想要的箱线图是基于 'N0_YLDF' 这一列,但要按照 'MAT' 来分组。当我使用以下命令时:

p1.boxplot(column='N0_YLDF',by='MAT')

它会使用所有独特的 MAT 值,而在完整的 p1 数据框中,这个值大约有 15,000 个。这导致生成的箱线图看起来非常混乱。

有没有办法让我对 MAT 值进行分组,这样我就可以得到不同的 N0_YLDF 箱线图,比如针对 MAT 值的第一个四分位数等等……

谢谢!

2 个回答

10

Pandas有两个很方便的函数,叫做cutqcut,可以帮助我们轻松地把变量分成不同的组。

# Just asking for split into 4 equal groups (i.e. quartiles) here,
# but you can split on custom quantiles by passing in an array
p1['MAT_quartiles'] = pd.qcut(p1['MAT'], 4, labels=['0-25%', '25-50%', '50-75%', '75-100%'])
p1.boxplot(column='N0_YLDF', by='MAT_quartiles')

输出结果:

enter image description here

6

pandas.qcut 可以用来计算分位数,但如果想要做类似直方图的操作,就需要用到一些 numpy 的小技巧,这里会派上用场:

_, breaks = np.histogram(df.MAT, bins=5)
ax = df.boxplot(column='N0_YLDF', by='Class')
ax.xaxis.set_ticklabels(['%s'%val for i, val in enumerate(breaks) if i in df.Class])

这里插入图片描述

现在这个数据表看起来是这样的:

   N0_YLDF    MAT  Class
0     1.29  13.67      1
1     2.32  10.67      0
2     6.24  11.29      1
3     5.34  21.29      1
4     6.35  41.67      2
5     5.35  91.67      5
6     9.32  21.52      1
7     6.32  31.52      2
8     3.33  13.52      1
9     4.56  44.52      3

[10 rows x 3 columns]

它也可以用来生成四分位数图:

breaks = np.asarray(np.percentile(df.MAT, [25,50,75,100]))
df['Class'] = (df.MAT.values > breaks[..., np.newaxis]).sum(0)
ax = df.boxplot(column='N0_YLDF', by='Class')
ax.xaxis.set_ticklabels(['%s'%val for val in breaks])

这里插入图片描述

撰写回答