Pandas:如何绘制一个有两个类别和四个系列的条形图?

Posted

技术标签:

【中文标题】Pandas:如何绘制一个有两个类别和四个系列的条形图?【英文标题】:Pandas: how to draw a bar plot with two categories and four series each? 【发布时间】:2017-02-08 01:07:00 【问题描述】:

我有以下数据框,其中pd.concat 已用于对列进行分组:

    a               b            
   C1  C2  C3  C4  C5  C6  C7  C8
0  15  37  17  10   8  11  19  86
1  39  84  11   5   5  13   9  11
2  10  20  30  51  74  62  56  58
3  88   2   1   3   9   6   0  17
4  17  17  32  24  91  45  63  48

现在我想绘制一个条形图,其中我只有两个类别(ab),每个类别有四个条形图代表每列的平均值。 C1 和 C5 列应具有相同的颜色,C2 和 C6 列也应具有相同的颜色,以此类推。

我怎样才能用 df.plot.bar() 做到这一点?

绘图应类似于下图。很抱歉它是手绘的,但我很难找到一个相关的例子:

编辑

这是我的实际 DataFrame 的标题:

    C1  C2  C3  C4  C5  C6  C7  C8
0   34  34  34  34  6   40  13  26
1   19  19  19  19  5   27  12  15
2   100 100 100 100 0   0   0   0
3   0   0   0   0   0   0   0   0
4   100 100 100 100 0   0   0   0

【问题讨论】:

我希望更多的人能手绘出他们想要的情节。 @CF84,条形图上的注释是所需情节的一部分还是仅用于演示目的? 您的意思是“红色”和“蓝色”之类的东西?这些仅用于演示,C1-C8 也是如此。 【参考方案1】:

您可以在计算DFmean 后简单地执行unstack 以呈现条形图。

import seaborn as sns
sns.set_style('white')

#color=0.75(grey)
df.mean().unstack().plot.bar(color=list('rbg')+['0.75'], rot=0, figsize=(8,8)) 


数据:(根据编辑后的帖子)

df

准备多索引DF,通过根据列的选择重复标签创建一个额外的列(这里,4)。

df_multi_col = df.T.reset_index()
df_multi_col['labels'] = np.concatenate((np.repeat('A', 4), np.repeat('B', 4)))
df_multi_col.set_index(['labels', 'index'], inplace=True)
df_multi_col

df_multi_col.mean(1).unstack().plot.bar(color=list('rbg')+['0.75'], rot=0, figsize=(6,6), width=2)

【讨论】:

如何删除那些竖线? 你是说网格线?这些只是使用的情节的风格。我会更新它以显示没有它们。 谢谢!你能把这两个类别在情节中拉近一点吗? 提供 arg width=1(或更大)。它们会显得更近。 哇,我收到一个错误:AttributeError: 'Index' object has no attribute 'labels' 指向 df.mean().unstack().plot.bar(color=list('rbg')+['0.75'], rot=0, figsize=(8,8)) 。为什么?【参考方案2】:

试试seaborn

import seaborn as sns
import pandas as pd

def r(df):
    return df.loc[df.name].reset_index(drop=True)

data = df.mean().groupby(level=0).apply(r) \
         .rename_axis(['grp', 'cat']).reset_index(name='mu')

ax = sns.barplot(x='grp', y='mu', hue='cat', data=data)

ax.legend_.remove()
for i, p in enumerate(ax.patches):
    height = p.get_height()
    ax.text(p.get_x() + .05, height + 1, df.columns.levels[1][i])

【讨论】:

df.loc[df.name] 中的name 指的是什么?还有,整条线的作用是什么? groupby 中使用 apply 时,组标识符通过 name 属性传递给 apply 函数。 df.loc[df.name] 正在获取该组 ID 的横截面。 无论如何,我得到这个错误:AttributeError: 'numpy.float64' object has no attribute 'reset_index',它指向定义data 的行。

以上是关于Pandas:如何绘制一个有两个类别和四个系列的条形图?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Pandas 在同一图中绘制分组数据

JSP系列:JSP进阶-九大内置对象和四个域对象

针对不同类别的其他列 pandas 和 seaborn 或 matplotlib 的 Groupby 逐年绘制

pandas:选择索引,然后选择多索引切片上的列

如何在 Pandas 中按子类别分组? [复制]

Pandas 多个时间序列绘制单个数据帧