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

使用geosphere包centroid函数编写For循环计算质心报错求助

问题:按track_ID计算坐标质心并生成汇总数据框

我有一个包含451个唯一track_ID的数据框tow_dat,每个ID对应约125条经纬度观测值。我想生成一个包含所有ID质心经纬度的数据框,于是尝试用For循环实现:先创建空数据框,再循环将每个ID的质心结果存入其中。

我的代码:

forage.central <- as.tibble(data.frame(matrix(ncol = 2, nrow = 451)))
for(i in unique(tow_dat$track_ID)){
  current_data <- tow_dat %>%  filter(track_ID == i) %>%
    dplyr::select(lon,lat)

  print(centroid(current_data))
  forage.central[i] <- centroid(current_data)
}

运行后报错:

lon       lat
[1,] 151.9351 -27.58116
Error in `[<-`:
! Can't recycle input of size 2 to size 1.
Run `rlang::last_trace()` to see where the error occurred.

错误原因

forage.central[i]是选中数据框的第i列,但centroid()返回的是包含经度、纬度的长度为2的向量,试图把长度2的向量塞进长度1的列位置,就会触发维度不匹配的报错。另外,unique(tow_dat$track_ID)的结果可能不是连续的整数(比如ID是字符串或非连续数字),直接用它作为行索引会导致位置错乱。

解决方法

方法1:修复For循环

  • 先提取所有唯一的track_ID并存储为向量,用索引循环而非ID值
  • 用forage.central[row_idx, ]选中对应行,存入质心向量
  • 给结果数据框命名列名,方便识别
# 提取唯一ID列表
unique_ids <- unique(tow_dat$track_ID)
# 创建空数据框,指定列名和行长度
forage.central <- tibble(
  track_ID = unique_ids,
  lon = numeric(length(unique_ids)), 
  lat = numeric(length(unique_ids))
)

# 按索引循环处理每个ID
for(row_idx in seq_along(unique_ids)){
  current_id <- unique_ids[row_idx]
  current_data <- tow_dat %>% 
    filter(track_ID == current_id) %>%
    select(lon, lat)
  
  # 获取质心并赋值到对应行的经纬度列
  current_centroid <- centroid(current_data)
  forage.central[row_idx, c("lon", "lat")] <- current_centroid
}

方法2:用dplyr分组计算(更高效简洁)

R中处理分组统计优先用dplyr的分组函数,代码更简洁且避免循环的效率问题:

library(dplyr)

forage.central <- tow_dat %>%
  group_by(track_ID) %>%
  summarise(
    lon = centroid(cbind(lon, lat))[1],  # 提取质心的经度值
    lat = centroid(cbind(lon, lat))[2],  # 提取质心的纬度值
    .groups = "drop"  # 计算完成后取消分组
  )

补充:如果centroid函数(常见于sp或sf包)要求输入空间对象,可先将经纬度转换为空间点再计算,示例如下:

library(sf)

forage.central <- tow_dat %>%
  group_by(track_ID) %>%
  summarise(
    # 将当前组的经纬度转为多点对象,再计算质心
    centroid = st_sfc(st_centroid(st_multipoint(cbind(lon, lat)))),
    .groups = "drop"
  ) %>%
  # 从空间对象中提取经纬度坐标
  st_coordinates(centroid) %>%
  as_tibble() %>%
  rename(lon = X, lat = Y) %>%
  # 关联track_ID
  bind_cols(tow_dat %>% distinct(track_ID))

内容的提问来源于stack exchange,提问作者Matt-W22

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:55:34