我想使用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}
}
}
条形图应该看起来像这样。条形组应从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):
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
函数将使用字典并在子图中创建条形图,并在其下方添加标签。该示例的结果将如下所示。
更容易或更好的解决方案和建议仍然受到高度赞赏。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句