通过Python的Matplotlib将3个柱状图叠加在一起
我想制作一个堆叠柱状图,里面有3根柱子叠在一起。我已经成功做了2根柱子的堆叠,但我不知道怎么加第3根柱子,有什么好主意吗?
我会加一些简单的示例代码来说明我的意思:
from matplotlib import pyplot as plt
data1 = [100,120,140]
data2 = [150,120,190]
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))
## Absolute count
ax1.bar(range(len(data1)), data1, label='data 1', alpha=0.5, color='b')
ax1.bar(range(len(data2)), data2, bottom=data1, label='data 2', alpha=0.5, color='r')
plt.sca(ax1)
plt.xticks([0.4, 1.4, 2.4], ['category 1', 'category 2', 'category 3'])
ax1.set_ylabel("Count")
ax1.set_xlabel("")
plt.legend(loc='upper left')
## Percent
totals = [i + j for i,j in zip(data1, data2)]
data1_rel = [i / j * 100 for i,j in zip(data1, totals)]
data2_rel = [i / j * 100 for i,j in zip(data2, totals)]
ax2.bar(range(len(data1_rel)), data1_rel, alpha=0.5, color='b')
ax2.bar(range(len(data2_rel)), data2_rel, bottom=data1_rel, alpha=0.5, color='r')
plt.sca(ax2)
plt.xticks([0.4, 1.4, 2.4], ['category 1', 'category 2', 'category 3'])
ax2.set_ylabel("Percentage")
ax2.set_xlabel("")
plt.show()
现在,假设我想加一个,比如说 data3 = [100,150,130]
。直观上,我会这样做:
ax1.bar(range(len(data3)), data3, bottom=data1+data2, label='data 3', alpha=0.5, color='g')
但是,很不幸的是,这样做并没有添加第3根柱子。
4 个回答
0
这样怎么样?对我来说似乎有效。
from __future__ import division
from matplotlib import pyplot as plt
data1 = [100,120,140]
data2 = [150,120,190]
data3 = [130,110,120]
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))
## Absolute count
b = list(r_[data1] +r_[ data2])
ax1.bar(range(len(data1)), data1, label='data 1', alpha=0.5, color='b')
ax1.bar(range(len(data2)), data2, bottom=data1, label='data 2', alpha=0.5, color='r')
ax1.bar(range(len(data3)), data3, bottom=b, label='data 3', alpha=0.5, color='g')
plt.sca(ax1)
plt.xticks([0.4, 1.4, 2.4], ['category 1', 'category 2', 'category 3'])
ax1.set_ylabel("Count")
ax1.set_xlabel("")
plt.legend(loc='upper left')
## Percent
totals = [i + j + k for i,j,k in zip(data1, data2, data3)]
data1_rel = [i / j * 100 for i,j in zip(data1, totals)]
data2_rel = [i / j * 100 for i,j in zip(data2, totals)]
data3_rel = [i / j * 100 for i,j in zip(data3, totals)]
b_rel = list(r_[data1_rel] +r_[ data2_rel] )
ax2.bar(range(len(data1_rel)), data1_rel, alpha=0.5, color='b')
ax2.bar(range(len(data2_rel)), data2_rel, bottom=data1_rel, alpha=0.5, color='r')
ax2.bar(range(len(data3_rel)), data3_rel, bottom=b_rel, alpha=0.5, color='g')
plt.sca(ax2)
plt.xticks([0.4, 1.4, 2.4], ['category 1', 'category 2', 'category 3'])
ax2.set_ylabel("Percentage")
ax2.set_xlabel("")
plt.show()
0
我猜你在尝试绘图的时候遇到了错误,对吧?
现在你使用的是列表,所以:
>>> data1 = [1, 2, 3]
>>> data2 = [4, 5, 6]
>>> data+data2
>>> [1, 2, 3, 4, 5, 6]
你可以试试用numpy数组,这样应该能解决你的问题。
>>> data1 = numpy.array([1, 2, 3])
>>> data2 = numpy.array([4, 5, 6])
>>> data1+data2
>>> [5, 7, 9]
10
应该这样做:ax1.bar(range(len(data3)), data3, bottom=np.array(data1)+np.array(data2), label='data 3', alpha=0.5, color='g')
:

而且,这可能是更好的方法。用pandas
可以非常优雅地处理,只需要几行代码:
In [17]:
import pandas as pd
df=pd.DataFrame({'data1':data1, 'data2':data2, 'data3':data3})
df.plot(kind='bar', stacked=True)
Out[17]:
<matplotlib.axes.AxesSubplot at 0x108f2b050>