如何修复Pandas plot.barh无法生成单条水平堆叠条形图的问题?
解决单条水平堆叠条形图无法堆叠的问题
嘿,我立刻明白问题出在哪了!你用freq.plot.barh(ax=ax, stacked=True)没出现堆叠效果,核心原因是:
stacked=True参数是为多列的二维数据(比如DataFrame)设计的,用来把不同列的条形堆叠在一起;但你的freq是一个一维的Pandas Series,Pandas只会把每个类别绘制成独立的水平条形,堆叠参数自然无法生效。
解决方案1:把Series转成一行多列的DataFrame
这是最贴合你原有代码习惯的方法,只需要把一维的频率数据转换成一行、多列的DataFrame结构,就能触发堆叠效果:
import pandas as pd import matplotlib.pyplot as plt data = pd.DataFrame(data={"R1":["Yes","Yes","Yes","No","No"]}) freq = data["R1"].value_counts(normalize=True)*100 # 关键步骤:将一维Series转为1行2列的DataFrame freq_df = pd.DataFrame([freq.values], columns=freq.index) fig, ax = plt.subplots() freq_df.plot.barh(ax=ax, stacked=True) # 可选:添加百分比标签,让图表更直观 for container in ax.containers: ax.bar_label(container, fmt='%.1f%%') plt.title("Yes/No Response Percentage") plt.show()
解决方案2:用Matplotlib手动绘制堆叠条形
如果你想更灵活地控制绘图细节,可以直接用Matplotlib的barh函数手动绘制堆叠部分:
import pandas as pd import matplotlib.pyplot as plt data = pd.DataFrame(data={"R1":["Yes","Yes","Yes","No","No"]}) freq = data["R1"].value_counts(normalize=True)*100 fig, ax = plt.subplots() # 绘制第一个堆叠块(Yes) yes_pct = freq["Yes"] bar1 = ax.barh(y=0, width=yes_pct, label="Yes") # 绘制第二个堆叠块(No),起始位置是第一个块的宽度 no_pct = freq["No"] bar2 = ax.barh(y=0, width=no_pct, left=yes_pct, label="No") # 添加百分比标签 ax.bar_label(bar1, fmt='%.1f%%') ax.bar_label(bar2, fmt='%.1f%%') # 调整y轴显示 ax.set_yticks([0]) ax.set_yticklabels(["Total Responses"]) ax.legend() plt.title("Yes/No Response Percentage") plt.show()
为什么这样能解决问题?
堆叠条形图的本质是把同一行的多个数据列,在同一个条形位置上叠加展示。当你把一维的Series转换成一行多列的DataFrame后,Pandas就能识别出需要把这两列的数据堆叠成一个单一的水平条形,完美实现你想要的“替代饼图展示百分比”的效果。
内容的提问来源于stack exchange,提问作者CharlesW
相关产品推荐
相关产品推荐

