【问题标题】:Horizontal stacked bar chart in MatplotlibMatplotlib 中的水平堆积条形图
【发布时间】:2013-05-15 06:21:04
【问题描述】:

我正在尝试使用 matplotlib 创建一个水平堆叠条形图,但我看不到如何使条形实际堆叠而不是全部从 y 轴开始。

这是我的测试代码。

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()

在看到 tcaswell 的评论后编辑为使用leftkwarg。

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()

这似乎是正确的方法,但如果没有特定柱的数据,它会失败,因为它试图将nan 添加到一个值,然后返回nan

【问题讨论】:

标签: python matplotlib pandas


【解决方案1】:

由于您使用的是 pandas,值得一提的是,您可以在本地制作堆积条形图:

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

visualisation section of the docs

【讨论】:

    【解决方案2】:

    这里有一个解决方案,尽管我确信一定有更好的方法。 series.fillna(0) 部分将任何 nan 替换为 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()
    

    【讨论】:

      【解决方案3】:

      这是一个显示等待和运行时间的简单堆叠水平条形图。

      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()
      

      【讨论】:

        【解决方案4】:

        作为旁注,您可以通过以下方式将重复的代码包装在一个循环中:

        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
        

        模数数据清理

        【讨论】: