Matplotlib零高度柱状图显示问题:如何可视化零高度条目?
解决柱状图零高度条目不可见的问题
我有一个包含两组数值的数据集,需要以两组数值的差值作为柱状图的高度,但当两组数值相等时,柱高为0导致无法显示。我需要将这类零高度条目显示为细线、点或其他可见元素,曾尝试给差值添加固定小值,但Y轴刻度动态变化,固定值在不同刻度范围适配性差。想知道使用subplot搭配bar(x, height)是否不合适,或是是否有更优方案比如ax.errorbar()?
原始示例代码
import matplotlib.pyplot as plt import pandas as pd df=pd.DataFrame() df["desc"] = ("A","B","C","D","E") df["a"] = (0.1,0.5,1,0.6,0.4) df["b"] = (0.3,0.6,0.6,0.7,0.4) fig, ax = plt.subplots() ax.bar(x=df['desc'], bottom=df['a'], height=df['b'] - df['a']) ax.set_ylim(bottom=0, top=1.2) new_yticks = list(set(df['a']).union(df['b'])) plt.yticks(new_yticks) plt.show()
可以看到X轴为"E"的条目因高度为0未显示。此前尝试给差值添加固定小值,但适配性差。
方案1:区分处理零高度与非零高度条目
针对零高度的条目单独绘制极窄柱子或标记点,既不影响正常柱子展示,又能让零值条目清晰可见,且高度会随Y轴范围自动适配:
import matplotlib.pyplot as plt import pandas as pd df = pd.DataFrame() df["desc"] = ("A","B","C","D","E") df["a"] = (0.1,0.5,1,0.6,0.4) df["b"] = (0.3,0.6,0.6,0.7,0.4) df['diff'] = df['b'] - df['a'] fig, ax = plt.subplots() # 绘制正常高度的柱子 non_zero_mask = df['diff'] != 0 ax.bar(x=df.loc[non_zero_mask, 'desc'], bottom=df.loc[non_zero_mask, 'a'], height=df.loc[non_zero_mask, 'diff']) # 处理零高度条目:绘制占Y轴范围1%的细柱,居中在a值位置 zero_mask = df['diff'] == 0 y_range = ax.get_ylim()[1] - ax.get_ylim()[0] tiny_height = y_range * 0.01 ax.bar(x=df.loc[zero_mask, 'desc'], bottom=df.loc[zero_mask, 'a'] - tiny_height/2, height=tiny_height, color='red', width=0.1) # 也可以替换成散点标记,更直观 # ax.scatter(x=df.loc[zero_mask, 'desc'], # y=df.loc[zero_mask, 'a'], # color='red', marker='o', s=50) ax.set_ylim(bottom=0, top=1.2) new_yticks = list(set(df['a']).union(df['b'])) plt.yticks(new_yticks) plt.show()
方案2:改用线段+标记的展示方式
如果核心是展示两组数值的差异而非严格柱状图,用散点+线段的组合会更灵活,零差异条目自然显示为重合的点,无需处理高度适配问题:
import matplotlib.pyplot as plt import pandas as pd df = pd.DataFrame() df["desc"] = ("A","B","C","D","E") df["a"] = (0.1,0.5,1,0.6,0.4) df["b"] = (0.3,0.6,0.6,0.7,0.4) x_indices = range(len(df['desc'])) fig, ax = plt.subplots() # 绘制两组数值的标记点 ax.scatter(x_indices, df['a'], color='blue', label='a') ax.scatter(x_indices, df['b'], color='orange', label='b') # 绘制连接每组a和b的线段 for i in x_indices: ax.plot([i, i], [df['a'][i], df['b'][i]], color='gray', linestyle='-') # 设置X轴刻度 ax.set_xticks(x_indices) ax.set_xticklabels(df['desc']) ax.set_ylim(bottom=0, top=1.2) new_yticks = list(set(df['a']).union(df['b'])) plt.yticks(new_yticks) plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者insane_IT
相关产品推荐
相关产品推荐

