当输入是DataFrame时,在seaborn中对boxmap进行分组

时间:2014-08-13 11:24:00

标签: matplotlib pandas seaborn

我打算在pandas dataframe中绘制多个列,所有列都使用groupby内的seaborn.boxplot按另一列进行分组。这里有一个很好的答案,对于matplotlib matplotlib: Group boxplots中的类似问题,但考虑到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选项的内容:

Failed groupby

然而,如果我使用一个列进行此操作,那么感谢另一个SO问题Seaborn groupby pandas Series

sns.boxplot(df.a1, groupby=df.b)

seaborn that does not fail

所以我想在一个图中得到我的所有列(所有列都以相似的比例)。

编辑:

上面的SO问题已被编辑,现在包含了一个“不干净”的问题答案,但如果有人对此问题有更好的了解,那就太好了。

4 个答案:

答案 0 :(得分:24)

正如其他答案所指出的那样,boxplot功能仅限于绘制单个“图层”的箱图,groupby参数仅在输入为系列且您有一个效果时才有效您想要用于将观察结果分成每个框的第二个变量..

但是,使用factorplot,您可以使用kind="box"函数完成我认为您希望的内容。但是,您首先必须将示例数据框“融化”为所谓的长格式或“整齐”格式,其中每列都是变量,每行都是一个观察点:

df_long = pd.melt(df, "b", var_name="a", value_name="c")

然后绘制非常简单:

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

enter image description here

答案 1 :(得分:4)

这并不比你链接的答案好,但我认为在seaborn中实现这一目标的方法是使用FacetGrid功能,因为groupby参数仅定义为传递给boxplot函数的Series

这是一些代码 - pd.melt是必要的,因为(尽我所知)构面映射只能将单个列作为参数,因此需要将数据转换为“长”格式。

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

faceted seaborn boxplot

答案 2 :(得分:4)

Seaborn的groupby函数采用Series而不是DataFrames,这就是它无法正常工作的原因。

作为一种解决方法,你可以这样做:

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])

它给出:sns

请注意,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

希望这有帮助

答案 3 :(得分:1)

您可以直接使用boxplot(我想问这个问题是不可能的,但是seaborn版本> 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)

plot obtained with boxplot