Python 更高效的 matplotlib 堆积条形图 - 如何计算底部值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19060144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
More efficient matplotlib stacked bar chart - how to calculate bottom values
提问by 2705114-john
I need some help making a set of stacked bar charts in python with matlibplot. My basic code is below but my problems is how to generate the value for bottomfor any element beyond the 2nd one efficiently. I can get the example graph to stack correctly (always a,b,c,d from bottom to top)
我需要一些帮助在 python 中使用 matlibplot 制作一组堆积条形图。我的基本代码如下,但我的问题是如何有效地为第二个元素以外的任何元素生成底部的值。我可以让示例图正确堆叠(从下到上总是 a,b,c,d)
import numpy as np
import matplotlib.pyplot as plt
ind = np.arange(3)
a = [3,6,9]
b = [2,7,1]
c = [0,3,1]
d = [4,0,3]
p1 = plt.bar(ind, a, 1, color='#ff3333')
p2 = plt.bar(ind, b, 1, color='#33ff33', bottom=a)
p3 = plt.bar(ind, c, 1, color='#3333ff', bottom=[a[j] +b[j] for j in range(len(a))])
p4 = plt.bar(ind, d, 1, color='#33ffff', bottom=[a[j] +b[j] +c[j] for j in range(len(a))])
plt.show()
My final code could have very large number of bars and the ever expanding function bottom = [...] cannot be the best solution. It would be great if you could also explain how I need to derive the value. Is there a numpy function.
我的最终代码可能有非常多的条形,而且不断扩展的函数 bottom = [...] 不可能是最好的解决方案。如果您还可以解释我需要如何得出价值,那就太好了。是否有 numpy 功能。
Thank you very much!!! PS I have searched for an answer but I did not understand what I could find.
非常感谢!!!PS我已经搜索了答案,但我不明白我能找到什么。
采纳答案by minillinim
I have just recently faced the same problem. Afterwards I decided to wrap it all up in a nice class. For anyone interested you get an implementation of a stacked bar graph class here:
我最近遇到了同样的问题。后来我决定把这一切都放在一个不错的班级里。对于任何感兴趣的人,您都可以在此处获得堆叠条形图类的实现:
https://github.com/minillinim/stackedBarGraph
https://github.com/minillinim/stackedBarGraph
It allows scaled stacked graphs as well as setting bar widths and set heights (with scaled inners).
它允许缩放堆叠图形以及设置条形宽度和设置高度(带有缩放的内部)。
Given a data set like this:
给定这样的数据集:
d = np.array([[101.,0.,0.,0.,0.,0.,0.],
[92.,3.,0.,4.,5.,6.,0.],
[56.,7.,8.,9.,23.,4.,5.],
[81.,2.,4.,5.,32.,33.,4.],
[0.,45.,2.,3.,45.,67.,8.],
[99.,5.,0.,0.,0.,43.,56.]])
d_heights = [1.,2.,3.,4.,5.,6.]
d_widths = [.5,1.,3.,2.,1.,2.]
d_labels = ["fred","julie","sam","peter","rob","baz"]
d_colors = ['#2166ac',
'#fee090',
'#fdbb84',
'#fc8d59',
'#e34a33',
'#b30000',
'#777777']
It can make images like this:
它可以制作这样的图像:
GPLv3 with love.
GPLv3 充满爱。
回答by Veedrac
[sum(values) for values in zip(a, b, c)]
In Python 2 you can also do
在 Python 2 中你也可以做
map(sum, zip(a, b, c))
but Python 3 would need
但是 Python 3 需要
list(map(sum, zip(a, b, c)))
which is less nice.
这不太好。
You could encapsulate this:
你可以封装这个:
def sumzip(*items):
return [sum(values) for values in zip(*items)]
and then do
然后做
p1 = plt.bar(ind, a, 1, color='#ff3333')
p2 = plt.bar(ind, b, 1, color='#33ff33', bottom=sumzip(a))
p3 = plt.bar(ind, c, 1, color='#3333ff', bottom=sumzip(a, b))
p4 = plt.bar(ind, d, 1, color='#33ffff', bottom=sumzip(a, b, c))
too.
也。
If a
, b
, c
and d
are numpy arrays you can also do sum([a, b, c])
:
如果a
,b
,c
并且d
是numpy的阵列,你也可以做sum([a, b, c])
:
a = np.array([3,6,9])
b = np.array([2,7,1])
c = np.array([0,3,1])
d = np.array([4,0,3])
p1 = plt.bar(ind, a, 1, color='#ff3333')
p2 = plt.bar(ind, b, 1, color='#33ff33', bottom=sum([a]))
p3 = plt.bar(ind, c, 1, color='#3333ff', bottom=sum([a, b]))
p4 = plt.bar(ind, d, 1, color='#33ffff', bottom=sum([a, b, c]))
回答by Jaime
Converting your values to numpy arrays will make your life easier:
将您的值转换为 numpy 数组将使您的生活更轻松:
data = np.array([a, b, c, d])
bottom = np.cumsum(data, axis=0)
colors = ('#ff3333', '#33ff33', '#3333ff', '#33ffff')
plt.bar(ind, data[0], color=colors[0])
for j in xrange(1, data.shape[0]):
plt.bar(ind, data[1], color=colors[j], bottom=bottom[i-1])
Alternatively, to get rid of the nasty particular case for the first bar:
或者,要摆脱第一个酒吧的讨厌的特殊情况:
data = np.array([a, b, c, d])
bottom = np.vstack((np.zeros((data.shape[1],), dtype=data.dtype),
np.cumsum(data, axis=0)[:-1]))
colors = ('#ff3333', '#33ff33', '#3333ff', '#33ffff')
for dat, col, bot in zip(data, colors, bottom):
plt.bar(ind, dat, color=col, bottom=bot)
回答by Zelphir Kaltstahl
I solved it like this:
我是这样解决的:
import numpy as np
dates = # somehow get a list of dates
labels = # a list of various labels
colors = # somehow get a list of colors
margin_bottom = np.zeros(dates)
for index, label in enumerate(labels):
values = # get your values for the label at index-th position from somewhere
ax.bar(
dates, values,
align='center', label=label, color=colors[index], bottom=margin_bottom
)
margin_bottom += values # here you simply add it to the previous margin
# margin_bottom is a numpy array, adding a list will not change that
It's similar to some other solutions, but it doesn't require all of the margins being stored at all time. Instead it "builds" the stacks from bottom up, adding more and more margin with each iteration.
它类似于其他一些解决方案,但它不需要一直存储所有边距。相反,它自下而上“构建”堆栈,每次迭代增加越来越多的余量。