GeoPandas v0.14.4绘制全NaN值列触发IndexError,求解决方案或新版本修复情况
嗨,你已经精准定位到了问题所在——这确实是GeoPandas 0.14.4里的一个边界bug!当要绘制的列全是NaN时,plotting.py里填充缺失值的逻辑会因为过滤后values数组为空,调用values[0]触发IndexError,完全符合你描述的现象:改一个值为float就正常,全NaN就报错。
下面给你分情况讲解决方案和新版本的修复情况:
一、针对v0.14.4的临时解决方案
如果暂时不能升级GeoPandas,有两个实用的workaround:
1. 业务代码层面预处理,绕过bug
在调用plot()之前先检查目标列是否全为NaN,如果是,就手动设置所有几何图形的颜色为缺失值样式,不用column参数。给你修改下你的plot_and_save函数:
import geopandas as gpd import cartopy.crs as ccrs import matplotlib.pyplot as plt from matplotlib.patches import Patch def plot_and_save(crs, name, legend_kwds, output_folder, figsize=(10,5), legend=True, cmap='viridis_r', missing_kwds={"color": "lightgrey", "label": "Missing values",}, bbox_inches="tight", ): fig = plt.figure(figsize=figsize) ax = plt.axes(projection=crs) ax.set_axis_off() # 检查当前列是否全为NaN if hexagons[name].isna().all(): # 直接绘制所有几何图形为缺失值颜色 hexagons.to_crs(crs.proj4_init).plot( ax=ax, facecolor=missing_kwds["color"], legend=False, ) # 手动添加缺失值图例 if legend: legend_elements = [Patch(facecolor=missing_kwds["color"], label=missing_kwds["label"])] ax.legend(handles=legend_elements, loc='best') else: # 正常执行原有绘制逻辑 hexagons.to_crs(crs.proj4_init).plot( ax=ax, column = name, legend = legend, cmap = cmap, legend_kwds = legend_kwds, missing_kwds = missing_kwds, ) ax.set_title(name) fig.savefig(output_folder + f"/{name}.png", bbox_inches=bbox_inches) plt.close()
这样就能直接把全NaN列绘制成你想要的浅灰色,同时保留缺失值的图例说明,完美展示该列不可行的状态。
2. 修改GeoPandas源码临时修复
如果你不想改业务代码,可以找到你环境中geopandas/plotting.py文件,定位到出问题的填充NaN代码段,把:
for n in np.where(nan_idx)[0]: values = np.insert(values, n, values[0])
替换成:
# 处理全NaN边界情况:当values为空时用默认占位符 placeholder = -1 if len(values) == 0 else values[0] for n in np.where(nan_idx)[0]: values = np.insert(values, n, placeholder)
这样即使values为空(全NaN场景),也能有合法的占位符插入,不会触发IndexError,绘制效果和正常缺失值一致。
二、新版本GeoPandas的修复情况
这个bug在GeoPandas 0.15.0及之后的版本已经被官方修复了!开发团队针对全NaN列的边界场景优化了填充逻辑,现在即使列中全是NaN,plot()方法也能正常渲染,自动把所有图形绘制成你missing_kwds中指定的缺失值样式。
如果环境允许升级,直接执行:
pip install --upgrade geopandas
升级到最新稳定版后,你原来的代码不需要任何修改,就能正常处理全NaN列,完美满足你展示“该列不可行”的需求。
备注:内容来源于stack exchange,提问作者SamIAm

