Matplotlib无法绘制首元素为np.nan的numpy数组如何解决?
问题原因
你遇到的现象是旧版本Matplotlib的bar接口对NaN值的处理缺陷导致的:当你批量传入包含np.nan的bottom数组时,整组条形都会被判定为无效直接跳过绘制,而不是仅跳过NaN对应的单个位置。3.4及以上版本的Matplotlib已经修复了这个问题,升级后会自动跳过NaN对应位置的条形,其余有效位置可正常渲染。
绕过方法(兼容所有版本)
最稳妥的方式是提前过滤掉缺失值对应的数据,只把有效值传给bar接口,示例修改代码如下:
import numpy as np import matplotlib.pyplot as plt N = 3 ind = np.arange(N) # 组的x轴位置 width = 2 # 条形宽度 height = 0.35 # 条形高度 D_data = np.array([27.68,np.nan,np.nan]) E_data = np.array([np.nan,18.59,18.31]) fig, ax = plt.subplots() # 过滤E的有效数据后绘制 e_valid_mask = ~np.isnan(E_data) E = ax.bar(ind[e_valid_mask], width, height, bottom=E_data[e_valid_mask]-1, label='E') # 过滤D的有效数据后绘制 d_valid_mask = ~np.isnan(D_data) D = ax.bar(ind[d_valid_mask], width, height, bottom=D_data[d_valid_mask]-1, label='D') ax.legend() plt.show()
如果你不想修改原始数据,也可以逐位置绘制条形,遇到NaN就跳过:
for x, d_bottom, e_bottom in zip(ind, D_data, E_data): if not np.isnan(d_bottom): ax.bar(x, width, height, bottom=d_bottom-1, color='#1f77b4', label='D' if x==ind[0] else "") if not np.isnan(e_bottom): ax.bar(x, width, height, bottom=e_bottom-1, color='#ff7f0e', label='E' if x==ind[1] else "")
相关问题解答
- 这是Matplotlib本身的问题吗?
是低版本Matplotlib的已知适配问题,3.4+版本已修复该缺陷,升级后直接传入带NaN的数组也能正常渲染有效位置的条形。 - 有没有比np.nan更优的空值处理方式?
np.nan是Matplotlib官方推荐的缺失值标记方式,除旧版本bar等少数接口外,其余绘图接口(折线图、散点图、箱型图等)都能正确识别并跳过np.nan对应数据点,不需要额外替换。如果需要兼容所有版本,最优方式是绘图前提前过滤缺失值,仅传入有效数据到绘图接口。
内容的提问来源于stack exchange,提问作者Ryguy
相关产品推荐
相关产品推荐

