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

Why does DataFrameGroupBy.boxplot method throw error when given argument "subplots=True/False"?

我可以使用 DataFrameGroupBy.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()

这将生成以下图像:

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

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

但它产生了错误

KeyError: 'gene_id'

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

要使用纯 pandas 函数,我认为您不应该在调用 boxplot 之前 GroupBy,而是请求在调用 [=16] 时按某些列分组=] 在 DataFrame 本身:

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

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

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

编辑 以考虑下面的评论 如果你想为每个 gene_id 绘制你的队列箱线图 stacked/superimposed,那就有点复杂了(而且你最终可能会得到非常难看的输出)。您不能使用 Seaborn,AFAIK 来执行此操作,但您可以直接使用 pandas,通过将 position= 参数用于箱线图 (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)

另一种方法是使用 seaborn.swarmplot 而不是箱线图。 swarmplot 绘制每个点而不是箱线图的综合表示,但您可以使用参数 split=False 来获取按群组着色的点,但每个 gene_id.[=28= 堆叠在彼此之上]

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

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