从Pandas数据框中叠加实际数据在箱线图上

4
我正在使用Seaborn从pandas数据框绘制箱线图。Seaborn箱线图似乎与pandas的boxplot功能基本相同(因此我希望两者的解决方案是相同的,但我也可以使用dataframe.boxplot函数)。我的数据框有12列,以下代码会生成一个图,其中每个列都有一个箱线图(就像dataframe.boxplot()函数一样)。
fig, ax = plt.subplots()
sns.set_style("darkgrid", {"axes.facecolor":"darkgrey"})
pal = sns.color_palette("husl",12)
sns.boxplot(dataframe, color = pal)

有人能建议一种简单的方法,在制作数据框的箱线图时,叠加所有值(按列)吗? 我将感激任何帮助。
3个回答

6

目前,seaborn.boxplot函数还没有添加这个功能,但在seaborn.violinplot函数中有类似的功能,并且具有其他优点

x = np.random.randn(30, 6)
sns.violinplot(x, inner="points")
sns.despine(trim=True)

enter image description here


2

针对整个数据框的箱线图,应适用于seabornpandas,因为它们都基于matplotlib,我将使用pandas绘图作为示例,假设已经放置了import matplotlib.pyplot as plt。由于您已经拥有了ax,最好使用ax.text(...)而不是plt.text(...)

In [35]:    
print df
         V1        V2        V3        V4        V5
0  0.895739  0.850580  0.307908  0.917853  0.047017
1  0.931968  0.284934  0.335696  0.153758  0.898149
2  0.405657  0.472525  0.958116  0.859716  0.067340
3  0.843003  0.224331  0.301219  0.000170  0.229840
4  0.634489  0.905062  0.857495  0.246697  0.983037
5  0.573692  0.951600  0.023633  0.292816  0.243963

[6 rows x 5 columns]

In [34]:    
df.boxplot()
for x, y, s in zip(np.repeat(np.arange(df.shape[1])+1, df.shape[0]), 
                   df.values.ravel(), df.values.astype('|S5').ravel()):
    plt.text(x,y,s,ha='center',va='center')

enter image description here

对于数据帧中的单个系列,需要进行一些小的更改:

In [35]:    
sub_df=df.V1
pd.DataFrame(sub_df).boxplot()
for x, y, s in zip(np.repeat(1, df.shape[0]), 
                   sub_df.ravel(), sub_df.values.astype('|S5').ravel()):
    plt.text(x,y,s,ha='center',va='center')

在这里输入图片描述

制作散点图也类似:

#for the whole thing
df.boxplot()
plt.scatter(np.repeat(np.arange(df.shape[1])+1, df.shape[0]), df.values.ravel(), marker='+', alpha=0.5)
#for just one column
sub_df=df.V1
pd.DataFrame(sub_df).boxplot()
plt.scatter(np.repeat(1, df.shape[0]), sub_df.ravel(), marker='+', alpha=0.5)

输入图像描述 输入图像描述

要在 boxplot 上叠加东西,我们需要首先猜测每个箱子在 xaxis 中的绘制位置。它们似乎是在 1,2,3,4,... 上显示的。因此,对于第一列中的值,我们希望它们在 x=1 位置绘制;第二列在 x=2 位置绘制,以此类推。

任何有效的方法都可以使用 np.repeat 来完成,重复 1,2,3,4...,每个重复 n 次,其中 n 是观察次数。然后,我们可以绘制一个图形,使用这些数字作为x坐标。由于它是一维的,所以对于 y 坐标,我们将需要数据的展平视图,由df.ravel() 提供。

对于叠加文本字符串,我们需要进行另一步操作(即循环)。因为我们只能一次绘制一个 x 值、一个 y 值和一个文本字符串。


很抱歉,“实际值”这个词有些令人困惑。我的意思是在箱线图上叠加一种散点图——即用点代替数值。感谢您查看我的问题! - geog_newbie
嗯,那个确实有些令人困惑。看看编辑部分。我建议您使用合理的“alpha”值,这样如果您有很多数据点,就可以更好地看到“云”。如果您想要更加高级的效果,请考虑使用此链接:http://nbviewer.ipython.org/github/mgymrek/pybeeswarm/blob/master/beeswarm_example.ipynb?create=1 - CT Zhu
是的,那很棒。感谢您的快速回复,@CT Zhu!它像魔法一样运行。我必须承认,我需要再看一下解决方案才能理解你做了什么...我需要再得到几个点才能给你点赞。 - geog_newbie
没问题,我已经写了几行代码,这次是用英语写的,供你观看。干杯! - CT Zhu
@CTZhu 我想做与此非常相似的事情,但我正在使用 dataframe.boxplot(by='column1') 进行分组,这似乎与您的示例不兼容。您有什么建议吗?我的箱线图是 x 轴 df[column1],y 轴 df[column2],我想在其上绘制散点图。但由于 xticks 设置为文本,我感到困惑。我能够找到 boxplot 设置的 xticks 和 xtick_labels。 - CRogers

0

我有以下技巧:

data = np.random.randn(6,5)

df = pd.DataFrame(data,columns = list('ABCDE'))

Now assign a dummy column to df:
df['Group'] = 'A'

print df

          A         B         C         D         E Group
0  0.590600  0.226287  1.552091 -1.722084  0.459262     A
1  0.369391 -0.037151  0.136172 -0.772484  1.143328     A
2  1.147314 -0.883715 -0.444182 -1.294227  1.503786     A
3 -0.721351  0.358747  0.323395  0.165267 -1.412939     A
4 -1.757362 -0.271141  0.881554  1.229962  2.526487     A
5 -0.006882  1.503691  0.587047  0.142334  0.516781     A

使用 df.groupby.boxplot(),你就可以完成它。
df.groupby('Group').boxplot()

Box plot overlay


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接