df.boxplot()
返回的轴对象,并使用相同的轴将均值绘制为线图。我建议使用Seaborn的pointplot
来绘制这些线条,因为它可以很好地处理分类x轴。首先让我们生成一些示例数据:import pandas as pd
import numpy as np
import seaborn as sns
N = 150
values = np.random.random(size=N)
groups = np.random.choice(['A','B','C'], size=N)
df = pd.DataFrame({'value':values, 'group':groups})
print(df.head())
group value
0 A 0.816847
1 A 0.468465
2 C 0.871975
3 B 0.933708
4 A 0.480170
...
接下来,制作箱线图并保存轴对象:
ax = df.boxplot(column='value', by='group', showfliers=True,
positions=range(df.group.unique().shape[0]))
boxplot()
中有一个奇怪的positions
参数,可能导致偏差。请参阅此讨论,其中包括我在此处使用的解决方法。groupby
获取类别平均值,然后将平均值与覆盖在箱线图上的折线图连接起来:sns.pointplot(x='group', y='value', data=df.groupby('group', as_index=False).mean(), ax=ax)
您的标题提到了“中位数”,但在帖子中您谈论的是类别均值。我在这里使用了均值;如果您想绘制中位数,请将groupby
聚合更改为median()
。
您可以通过使用绘制它们的matplotlib.lines.Line2D
对象的.get_data()
属性来获取中位数的值,而无需使用seaborn。
假设您创建了一个箱线图bp=plt.boxplot(data)
。那么,bp
是一个包含medians
键的dict
,其中还有其他键。该键包含一个list
,其中包含matplotlib.lines.Line2D
,您可以按以下方式提取(x,y)位置:
bp=plt.boxplot(data)
X=[]
Y=[]
for m in bp['medians']:
[[x0, x1],[y0,y1]] = m.get_data()
X.append(np.mean((x0,x1)))
Y.append(np.mean((y0,y1)))
plt.plot(X,Y,c='C1')
data
),此脚本生成此图。希望有所帮助!