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

在R中按Code内最近位置将天气数据连接至参与者数据列表

问题原因与解决方法

核心问题

你在for循环中每次将连接结果赋值给同一个merge变量,导致前一个参与者的结果被后一个覆盖,最终仅保留最后一个参与者的连接数据。

解决步骤

  1. 初始化存储容器:创建一个空列表,用于保存每个参与者的处理结果,避免赋值覆盖。
  2. 遍历处理每个参与者:对每个参与者的分Code子数据框,与对应Code的天气数据进行空间连接,再将该参与者的所有子结果合并为单个sf对象。
  3. 合并所有结果(可选):将所有参与者的结果合并为一个完整的sf数据框,并添加参与者标识以便区分。

修正后的完整代码

library(sf)
library(purrr)

#Participant1
HR<- c(60,62,61,60,60,61)
Code<- c("0_0", "0_1", "1_1", "0_2", "2_2", "0_0")
Lat <- c("1.295824", "1.295824", "1.295826", "1.295828", "1.295830", "1.295830")
Lon <- c("103.8494", "103.8494", "103.8494", "103.8494", "103.8494", "103.8494")
P1 <- data.frame(HR, Code, Lat, Lon)

#Participant2
HR<- c(71,70,69,71,72, 70)
Code<- c("0_0", "0_1", "1_1", "1_1", "0_2", "2_2")
Lat <- c("1.295995", "1.295977", "1.295995", "1.295992", "1.295987", "1.295992")
Lon <- c("103.8492", "103.8492", "103.8492", "103.8492", "103.8492", "103.8492")
P2 <- data.frame(HR, Code, Lat, Lon)

#Participant3
HR<- c(68,67,65,66,68, 68)
Code<- c("0_0", "0_1", "1_1", "0_2", "2_2", "2_2")
Lat <- c("1.295773", "1.295770", "1.295769", "1.295769", "1.295772",  "1.295769")
Lon <- c("103.8493", "103.8493", "103.8493", "103.8493", "103.8493", "103.8493")
P3 <- data.frame(HR, Code, Lat, Lon)

#Creating a list of df from participant data
ListP <- list(P1, P2, P3)

# 修正:先将Lat/Lon转为数值型,再创建sf对象并指定CRS
ListP <- lapply(ListP, function(x) {
  x$Lat <- as.numeric(x$Lat)
  x$Lon <- as.numeric(x$Lon)
  sf::st_as_sf(x, coords = c("Lon", "Lat"), crs = 4326) # 坐标顺序:经度在前、纬度在后,指定WGS84坐标系
})

#Creating Weather df
Tair <- c(30, 31, 32, 30, 21)
Code<- c("0_0", "0_1", "1_1", "0_2", "2_2")
Lat <- c("1.296033", "1.296028", "1.296020","1.296013", "1.296008")
Lon <- c("103.8493", "103.8493", "103.8493", "103.8493", "103.8493")
Weather <- data.frame(Tair, Code, Lat, Lon)

# 修正:天气数据同样转换坐标为数值型并指定CRS
Weather$Lat <- as.numeric(Weather$Lat)
Weather$Lon <- as.numeric(Weather$Lon)
Weather <- sf::st_as_sf(Weather, coords = c("Lon", "Lat"), crs = 4326)

#splitting into nested data frames by Code
ListP <- lapply(ListP, function(x) split(x, f=x$Code)) 
Weather <- split(x=Weather, f=Weather$Code)

# 用for循环处理并存储结果
merged_results <- list()
for(i in seq_along(ListP)) {
  # 对当前参与者的各Code子数据框,与对应天气数据做空间连接
  merged_part <- purrr::map2(ListP[[i]], Weather, st_join, join = st_nearest_feature)
  # 将当前参与者的所有Code子结果合并为单个sf对象
  merged_part <- do.call(rbind, merged_part)
  # 存入结果列表
  merged_results[[i]] <- merged_part
}

# 可选:合并所有参与者结果,添加参与者ID
final_merged <- do.call(rbind, merged_results)
final_merged$participant_id <- rep(paste0("P", 1:length(ListP)), sapply(merged_results, nrow))

# 查看最终结果
head(final_merged)

额外说明

  • 原代码中Lat和Lon是字符型,转换为sf对象时会导致坐标解析错误,因此添加了as.numeric()转换步骤,并指定了标准地理坐标系(WGS84,EPSG:4326)。
  • 使用do.call(rbind, ...)将每个参与者按Code拆分的子结果合并,避免嵌套列表结构,方便后续分析。
  • 如果偏好函数式编程风格,也可以用lapply替代for循环,代码更简洁:
# 方法2:用lapply替代for循环
merged_results <- lapply(ListP, function(participant) {
  merged <- map2(participant, Weather, st_join, join = st_nearest_feature)
  do.call(rbind, merged)
})

final_merged <- do.call(rbind, merged_results)
final_merged$participant_id <- rep(paste0("P", 1:3), sapply(merged_results, nrow))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 13:54:20