如何结合分组数据实现空间连接?按Year匹配最近邻空间要素
按年份匹配的空间最近点连接方法
你需要的是仅在同一年份内为dat中的每个点匹配dat2里的最近点,而st_join默认的st_nearest_feature是全局查找最近点,不会考虑Year字段的匹配。由于st_join没有直接支持同时结合属性过滤和空间连接的by参数,我们可以通过按年份分组后再执行组内空间连接来实现需求。
解决方案代码
方法一:使用dplyr分组处理
library(sf) library(dplyr) # 构造原始数据 dat <- data.frame(Year = c(1980:1989), Lat = c(50.20920, 50.20920, 48.91840, 49.28491, 52.28401, 50.20920, 50.20920, 48.91840, 49.28491, 52.28401), Lon = c(9.49204, 8.75930, 9.84920, 7.85730, 7.49284, 9.49204, 8.75930, 9.84920, 7.85730, 7.49284)) dat2 <- data.frame(Var = c(rep("A", 3), rep("B", 5), rep("C", 6)), Year = c(1980:1982, 1981:1985, 1984:1989), Lat = c(49.829402, 48.02849, 50.94892, 41.38593, 50.28402, 48.93840, 50.73850, 52.48492, 41.38593, 50.28402, 48.93840, 50.20920, 50.20920, 48.02849), Lon = c(9.84920, 7.85730, 7.49284, 6.29482, 9.87294, 8.67204, 8.94837, 7.49284, 6.29482, 9.87294, 7.92840, 8.02948, 9.89039, 8.63029)) # 转换为空间数据框 dat.sf <- st_as_sf(dat, coords = c("Lon", "Lat")) %>% st_set_crs(4326) dat2.sf <- st_as_sf(dat2, coords = c("Lon", "Lat")) %>% st_set_crs(4326) # 按年份分组执行最近点连接 result <- dat.sf %>% group_by(Year) %>% group_modify(function(.x, .y) { # 筛选dat2中对应年份的点 dat2_year <- dat2.sf %>% filter(Year == .y$Year) # 组内执行空间最近点连接 st_join(.x, dat2_year, join = st_nearest_feature) }) %>% ungroup() # 查看结果 print(result)
方法二:使用purrr循环处理
如果你更习惯用purrr,可以用以下代码实现相同效果:
library(sf) library(purrr) # (数据转换部分同方法一,此处省略) # 获取所有唯一年份 years <- unique(dat.sf$Year) # 循环每个年份执行连接并合并结果 result <- map_dfr(years, function(y) { dat_year <- filter(dat.sf, Year == y) dat2_year <- filter(dat2.sf, Year == y) st_join(dat_year, dat2_year, join = st_nearest_feature) }) print(result)
代码说明
- 两种方法的核心逻辑一致:先按
Year字段筛选出对应年份的子数据集,再在子数据集内执行st_nearest_feature的空间连接,确保只在同一年份的点中查找最近匹配。 - 执行后,你会看到
Year字段完全匹配,比如1980年的点只会匹配dat2中1980年的点,不会再出现原代码中跨年份匹配的情况。
内容的提问来源于stack exchange,提问作者erc
相关产品推荐
相关产品推荐

