Arm*_*man 20 matplotlib pandas seaborn
我打算在a中绘制多个列pandas dataframe,所有列都使用groupbyinside在另一列中进行分组seaborn.boxplot.这里有一个很好的答案,对于matplotlib 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)
Run Code Online (Sandbox Code Playgroud)
我得到的是完全忽略groupby选项的东西:

然而,如果我用一个专栏做这个,它的工作得益于另一个SO问题Seaborn groupby pandas系列:
sns.boxplot(df.a1, groupby=df.b)
Run Code Online (Sandbox Code Playgroud)

所以我想在一个图中得到我的所有列(所有列都以相似的比例).
编辑:
上面的SO问题已被编辑,现在包含了一个"不干净"的问题答案,但如果有人对这个问题有更好的了解,那就太好了.
mwa*_*kom 24
正如其他答案所指出的那样,该boxplot功能仅限于绘制单个"图层"箱形图,并且该groupby参数仅在输入为系列时才有效,并且您有第二个变量要用于将观察结果插入每个框中..
但是,您可以使用该factorplot功能完成我认为您希望使用的功能kind="box".但是,您首先必须将样本数据框"融化"为所谓的长格式或"整齐"格式,其中每列都是变量,每行都是一个观察点:
df_long = pd.melt(df, "b", var_name="a", value_name="c")
Run Code Online (Sandbox Code Playgroud)
然后绘制非常简单:
sns.factorplot("a", hue="b", y="c", data=df_long, kind="box")
Run Code Online (Sandbox Code Playgroud)

MrT*_*T77 11
您可以直接使用sns.boxplot轴级函数 或sns.catplotwithkind='box'图形级函数。有关更多详细信息,请参阅图形级函数与轴级函数
sns.catplot具有col和row变量,用于使用不同的变量创建子图/方面。
默认值palette由传递给 的变量类型(连续(数字)或分类)确定hue。
正如@mwaskom 所解释的,您必须将melt示例数据帧转换为“长格式”,其中每列都是一个变量,每行都是一个观察值。
测试于python 3.12.0, pandas 2.1.2, matplotlib 3.8.1,seaborn 0.13.0
df_long = pd.melt(df, "b", var_name="a", value_name="c")
# display(df_long.head())
b a c
0 1 a1 2
1 2 a1 4
2 1 a1 5
3 2 a1 10
4 2 a1 9
Run Code Online (Sandbox Code Playgroud)
sns.boxplotfig, ax = plt.subplots(figsize=(5, 5))
sns.boxplot(x="a", hue="b", y="c", data=df_long, ax=ax)
ax.spines[['top', 'right']].set_visible(False)
sns.move_legend(ax, bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)
Run Code Online (Sandbox Code Playgroud)
sns.catplotsns.boxplot使用更少的代码行创建相同的绘图。
g = sns.catplot(kind='box', data=df_long, x='a', y='c', hue='b', height=5, aspect=1)
Run Code Online (Sandbox Code Playgroud)
它实际上并不比您链接的答案更好,但我认为在 seaborn 中实现此目的的方法是使用该功能FacetGrid,因为 groupby 参数仅为传递给 boxplot 函数的 Series 定义。
这是一些代码 - 这pd.melt是必要的,因为(据我所知)构面映射只能将单个列作为参数,因此数据需要转换为“长”格式。
g = sns.FacetGrid(pd.melt(df, id_vars='b'), col='b')
g.map(sns.boxplot, 'value', 'variable')
Run Code Online (Sandbox Code Playgroud)

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])
Run Code Online (Sandbox Code Playgroud)
它给 : 
请注意,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
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助
| 归档时间: |
|
| 查看次数: |
23418 次 |
| 最近记录: |