Matplotlib 输入为数据帧时seaborn中的分组箱线图

Matplotlib 输入为数据帧时seaborn中的分组箱线图,matplotlib,pandas,seaborn,Matplotlib,Pandas,Seaborn,我打算在pandas数据框中绘制多个列,所有列都使用groupbyinsideseaborn.boxplot按另一列分组。对于matplotlib中的类似问题,这里有一个很好的答案,但鉴于seaborn.boxplot带有groupby选项,我认为在seaborn中这样做可能会容易得多 这里我们使用一个失败的可重复示例: import seaborn as sns import pandas as pd df = pd.DataFrame( [ [2, 4, 5, 6, 1], [4, 5, 6

我打算在
pandas数据框中绘制多个列,所有列都使用
groupby
inside
seaborn.boxplot
按另一列分组。对于
matplotlib
中的类似问题,这里有一个很好的答案,但鉴于
seaborn.boxplot
带有
groupby
选项,我认为在
seaborn
中这样做可能会容易得多

这里我们使用一个失败的可重复示例:

import seaborn as sns
import pandas as pd
df = pd.DataFrame(
[
[2, 4, 5, 6, 1],
[4, 5, 6, 7, 2],
[5, 4, 5, 5, 1],
[10, 4, 7, 8, 2],
[9, 3, 4, 6, 2],
[3, 3, 4, 4, 1]
], columns=['a1', 'a2', 'a3', 'a4', 'b'])

#Plotting by seaborn
sns.boxplot(df[['a1','a2', 'a3', 'a4']], groupby=df.b)
我得到的结果是完全忽略了
groupby
选项:

然而,如果我用一个专栏来做这件事,那要感谢另一个问题:

所以我想把我所有的栏都放在一个图中(所有的栏都有相似的比例)

编辑:


上面的问题经过编辑,现在包含了这个问题的“不干净”答案,但如果有人对这个问题有更好的想法,那就太好了

这实际上并不比您链接的答案好多少,但我认为在seaborn中实现这一点的方法是使用该功能,因为groupby参数仅为传递给boxplot函数的序列定义

这里有一些代码,
pd.melt
是必需的,因为(我能说的最好)刻面映射只能将单个列作为参数,所以需要将数据转换为“长”格式

g = sns.FacetGrid(pd.melt(df, id_vars='b'), col='b')
g.map(sns.boxplot, 'value', 'variable')

Seaborn的groupby函数接受的是序列而不是数据帧,这就是它不起作用的原因

作为解决方法,您可以执行以下操作:

fig, ax = plt.subplots(1,2, sharey=True)
for i, grp in enumerate(df.filter(regex="a").groupby(by=df.b)):
    sns.boxplot(grp[1], ax=ax[i])
它给出:

请注意,
df.filter(regex=“a”)
相当于
df[['a1'、'a2'、'a3'、'a4']]

   a1  a2  a3  a4
0   2   4   5   6
1   4   5   6   7
2   5   4   5   5
3  10   4   7   8
4   9   3   4   6
5   3   3   4   4

希望这有帮助

正如其他答案所指出的那样,
箱线图
功能仅限于绘制一个单一的箱线图“层”,而
groupby
参数仅在输入是一个系列并且您有第二个变量要用于将观察结果存储到每个框中时才有效

但是,您可以使用
kind=“box”
使用
factorplot
函数实现我认为您希望的功能。但是,您首先必须将示例数据帧“融化”为所谓的长格式或“整洁”格式,其中每列是一个变量,每行是一个观察值:

df_long = pd.melt(df, "b", var_name="a", value_name="c")
然后很容易绘制:

sns.factorplot("a", hue="b", y="c", data=df_long, kind="box")

您可以直接使用
boxplot
(我想当有人问这个问题时,这是不可能的,但是使用
seaborn
version>0.6就可以了)

正如@mwaskom所解释的,您必须将样本数据帧“融化”为其“长形式”,其中每列是一个变量,每行是一个观察值:

df_long = pd.melt(df, "b", var_name="a", value_name="c")
然后你只要画出来:

sns.boxplot(x="a", hue="b", y="c", data=df_long)

谢谢,我接受了下面的答案,因为它在一个图中给出了所有的图。实际上没有必要直接使用
FaceGrid
如果你想要这种图,你也可以在这里使用
factorplot
col=b
。(这并没有错,只是做的工作比必要的要多。)这偶尔会得到提升票,但FWIW嵌套箱线图在
sns中是可能的。箱线图
从0.6开始就出现了。这种
melt
是疯狂和出人意料的
sns.boxplot(x="a", hue="b", y="c", data=df_long)