我打算在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
选项的内容:
然而,如果我使用一个列进行此操作,那么感谢另一个SO问题Seaborn groupby pandas Series:
sns.boxplot(df.a1, groupby=df.b)
所以我想在一个图中得到我的所有列(所有列都以相似的比例)。
编辑:
上面的SO问题已被编辑,现在包含了一个“不干净”的问题答案,但如果有人对此问题有更好的了解,那就太好了。
答案 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")
答案 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')
答案 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])
它给出:
请注意,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)