专栏名称: 走天涯徐小洋地理数据科学
一个爱生活的地理土博,分享GIS、遥感、空间分析、R语言、景观生态等地理数据科学实操教程、经典文献、数据资源
目录
相关文章推荐
51好读  ›  专栏  ›  走天涯徐小洋地理数据科学

R语言terra包提取矢量点位对应5×5窗口栅格像元值

走天涯徐小洋地理数据科学  · 公众号  ·  · 2025-03-06 17:06

正文

请到「今天看啥」查看全文


有学员自己写了一部分代码,运行不出结果,让我改改,下面是学员代码和修改过程,供大家学习参考。

任务要求

我有一个excle表格,里边包含一组带有编号、X、Y地理坐标(WGS84)的坐标点,另外给定一个含有空间参考坐标系和空间分辨率的栅格数据,想编写一个R语言代码,提取以表格中的坐标点为中心所对应的栅格数据5x5窗口中的像元值,然后存放到表格中相应的坐标点后。

学员代码

# 加载所需的包
library(readxl)
library(sf)
library(terra)
library(writexl)

# 读取Excel表格中的坐标点
coords "I:/2024年课题/地面样地/KT-1.xlsx")  # 替换为实际文件路径

# 将坐标点转换为sf对象(WGS84坐标系)
pts_sf "X""Y"), crs = 4326)

# 读取栅格数据
raster "I:/2024年课题/无人机光谱指数/SAVI_KT1.tif")  # 替换为实际文件路径

# 将点转换到栅格数据的坐标系
pts_proj

# 提取转换后的坐标点坐标
pts_coords

# 获取每个点对应的中心像元行列号
cells_center
rows_center
cols_center

# 获取栅格的行列总数
n_rows
n_cols

# 初始化存储结果的矩阵(每个点25个像元值)
values_matrix

# 遍历每个坐标点
for (i in 1:nrow(coords)) {
  r
  c
  
  # 生成5x5窗口的行列号范围
  rows_window
  cols_window
  
  # 生成所有行列组合并按行优先排序
  grid
  grid $row, grid$col), ]
  
  # 检查行列号是否在栅格范围内
  valid $row >= 1 & grid$row <= n_rows & grid$col >= 1 & grid$col <= n_cols
  
  # 提取有效的像元值
  cells_valid $row[valid], grid$col[valid])
  vals_valid
  
  # 填充到结果矩阵(无效位置为NA)
  vals
  vals[valid]
  values_matrix[i, ]
}

# 将结果添加到原始数据框
colnames(values_matrix) "Cell_", 1:25)
result_df

# 保存结果到Excel文件
write_xlsx(result_df, "output.xlsx")  # 替换为期望的输出路径

代码点评

上面的代码无法正常执行,是因为出现了一个典型问题,R包的混用问题。 terra 包和 sf 包不能混用!

  • terra 包有完整的空间分析功能,包括矢量和栅格
    • 矢量: vect() 函数,生成SpatVector
    • 栅格: rast() 函数,生成SpatRaster

要想提取矢量对应的栅格值,注意矢量一定要使用 vect() 函数,读取后获得的SpatVector,不能使用 sf 包, sf 包生成的sf对象,terra包是无法处理的,无法和SpatRaster进行叠置分析。

代码修改

发现了上面的问题,我就把代码进行了修改,把多余的包去掉,使用 terra 包函数来做,结合DeepSeek辅助编程。

改了一部分代码,把空间分析完全使用 terra 包来写,然后把情况完整的描述给DeepSeek,让它帮我完成代码:

# 加载所需的包
library(readxl)
library(terra)
library(openxlsx)

# 读取Excel表格中的坐标点
coords "./KT1.xlsx")  # 替换为实际文件路径
coords
# 将坐标点转换为sf对象(WGS84坐标系)
pts_sf "X""Y" ), crs = "EPSG:4326")
pts_sf
plot(pts_sf)
# 读取栅格数据
raster "./NDVI_KT1.tif")  # 替换为实际文件路径
raster
plot(raster)
# 将点转换到栅格数据的坐标系
rast_4326 = project(raster, "EPSG:4326")
rast_4326
已有代码如上所示,下面有一个任务,提取pts_sf点位对应的rast_4326栅格数据5x5窗口中的像元值,生成一个新的数据框,coords_rast_df,里面有ID,X,Y,还有对应的25个像元值的值,V1,V2一直到V25,请补全代码

对话过程

对话过程太长了,放到公众号里不合适,感兴趣的同学扫码看吧。

对话过程
对话过程

完整代码

下面是实际可以运行的完整代码

# 我有一个excle表格,里边包含一组带有编号、X、Y地理坐标(WGS84)的坐标点,另外给定一个含有空间参考坐标系和空间分辨率的栅格数据,想编写一个R语言代码,提取以表格中的坐标点为中心所对应的栅格数据5x5窗口中的像元值,然后存放到表格中相应的坐标点后。
# 加载所需的包
library(readxl)
library(terra)
library(openxlsx)

# 读取Excel表格中的坐标点
coords "./KT1.xlsx")  # 替换为实际文件路径
coords
# 将坐标点转换为sf对象(WGS84坐标系)
pts_sf "X""Y"), crs = "EPSG:4326")
pts_sf
plot(pts_sf)
# 读取栅格数据
raster "./NDVI_KT1.tif")  # 替换为实际文件路径
raster
plot(raster)
# 将点转换到栅格数据的坐标系
rast_4326 = project(raster, "EPSG:4326")
rast_4326

pts_coords # 获取坐标矩阵
cells # 获取像元索引
row_col # 转换为行列号

# 初始化存储25个像元值的列表
values_list

# 遍历每个点提取窗口值
for (i in 1:nrow(row_col)) {
  # 当前点的中心行列号
  center_row
  center_col
  
  # 生成5x5窗口的行列范围
  rows
  cols
  
  # 过滤有效行列(处理边界情况)
  valid_rows = 1 & rows <= nrow(rast_4326)]
  valid_cols = 1 & cols <= ncol(rast_4326)]
  
  # 跳过完全超出范围的窗口
  if (length(valid_rows) == 0 || length(valid_cols) == 0) {
    values_list[[i]]
    next
  }
  
  # 提取值并转换为矩阵
  window_vals
  
  # 创建全尺寸5x5矩阵(自动填充NA)
  full_matrix
  
  # 计算填充位置(相对窗口的偏移量,索引从1开始)
  row_offset # 原始偏移量
  col_offset
  
  # 转换为矩阵有效索引(防止越界)
  row_index # 调整索引从1开始
  col_index
  
  # 有效性校验
  valid_pos = 1) & (row_index <= 5) & 
    (col_index >= 1) & (col_index <= 5)
  
  # 执行矩阵赋值(仅有效位置)
  full_matrix[row_index[valid_pos], col_index[valid_pos]]
  
  # 按行展开并保存
  values_list[[i]]
}

# 创建最终数据框
coords_rast_df
  ID = coords$ID,          # 假设原始数据有id列
  X = coords[, "X"],  # 经度坐标
  Y = coords[, "Y"]   # 纬度坐标
)

# 添加25个值列
value_cols
colnames(value_cols) "V", 1:25)
coords_rast_df

# 查看结果
head(coords_rast_df)

更多内容欢迎加入地理数据科学培训班:

点击 阅读原文 即可跳转培训班







请到「今天看啥」查看全文