You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python堆叠柱状图如何隐藏含0/NaN的单元格而非整行?

解决堆叠柱状图中0值单元格隐藏问题

问题背景

使用Python 3.12 + Spyder,通过Pandas处理DataFrame后绘制堆叠柱状图。原始处理后的数据如下:

{'storage': {0: 'a', 2: 'a', 3: 'a', 4: 'b', 5: 'b'},
'time': {0: '4h', 2: '4h', 3: '4h', 4: '4h', 5: '4h'},
'Predicted Class': {0: 'germling',
 2: 'resting',
 3: 'swollen',
 4: 'germling',
 5: 'hyphae'},
'%': {0: 0.22, 2: 99.02, 3: 0.76, 4: 65.41, 5: 1.72}}

通过以下代码透视数据后出现0值单元格,希望仅隐藏这些0值对应的柱子,而非删除整行:

class_order = ['resting', 'swollen', 'germling', 'hyphae', 'mature hyphae']
counts2_reduced_df['Predicted Class'] = pd.Categorical(counts2_reduced_df['Predicted Class'], categories=class_order, ordered=True)

counts2_pivot_df = counts2_reduced_df.pivot_table(index=["storage","time"], columns="Predicted Class", values="%", aggfunc="sum")

尝试将0转为NaN后用drop.na会删除整行,转为空字符串会导致对应列完全不显示,现需解决仅隐藏0值柱子的问题。

解决方案

核心思路是将透视后的0值替换为NaN,然后在绘图时过滤掉高度为0的柱子,同时只对非0值添加注释。

修改后的完整代码

import pandas as pd
import matplotlib.pyplot as plt

# 原始数据(示例)
data = {'storage': {0: 'a', 2: 'a', 3: 'a', 4: 'b', 5: 'b'},
        'time': {0: '4h', 2: '4h', 3: '4h', 4: '4h', 5: '4h'},
        'Predicted Class': {0: 'germling', 2: 'resting', 3: 'swollen', 4: 'germling', 5: 'hyphae'},
        '%': {0: 0.22, 2: 99.02, 3: 0.76, 4: 65.41, 5: 1.72}}
counts2_reduced_df = pd.DataFrame(data)

# 数据透视处理
class_order = ['resting', 'swollen', 'germling', 'hyphae', 'mature hyphae']
counts2_reduced_df['Predicted Class'] = pd.Categorical(counts2_reduced_df['Predicted Class'], categories=class_order, ordered=True)
counts2_pivot_df = counts2_reduced_df.pivot_table(index=["storage","time"], columns="Predicted Class", values="%", aggfunc="sum")

# 关键步骤:将0值替换为NaN,绘图时不会显示对应柱子
counts2_pivot_df = counts2_pivot_df.replace(0, pd.NA)

# 绘图部分
fig, ax = plt.subplots()
color_mapping = {
    'resting': 'yellow',
    'swollen': 'blue',
    'germling': 'red',
    'hyphae': 'cyan',
    'mature hyphae': 'green',   
}
colors = [color_mapping[class_name] for class_name in class_order]

# 绘制堆叠柱状图
counts2_pivot_df.plot(kind='bar', stacked=True, color=colors, ax=ax)

# 设置X轴标签
ax.set_xticks(range(len(counts2_pivot_df.index)))
ax.set_xticklabels([f'{i[0]} & {i[1]}' for i in counts2_pivot_df.index], rotation=0)
ax.set_xlabel('Storage Condition and Time after Inoculation')
ax.set_ylabel('Percentage (%)')
ax.legend(title='Predicted Class', loc='center left', bbox_to_anchor=(1, 0.5))

# 仅对非0值添加注释
for bar_group in ax.containers:
    # 过滤掉高度为0的柱子
    bars = [bar for bar in bar_group if bar.get_height() > 0]
    for bar in bars:
        height = bar.get_height()
        text_x = bar.get_x() + bar.get_width() / 2
        text_y = bar.get_y() + height / 2
        ha = 'center' if height > 5 else 'left'
        text_x_adjusted = text_x if height > 5 else bar.get_x() + bar.get_width()
        ax.annotate(f'{height:.2f}%', xy=(text_x_adjusted, text_y), ha=ha, va='center', color='black', fontsize=8, fontweight='bold')

plt.tight_layout()
plt.show()

关键说明

  1. 替换0为NaN:counts2_pivot_df = counts2_pivot_df.replace(0, pd.NA),Pandas在绘制堆叠柱状图时会自动忽略NaN值对应的柱子,不会显示,且不会删除整行。
  2. 过滤注释:遍历柱子容器时,只处理高度大于0的柱子,避免对0值添加不必要的注释。
  3. 布局优化:添加plt.tight_layout()避免图例和图表元素重叠。

内容的提问来源于stack exchange,提问作者mr.raccoon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 06:22:06