pandas v1.3.0中DataFrame.plot()绘制柱状图忽略0值的实现方法
问题根源说明
pandas v1.3.0 版本的柱状图绘制接口不会自动跳过0值或NaN值,你将0替换为NaN的方案失效,是因为该版本会默认将NaN处理为0高度进行渲染,所以还是会显示无效的空白占位。
可行解决方案
方案1:最小改动适配原有逻辑
直接在原有代码绘制后,移除高度为0的柱子即可,无需调整数据结构:
X_AXIS = x_axis_labels_list index = pd.Index(X_AXIS, name= 'my_name') cmap = 'tab20' df = pd.DataFrame(dic, index=index) ax = df.plot(kind='bar', figsize=(50, 6), colormap=cmap) # 新增代码:删除高度为0的柱子,加极小阈值避免浮点精度导致的判断误差 for bar_container in ax.containers: for bar in bar_container: if bar.get_height() < 1e-9: bar.remove() ax.set_ylabel('tk score') plt.legend(title='labels', bbox_to_anchor=(1.0, 1), loc='upper left') plt.show()
方案2:调整数据格式过滤0值后绘图
如果需要从数据层面提前过滤无效值,可以将宽表转换为长表,过滤0值后再绘制:
import pandas as pd import numpy as np import matplotlib.pyplot as plt X_AXIS = x_axis_labels_list cmap = 'tab20' df = pd.DataFrame(dic, index=X_AXIS) # 宽表转长表,过滤0值 df_long = df.stack().reset_index() df_long.columns = ['x_label', 'protein', 'score'] df_long = df_long[df_long['score'] > 1e-9] # 配置颜色映射,和原pandas绘图逻辑保持一致 protein_all = df.columns.tolist() color_list = plt.get_cmap(cmap)(np.linspace(0, 1, len(protein_all))) color_mapper = dict(zip(protein_all, color_list)) # 计算分组柱子的偏移量 bar_width = 0.8 / len(protein_all) x_tick_pos = np.arange(len(X_AXIS)) plt.figure(figsize=(50,6)) for protein in protein_all: sub_data = df_long[df_long['protein'] == protein] x_pos = [x_tick_pos[X_AXIS.index(label)] + bar_width * protein_all.index(protein) for label in sub_data['x_label']] plt.bar(x_pos, sub_data['score'], width=bar_width, color=color_mapper[protein], label=protein) plt.xticks(x_tick_pos + 0.4, X_AXIS) plt.ylabel('tk score') plt.legend(title='labels', bbox_to_anchor=(1.0, 1), loc='upper left') plt.tight_layout() plt.show()
两个方案都可以在pandas v1.3.0下实现仅渲染非0柱子的需求。
内容的提问来源于stack exchange,提问作者Tim Kirkwood
相关产品推荐
相关产品推荐

