为什么DataFrameGroupBy.boxplot方法在给定参数“subplots = True / False”时抛出错误?

时间:2017-05-04 20:07:18

标签: pandas matplotlib dataframe boxplot

我可以使用DataFrameGroupBy.boxplot(...)以下列方式创建一个boxplot:

In [15]: df = pd.DataFrame({"gene_length":[100,100,100,200,200,200,300,300,300],
...:                        "gene_id":[1,1,1,2,2,2,3,3,3],
...:                        "density":[0.4,1.1,1.2,1.9,2.0,2.5,2.2,3.0,3.3],
...:                        "cohort":["USA","EUR","FIJ","USA","EUR","FIJ","USA","EUR","FIJ"]})

In [17]: df.groupby("cohort").boxplot(column="density",by="gene_id")

In [18]: plt.show()

这会产生以下图像: enter image description here

这正是我想要的,除了不是制作三个子图,我希望所有的图都在一个图中(美国,欧元和FIJ的颜色不同)。我试过了

In [17]: df.groupby("cohort").boxplot(column="density",subplots=False,by="gene_id")

但它会产生错误

KeyError: 'gene_id'

我认为问题与by="gene_id"是发送到matplotlib boxplot方法的关键字这一事实有关。如果有人有更好的方法来制作我想要的情节,可能是使用DataFrame.boxplot(?)代替,请在这里回复。非常感谢!

1 个答案:

答案 0 :(得分:2)

要使用纯pandas函数,我认为您在调用GroupBy之前不应该boxplot,而是请求通过调用boxplot中的某些列进行分组在DataFrame本身:

df.boxplot(column='density',by=['gene_id','cohort'])

enter image description here

要获得更好看的结果,您可能需要考虑使用Seaborn库。它旨在准确地帮助完成这类任务:

sns.boxplot(data=df,x='gene_id',y='density',hue='cohort')

enter image description here

编辑以考虑以下评论 如果你想为每个gene_id堆叠/叠加你的每个群组箱图,那就更复杂了(加上你可能会得到相当丑陋的输出)。你不能使用Seaborn,AFAIK这样做,但是你可以直接使用pandas,使用position=参数来设置boxplot(see doc)。捕获它以生成正确的位置序列以将箱形图放置在您想要的位置,但您必须自己修复刻度标签和图例。

pos = [i for i in range(len(df.gene_id.unique())) for _ in range(len(df.cohort.unique()))]
df.boxplot(column='density',by=['gene_id','cohort'],positions=pos)

enter image description here

另一种方法是使用seaborn.swarmplot而不是使用boxplot。 swarmplot绘制每个点而不是箱形图的合成表示,但是您可以使用参数split=False来获得由群组着色的点,但是每个gene_id都堆叠在一起。

sns.swarmplot(data=df,x='gene_id',y='density',hue='cohort', split=False)

enter image description here

在不知道数据框的实际内容(每个基因和每个群组的点数,以及它们在每个群组中的分离程度)的情况下,很难说哪种解决方案最合适。