简体   繁体   中英

Horizontal stacked bar chart in Matplotlib

I'm trying to create a horizontal stacked bar chart using matplotlib but I can't see how to make the bars actually stack rather than all start on the y-axis.

Here's my testing code.

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plot_chart(df, fig, ax)
ind = arange(df.shape[0])      
ax.barh(ind, df['EndUse_91_1.0'], color='#FFFF00')
ax.barh(ind, df['EndUse_91_nan'], color='#FFFF00')
ax.barh(ind, df['EndUse_80_1.0'], color='#0070C0')
ax.barh(ind, df['EndUse_80_nan'], color='#0070C0')
plt.show()

Edited to use left kwarg after seeing tcaswell's comment.

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plot_chart(df, fig, ax)
ind = arange(df.shape[0])      
ax.barh(ind, df['EndUse_91_1.0'], color='#FFFF00')
lefts = df['EndUse_91_1.0']
ax.barh(ind, df['EndUse_91_nan'], color='#FFFF00', left=lefts)
lefts = lefts + df['EndUse_91_1.0']
ax.barh(ind, df['EndUse_80_1.0'], color='#0070C0', left=lefts)
lefts = lefts + df['EndUse_91_1.0']
ax.barh(ind, df['EndUse_80_nan'], color='#0070C0', left=lefts)
plt.show()

This seems to be the right approach, but it fails if there is no data for a particular bar as it's trying to add nan to a value which then returns nan .

Since you are using pandas, it's worth mentioning that you can do stacked bar plots natively:

df2.plot(kind='bar', stacked=True)

See the visualisation section of the docs .

Here's a solution, although I'm sure there must be a better way of doing it. The series.fillna(0) part replaces any nan with 0.

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plot_chart(df, fig, ax)
ind = arange(df.shape[0])      
ax.barh(ind, df['EndUse_91_1.0'], color='#FFFF00')
lefts = df['EndUse_91_1.0'].fillna(0)
ax.barh(ind, df['EndUse_91_nan'], color='#FFFF00', left=lefts)
lefts = lefts + df['EndUse_91_1.0'].fillna(0)
ax.barh(ind, df['EndUse_80_1.0'], color='#0070C0', left=lefts)
lefts = lefts + df['EndUse_91_1.0'].fillna(0)
ax.barh(ind, df['EndUse_80_nan'], color='#0070C0', left=lefts)
plt.show()

As a side note, you can wrap the repetitive code up in a loop via:

data_lst = [df['EndUse_91_1.0'], ..]
color_lst = ["FFFF00", ..]
left = 0
for data, color in zip(data_lst, color_lst):
    ax.barh(ind, data, color=color, left=left)
    left += data

modulo data-sanitation

There was another good answer, here in Stack Overflow. It draws the Hbars while appending in a list! Go to answer.

其他帖子的解决方案。

Here's a simple stacked horizontal bar graph displaying wait and run times.

from datetime import datetime
import matplotlib.pyplot as plt

jobs = ['JOB1','JOB2','JOB3','JOB4']

# input wait times
waittimesin = ['03:20:50','04:45:10','06:10:40','05:30:30']
# converting wait times to float
waittimes = []
for wt in waittimesin:
    waittime = datetime.strptime(wt,'%H:%M:%S')
    waittime = waittime.hour + waittime.minute/60 + waittime.second/3600
    waittimes.append(waittime)

# input run times
runtimesin = ['00:20:50','01:00:10','00:30:40','00:10:30']
# converting run times to float    
runtimes = []
for rt in runtimesin:
    runtime = datetime.strptime(rt,'%H:%M:%S')
    runtime = runtime.hour + runtime.minute/60 + runtime.second/3600
    runtimes.append(runtime)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.barh(jobs, waittimes, align='center', height=.25, color='#00ff00',label='wait time')
ax.barh(jobs, runtimes, align='center', height=.25, left=waittimes, color='g',label='run time')
ax.set_yticks(jobs)
ax.set_xlabel('Hour')
ax.set_title('Run Time by Job')
ax.grid(True)
ax.legend()
plt.tight_layout()
#plt.savefig('C:\\Data\\stackedbar.png')
plt.show()

请参见堆积条形图

Its also possible (and very easy) to just element wise add all elements by using Map and the add operator . As already answered in the question Element-wise Addition of 2 Lists in Python? . Or just use numpy array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM