Pandas 堆叠条形图出错

Pandas stacked bar chart went wrong

我尝试将普通条形图更改为堆叠条形图,但结果有问题。

数据:

                Total Monthly Actual Hours  Total Monthly Work Hours
Activity Month                                                      
Apr-19                            35381.25                     42592
May-19                            31722.50                     44528
Jun-19                            27708.50                     38720
Jul-19                            34283.50                     44528
Aug-19                            32225.60                     42592

这是正常图表:

ax = dfWorkActual.plot(kind='bar')
ax.tick_params(rotation = 0)

for date, (p, q) in enumerate(zip(dfWorkActual["Total Monthly Actual Hours"],dfWorkActual["Total Monthly Work Hours"])):
    ax.annotate(f"{round(p,2)}\n({(p/q)*100:.0f}%)", (date-0.25, p*1.02))
    ax.annotate(f"{round(q,2)}\n({(q/q)*100:.0f}%)", (date, q*1.02))

plt.ylabel('Work Hours')
plt.xlabel('Month')
plt.title("Chart 5: (Total Monthly Work Hours + Total Actual Work Hours) vs Month", fontweight='bold')

这是我加上stacked=True后的结果:

ax = dfWorkActual.plot(kind='bar')
ax.tick_params(rotation = 0)

for date, (p, q) in enumerate(zip(dfWorkActual["Total Monthly Actual Hours"],dfWorkActual["Total Monthly Work Hours"])):
    ax.annotate(f"{round(p,2)}\n({(p/q)*100:.0f}%)", (date-0.25, p*1.02))
    ax.annotate(f"{round(q,2)}\n({(q/q)*100:.0f}%)", (date, q*1.02))

# for p in ax.patches:
    # ax.annotate(str(round(p.get_height(), 2)), (p.get_x() * 1.005, p.get_height() * 1.005))

plt.ylabel('Work Hours')
plt.xlabel('Month')
plt.title("Chart 5: (Total Monthly Work Hours + Total Actual Work Hours) vs Month", fontweight='bold')

我期望的图表应该是这样的:

您可以使用此代码先绘制较高的条形图,然后绘制较低的条形图。不过你必须用不同的颜色绘制它们,否则它们不会显示在图表上。

代码

fig, ax= plt.subplots()

col = dfWorkActual.columns[::-1]

color = ['y','b']

for i in range(0,len(col)):
    dfWorkActual[col[i]].reset_index().plot(kind='bar',ax=ax,x='Activity Month',color=color[i],figsize=(25,20))

for date, (p, q) in enumerate(zip(dfWorkActual["Total Monthly Actual Hours"],dfWorkActual["Total Monthly Work Hours"])):
    ax.annotate(f"{round(p,2)}\n({(p/q)*100:.0f}%)", (date-0.45, p*1.02))
    ax.annotate(f"{round(q,2)}\n({(q/q)*100:.0f}%)", (date-0.1, q*1.02))

plt.ylabel('Work Hours')
plt.xlabel('Month')
plt.title("Chart 5: (Total Monthly Work Hours + Total Actual Work Hours) vs Month", fontweight='bold')

输出

或者,您可以在临时 df 中减去差异,然后将它们堆叠起来,我认为这样更容易。

代码

df = dfWorkActual.copy()
df['Total Monthly Work Hours'] = df['Total Monthly Work Hours']-df['Total Monthly Actual Hours']

ax = df.plot(kind='bar',stacked=True,figsize=(18,15))
ax.tick_params(rotation=0)

for date, (p, q) in enumerate(zip(dfWorkActual["Total Monthly Actual Hours"],dfWorkActual["Total Monthly Work Hours"])):
    ax.annotate(f"{round(p,2)}\n({(p/q)*100:.0f}%)", (date-0.45, p*1.02))
    ax.annotate(f"{round(q,2)}\n({(q/q)*100:.0f}%)", (date-0.1, q*1.02))

plt.ylabel('Work Hours')
plt.xlabel('Month')
plt.title("Chart 5: (Total Monthly Work Hours + Total Actual Work Hours) vs Month", fontweight='bold')

输出