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')
输出
我尝试将普通条形图更改为堆叠条形图,但结果有问题。
数据:
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')
输出