Seaborn groupby pandas系列

时间:2014-08-13 06:51:46

标签: matplotlib pandas seaborn

我希望将我的数据可视化为箱形图,这些图表按照我可怕的图纸中显示的另一个变量分组:

enter image description here

所以我所做的就是使用pandas系列变量告诉pandas我已经对变量进行了分组,这就是我所做的:

import pandas as pd
import seaborn as sns
#example data for reproduciblity
a = pd.DataFrame(
[
[2, 1],
[4, 2],
[5, 1],
[10, 2],
[9, 2],
[3, 1]
])

#converting second column to Series 
a.ix[:,1] = pd.Series(a.ix[:,1])
#Plotting by seaborn
sns.boxplot(a, groupby=a.ix[:,1])

这就是我得到的:

seaborn plot

然而,我原本期望获得的是两个箱图,每个箱图仅描述第一列,按第二列中的相应列(转换为系列的列)分组,而上图则分别显示每列不是我想要的。

3 个答案:

答案 0 :(得分:7)

Dataframe中的列已经是Series,因此无需进行转换。此外,如果您只想对两个箱图使用第一列,则只应将其传递给Seaborn。

所以:

#example data for reproduciblity
df = pd.DataFrame(
[
[2, 1],
[4, 2],
[5, 1],
[10, 2],
[9, 2],
[3, 1]
], columns=['a', 'b'])

#Plotting by seaborn
sns.boxplot(df.a, groupby=df.b)

我稍微改变了你的例子,给我一些标签让我觉得它更清晰。

enter image description here

编辑:

如果您想分别绘制所有列,我(我认为)基本上需要groupby列和任何其他列中所有值的组合。所以如果你Dataframe看起来像这样:

    a   b  grouper
0   2   5        1
1   4   9        2
2   5   3        1
3  10   6        2
4   9   7        2
5   3  11        1

您想要列ab的箱图,同时按列grouper进行分组。您应该展平列并更改groupby列以包含a1a2b1等值。

考虑到上面显示的Dataframe,我认为这是一种粗略的方法:

dfpiv = df.pivot(index=df.index, columns='grouper')

cols_flat = [dfpiv.columns.levels[0][i] + str(dfpiv.columns.levels[1][j]) for i, j in zip(dfpiv.columns.labels[0], dfpiv.columns.labels[1])]  
dfpiv.columns = cols_flat
dfpiv = dfpiv.stack(0)

sns.boxplot(dfpiv, groupby=dfpiv.index.get_level_values(1))

enter image description here

也许有更多奇特的方法来重组Dataframe。特别是旋转后层次的扁平化很难读,我不喜欢它。

答案 1 :(得分:1)

这是一个旧问题的新答案,因为在 seabornpandas 中是通过版本更新进行的一些更改。由于这种变化,Rutger 的答案不再有效。

最重要的变化是从 seaborn==v0.5.xseaborn==v0.6.0。我引用日志:

<块引用>

boxplot()violinplot() 的更改可能是最具破坏性的。这两个函数在它们可以接受的数据类型方面保持向后兼容性,但语法已更改为与其他 seaborn 函数更相似。现在使用 x 和/或 y 参数调用这些函数,这些参数是传递给新数据参数的长格式 DataFrame 中的数据向量或变量名称。

现在让我们来看看例子:

# preamble
import pandas as pd # version 1.1.4
import seaborn as sns # version 0.11.0
sns.set_theme()

示例 1:简单箱线图

df = pd.DataFrame([[2, 1] ,[4, 2],[5, 1],
                   [10, 2],[9, 2],[3, 1]
                  ], columns=['a', 'b'])

#Plotting by seaborn with x and y as parameter
sns.boxplot(x='b', y='a', data=df)

simple boxplot

示例 2:带石斑鱼的箱线图

df = pd.DataFrame([[2, 5, 1], [4, 9, 2],[5, 3, 1],
                   [10, 6, 2],[9, 7, 2],[3, 11, 1]
                  ], columns=['a', 'b', 'grouper'])
# usinge pandas melt
df_long = pd.melt(df, "grouper", var_name='a', value_name='b')
# join two columns together
df_long['a'] = df_long['a'].astype(str) + df_long['grouper'].astype(str)
sns.boxplot(x='a', y='b', data=df_long)

boxplot after melt

示例3:重新排列DataFrame传递直接给seaborn

def df_rename_by_group(data:pd.DataFrame, col:str)->pd.DataFrame:
    '''This function takes a DataFrame, groups by one column and returns 
       a new DataFrame where the old columnnames are extended by the group item. 
    '''
    grouper = df.groupby(col)
    max_length_of_group = max([len(values) for item, values in grouper.indices.items()])
    _df = pd.DataFrame(index=range(max_length_of_group))
    for i in grouper.groups.keys():
        helper = grouper.get_group(i).drop(col, axis=1).add_suffix(str(i))
        helper.reset_index(drop=True, inplace=True)
        _df = _df.join(helper)
    return _df

df = pd.DataFrame([[2, 5, 1], [4, 9, 2],[5, 3, 1],
                   [10, 6, 2],[9, 7, 2],[3, 11, 1]
                  ], columns=['a', 'b', 'grouper'])
df_new = df_rename_by_group(data=df, col='grouper')
sns.boxplot(data=df_new)

boxplot of rearanged data

我真的希望这个答案有助于避免一些混乱。

答案 2 :(得分:0)

sns.boxplot() 不接受 groupby。 也许你会看到
TypeError: boxplot() got an unexpected keyword argument 'groupby'.

对数据进行分组并在箱线图中使用的最佳方法是将数据作为 groupby 数据框值传递。

import seaborn as sns
grouDataFrame = nameDataFrame(['A'])['B'].agg(sum).reset_index()
sns.boxplot(y='B', x='A', data=grouDataFrame)

此处 B 列数据包含数值并在 A 的基础上进行分组。添加所有分组值及其各自的列并绘制箱线图。希望这会有所帮助。