You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:06:47