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

地图插值叠加异常求助:采样村庄数据插值后无法匹配区域地图

插值结果叠加地图异常问题

我从包含至少105个村庄的区域采样了10个村庄的数据,预测后得到含经度、纬度及预测值的数据集。

我的需求是通过插值将采样数据覆盖到未采样村庄,第一步的插值等高线图生成正常,但将插值结果叠加到区域地图时完全异常,无法覆盖未采样村庄。


第一步正常运行的插值代码

from scipy.interpolate import griddata
import numpy as np
import matplotlib.pyplot as plt

# 提取经纬度和预测值列
interpolation_data = decoded_df[['longitude', 'latitude', 'prediction']]

# 删除缺失值行
interpolation_data = interpolation_data.dropna()

# 转换为numpy数组
points = interpolation_data[['longitude', 'latitude']].values
values = interpolation_data['prediction'].values

# 定义插值网格点
grid_points = np.vstack((grid_lon.flatten(), grid_lat.flatten())).T

# 执行线性插值(注:代码注释写了IDW但实际调用的是linear方法)
interpolated_values = griddata(points, values, grid_points, method='linear')

interpolated_values = interpolated_values.reshape(grid_lon.shape)

# 绘制等高线图
plt.contourf(grid_lon, grid_lat, interpolated_values)
plt.colorbar()
plt.scatter(decoded_df['longitude'], decoded_df['latitude'], c=decoded_df['prediction'], cmap='viridis', edgecolors='black')
plt.xlabel('经度')
plt.ylabel('纬度')
plt.title('插值预测结果')
plt.show()

叠加地图的异常代码及问题

import geopandas as gpd
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import box

# 读取Babati村庄shapefile
shapefile_path = "Babati Villages/Babati_villages.shp"
gdf_babati = gpd.read_file(shapefile_path)

gdf_bti= gdf_babati[gdf_babati["District_N"] == "Babati"]

# 定义插值网格点
grid_points = np.vstack((grid_lon.flatten(), grid_lat.flatten())).T

# 执行线性插值
interpolated_values = griddata(points, values, grid_points, method='linear')

# 重塑插值结果匹配网格形状
interpolated_values = interpolated_values.reshape(grid_lon.shape)

# 创建Babati区域边界框
bbox = box(gdf_bti.total_bounds[0], gdf_bti.total_bounds[1],
           gdf_bti.total_bounds[2], gdf_bti.total_bounds[3])

# 裁剪插值结果到区域范围(此处存在核心错误)
interpolated_predictions = gpd.clip(interpolated_predictions, bbox)

# 创建子图
fig, ax = plt.subplots(figsize=(10, 10))

# 绘制村庄边界
gdf_bti.plot(ax=ax, facecolor='none', edgecolor='black')

# 绘制插值结果
interpolated_predictions.plot(ax=ax, column='prediction', cmap='viridis', markersize=30, legend=True)

# 添加颜色条
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.1)
interpolated_predictions.plot(ax=cax, column='prediction', cmap='viridis', legend=True, cax=cax)

# 设置标题和标签
ax.set_title('Babati区域插值预测结果')
ax.set_xlabel('经度')
ax.set_ylabel('纬度')

plt.show()

运行上述代码后,插值结果叠加地图完全异常,无法覆盖未采样村庄。


问题分析与修复方案

1. 核心错误:未将插值网格转换为GeoDataFrame

你直接对interpolated_values(numpy数组)调用gpd.clip,但interpolated_predictions从未被正确定义为GeoDataFrame,这是导致异常的根本原因。

修复步骤:
将插值网格和对应的预测值转换为带地理信息的GeoDataFrame:

from shapely.geometry import Point

# 生成网格点的几何对象列表
geometry = [Point(xy) for xy in grid_points]
# 创建GeoDataFrame,必须指定坐标系与shapefile一致
interpolated_predictions = gpd.GeoDataFrame(
    {'prediction': interpolated_values.flatten(),
     'geometry': geometry},
    crs=gdf_bti.crs  # 同步shapefile的坐标系
)

2. 坐标系不匹配问题

如果采样数据的经纬度是WGS84(EPSG:4326),而shapefile使用了其他投影坐标系,直接叠加会导致位置错位。

修复:
确保插值数据与shapefile坐标系一致:

# 查看shapefile的坐标系
print(gdf_bti.crs)
# 若插值数据是WGS84,转换为shapefile的坐标系
interpolated_predictions = interpolated_predictions.to_crs(gdf_bti.crs)

3. 针对「覆盖未采样村庄」的优化方案

如果你目标是给每个未采样村庄赋值,而非覆盖整个网格区域,更高效的方式是直接对村庄中心点插值:

# 筛选未采样村庄(需替换为实际的村庄ID列名和采样ID列表)
unsampled_villages = gdf_bti[~gdf_bti['Village_ID'].isin(sampled_village_ids)]
# 获取村庄几何中心点
village_centers = unsampled_villages.geometry.centroid
# 提取中心点坐标
village_coords = np.array([[point.x, point.y] for point in village_centers])
# 对村庄中心点执行插值
village_predictions = griddata(points, values, village_coords, method='linear')
# 将预测值关联到村庄数据
unsampled_villages['prediction'] = village_predictions

# 可视化所有村庄
fig, ax = plt.subplots(figsize=(10,10))
gdf_bti.plot(ax=ax, facecolor='none', edgecolor='black')
# 绘制采样村庄(标记为红色边框)
sampled_villages = gdf_bti[gdf_bti['Village_ID'].isin(sampled_village_ids)]
sampled_villages.plot(ax=ax, column='prediction', cmap='viridis', markersize=50, edgecolor='red', label='采样村庄')
# 绘制未采样村庄
unsampled_villages.plot(ax=ax, column='prediction', cmap='viridis', markersize=30, label='未采样村庄')
plt.legend()
plt.colorbar(ax=ax)
plt.title('Babati区域村庄预测值分布')
plt.xlabel('经度')
plt.ylabel('纬度')
plt.show()

4. 代码冗余清理

删除重复导入的geopandas和matplotlib.pyplot语句,简化代码结构。


内容的提问来源于stack exchange,提问作者LivingstoneM

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:29:54