python - 如何为条形图添加组标签

标签 python matplotlib bar-chart

我想绘制以下形式的数据,使用 matplotlib 条形图:

data = {'Room A':
           {'Shelf 1':
               {'Milk': 10,
                'Water': 20},
            'Shelf 2':
               {'Sugar': 5,
                'Honey': 6}
           },
        'Room B':
           {'Shelf 1':
               {'Wheat': 4,
                'Corn': 7},
            'Shelf 2':
               {'Chicken': 2,
                'Cow': 1}
           }
       }

条形图应该是这样的

like this

从 x 轴上的标签应该可以看到条形组。有没有办法用 matplotlib 做到这一点?

最佳答案

由于我在 matplotlib 中找不到内置解决方案,因此我编写了自己的代码:

#!/usr/bin/env python

from matplotlib import pyplot as plt

def mk_groups(data):
    try:
        newdata = data.items()
    except:
        return

    thisgroup = []
    groups = []
    for key, value in newdata:
        newgroups = mk_groups(value)
        if newgroups is None:
            thisgroup.append((key, value))
        else:
            thisgroup.append((key, len(newgroups[-1])))
            if groups:
                groups = [g + n for n, g in zip(newgroups, groups)]
            else:
                groups = newgroups
    return [thisgroup] + groups

def add_line(ax, xpos, ypos):
    line = plt.Line2D([xpos, xpos], [ypos + .1, ypos],
                      transform=ax.transAxes, color='black')
    line.set_clip_on(False)
    ax.add_line(line)

def label_group_bar(ax, data):
    groups = mk_groups(data)
    xy = groups.pop()
    x, y = zip(*xy)
    ly = len(y)
    xticks = range(1, ly + 1)

    ax.bar(xticks, y, align='center')
    ax.set_xticks(xticks)
    ax.set_xticklabels(x)
    ax.set_xlim(.5, ly + .5)
    ax.yaxis.grid(True)

    scale = 1. / ly
    for pos in xrange(ly + 1):  # change xrange to range for python3
        add_line(ax, pos * scale, -.1)
    ypos = -.2
    while groups:
        group = groups.pop()
        pos = 0
        for label, rpos in group:
            lxpos = (pos + .5 * rpos) * scale
            ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes)
            add_line(ax, pos * scale, ypos)
            pos += rpos
        add_line(ax, pos * scale, ypos)
        ypos -= .1

if __name__ == '__main__':
    data = {'Room A':
               {'Shelf 1':
                   {'Milk': 10,
                    'Water': 20},
                'Shelf 2':
                   {'Sugar': 5,
                    'Honey': 6}
               },
            'Room B':
               {'Shelf 1':
                   {'Wheat': 4,
                    'Corn': 7},
                'Shelf 2':
                   {'Chicken': 2,
                    'Cow': 1}
               }
           }
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    label_group_bar(ax, data)
    fig.subplots_adjust(bottom=0.3)
    fig.savefig('label_group_bar_example.png')

mk_groups 函数接受一个字典(或任何带有 items() 方法的东西,例如 collections.OrderedDict)并将其转换为数据格式,然后用于创建图表。它基本上是一个列表形式:

[ [(label, bars_to_span), ...], ..., [(tick_label, bar_value), ...] ]

add_line 函数在子图中的指定位置(在坐标轴坐标中)创建一条垂直线。

label_group_bar 函数采用字典并在子图中创建条形图,其下方带有标签。该示例的结果看起来是 like this .

仍然非常感谢更简单或更好的解决方案和建议。

bar chart with groups

关于python - 如何为条形图添加组标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19184484/

相关文章:

r - 将 x 轴设置为与 y 轴在 0 处与点阵相交

python - Python 3.5.2 中的本福德定律绘图

python - 存在哪些基于 Python 的仪表板选项?

python - 我无法在 Linux 中终止我的 Python 脚本

python - pip 安装 matplotlib : "no pkg-config"

python - 使用 matplotlib 从纪元开始绘制 time() 的日期

java - 动态更新 JavaFX BarChart

python - 无法在 mac OS X mountain lion 上导入 numpy

python - 具有 shutil 模块的最低版本的 Python 是什么?

python - 如何让 grabCut 与 GC_INIT_WITH_MASK 一起工作 opencv python