通过Python的Matplotlib将3个条形堆叠在一起

时间:2014-06-11 16:32:30

标签: python matplotlib bar-chart

我想创建一个堆叠的条形图,其中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()

enter image description here

现在,让我们说要添加,例如data3 = [100,150,130] 直观地说,我会这样做

ax1.bar(range(len(data3)), data3, bottom=data1+data2, label='data 3', alpha=0.5, color='g')

然而,遗憾的是,这并没有添加第3栏。

4 个答案:

答案 0 :(得分:6)

应该:ax1.bar(range(len(data3)), data3, bottom=np.array(data1)+np.array(data2), label='data 3', alpha=0.5, color='g')enter image description here

而且,可能是一种首选方式。 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> 

enter image description here

答案 1 :(得分:1)

如果要使用pandas绘图库而不是matplotlib:

,则选项
import pandas

column_names = ['cat1', 'cat2', 'cat3']
data1 = [100,120,140]
data2 = [150,120,190]
data3 = [100,150,130]

df = pandas.DataFrame([data1, data2, data3], columns = column_names)
df.plot.bar(stacked=True)

stacked bar graph from pandas

答案 2 :(得分: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]

答案 3 :(得分: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()