如何在matplotlib中为条形图添加组标签? [英] How to add group labels for bar charts in matplotlib?

查看:93
本文介绍了如何在matplotlib中为条形图添加组标签?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to plot data of the following form using matplotlib's bar plot feature:

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

条形图应该看起来像类似.条形组应从x轴上的标签可见.使用matplotlib有什么办法吗?

The bar chart is supposed to look like this. The bar groups should be visible from the labels on the x axis. Is there any way to do this with matplotlib?

推荐答案

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

Since I could not find a built-in solution for this in matplotlib, I coded my own:

#!/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):
        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)并将其转换为数据格式,该数据格式随后用于创建图表.它基本上是以下形式的列表:

The "mk_groups" function takes a dictionary (or anything with an items() method, like collections.OrderedDict) and converts it to a data format that is then used to create the chart. It is basically a list of the form:

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

"add_line"功能在子图中指定位置(在轴坐标中)创建一条垂直线.

The "add_line" function creates a vertical line in the subplot at the specified positions (in axes coordinates).

"label_group_bar"函数使用一个词典,并在子图中创建带有下面标签的条形图.然后,示例的结果看起来像这样的 .

The "label_group_bar" function takes a dictionary and creates the bar chart in the subplot with the labels beneath. The result from the example then looks like this.

更容易或更好的解决方案和建议仍然受到人们的赞赏.

Easier or better solutions and suggestions are still very much appreciated.

这篇关于如何在matplotlib中为条形图添加组标签?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆