Geopandas栅格采样后绘制折线子图空白问题排查
遥感点采样栅格分组折线图空白问题排查
问题背景
基于shapefile格式地面观测点提取40波段栅格对应点位数值,按地类分组绘制各波段均值折线子图。其中点读取、栅格采样代码运行正常,可输出正确的采样点属性表;分组统计绘图代码运行后所有子图为空白,已校验栅格与点数据投影完全一致。
正常运行的采样代码
#read points from shapefile train_pts = gpd.read_file (training_points) train_pts = train_pts[['class', 'classes' ,'CID', 'POINT_X','POINT_Y']] #attribute fields os shapefile train_pts.index = range(len(train_pts)) coords = [(x,y) for x, y in zip(train_pts.POINT_X, train_pts.POINT_Y)] #create list of point coordinates #sample each band of raster dataset at each point in the coordinate list train_pts ['Raster Value'] = [x for x in dataset.sample(coords)] #all band values saved as a list in the Raster Value column #Unpack the raster value column to separate column for each band train_pts[band_names] = pd.DataFrame(train_pts['Raster Value'].tolist(), index = train_pts.index) train_pts = train_pts.drop(['Raster Value'], axis=1) #drop raster value column #change the values for last three classes train_pts['CID'] = train_pts['CID'].replace([7,8,15],[5,6,7]) train_pts.to_csv('train_pts2.csv') #save as csv train_pts.head (30) #see columns
运行异常的绘图代码
prof = train_pts.groupby (['classes']).mean () fig = plt.figure(figsize = (17,20)) band_n = [ 'B2', 'B3', 'B4', 'B8' ,'NDVI' ,'VH', 'VV'] n = 1 for ba in band_n: ax = fig.add_subplot(4,2,n) ax.title.set_text(ba) band_val = prof[prof.columns[prof.columns.to_series().str.contains(ba)]] for index, row in band_val.iterrows(): color = cmap (index) ax.plot (row,color=color) ax.autoscale(enable=True, axis="both", tight=None) ax.set_xticklabels([str (x) for x in range(1, len(row)+1)]) ax.legend(loc='best', fontsize='small', ncol=2, labels=class_names) n=n+1
故障原因
- 列匹配逻辑不可靠:使用
str.contains(ba)做模糊匹配,容易出现错配、漏配——比如短波段名是其他列名的子串、列名带前后空格/大小写差异时,会取到空的band_val数据集,没有可绘制的内容。 - 坐标轴设置逻辑错误:直接调用
set_xticklabels但未先定义对应刻度位置,matplotlib默认刻度位置和传入的标签长度不匹配时,会导致坐标轴范围异常,绘制的线条落在可视区域外,呈现空白效果。 - 分组统计混入无关字段:
groupby.mean()默认对所有数值列计算均值,会把CID、POINT_X、POINT_Y等非光谱字段纳入统计,干扰波段筛选逻辑。 - 颜色映射调用错误:直接传入地类索引(大概率是字符串类名、非0起始的CID值)给colormap,无法解析出有效颜色值,会导致绘图静默失败,不渲染线条。
修复方案
替换原有绘图代码为以下版本,核心改动包括:分组统计时仅指定波段列计算均值、使用精确匹配筛选目标波段、先定义刻度位置再设置标签、提前为地类分配固定颜色、显式传入x/y坐标绘图避免索引错位。
import matplotlib.pyplot as plt import numpy as np # 仅对波段列做分组均值统计,排除坐标、CID等无关字段 prof = train_pts.groupby(['classes'])[band_names].mean() fig = plt.figure(figsize=(17,20)) band_n = ['B2', 'B3', 'B4', 'B8', 'NDVI', 'VH', 'VV'] n = 1 # 提前为所有地类分配固定颜色,避免cmap参数错误 class_list = prof.index.tolist() color_list = plt.cm.tab10(np.linspace(0, 1, len(class_list))) for ba in band_n: ax = fig.add_subplot(4,2,n) ax.title.set_text(ba) # 精确匹配目标波段列,避免模糊匹配的漏判错判 match_cols = [col for col in prof.columns if col.strip() == ba] if not match_cols: print(f"未找到波段{ba}对应列,跳过该子图") n += 1 continue band_val = prof[match_cols] x = np.arange(len(match_cols)) # 逐地类绘制折线,显式传入x、y值避免索引错位 for cls_idx, cls_name in enumerate(class_list): y_val = band_val.loc[cls_name].values ax.plot(x, y_val, color=color_list[cls_idx], label=cls_name) # 先设置刻度位置,再绑定刻度标签,解决坐标轴渲染异常 ax.set_xticks(x) ax.set_xticklabels(match_cols) ax.autoscale(enable=True, axis="both", tight=True) ax.legend(loc='best', fontsize='small', ncol=2) n += 1 # 自动调整子图间距避免标题、标签遮挡 plt.tight_layout() plt.show()
前置校验步骤
如果替换代码后仍有异常,先做两步检查:
- 打印
print(prof.columns.tolist()),确认所有波段列名和band_n列表内的名称完全一致,无多余空格、大小写差异。 - 循环内打印
print(ba, band_val.shape),确认每个子图取到的波段数据集非空。 - 如果存在同前缀多细分波段的情况(如B2包含多个波长子波段),将列匹配规则调整为
col.startswith(f"{ba}_")这类更精准的规则,不要用宽泛的包含匹配。
内容的提问来源于stack exchange,提问作者Gulnihal
相关产品推荐
相关产品推荐

