4

我想将我的数据可视化为由我可怕的绘图中显示的另一个变量分组的箱形图:

在此处输入图像描述

所以我要做的是使用 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])

这就是我得到的:

海生情节

但是,我期望得到的是有两个箱线图,每个箱线图仅描述第一列,按第二列中的相应列(转换为系列的列)分组,而上面的图分别显示了每一列,这不是我想。

4

3 回答 3

7

a 中的一列Dataframe已经是 a 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)

我稍微改变了你的例子,在我看来给列一个标签让它更清楚一点。

在此处输入图像描述

编辑:

如果你想单独绘制所有列,你(我认为)基本上想要你的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

并且您需要列的箱线图a并按列b分组grouper。您应该展平列并将 groupby 列更改为包含a1,等值a2b1

鉴于上面显示的数据框,这是一种我认为应该可行的粗略方式:

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

在此处输入图像描述

也许还有更多奇特的重组方式Dataframe。尤其是旋转后层次结构的扁平化很难阅读,我不喜欢它。

于 2014-08-13T09:17:30.103 回答
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)

简单的箱线图

示例 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)

融化后的箱线图

示例 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)

重新排列数据的箱线图

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

于 2021-01-16T10:54:49.687 回答
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的基础上进行分组。将所有分组值及其各自的列添加并绘制箱线图。希望这可以帮助。

于 2021-01-15T16:07:55.440 回答