在R语言base/dplyr中,为数据集行子集查找同组内最邻近行
分组DataFrame中行子集的同组最近邻计算方案
嘿,我来帮你解决这个问题——在按Group分组的DataFrame里,给指定的行子集找到同组内距离最近的其他行对吧?咱们用R来实现,步骤清晰,还会处理数据里的NA值。
先准备依赖包
首先得加载几个常用的工具包,dplyr用来分组操作,FNN高效计算最近邻,tidyr处理缺失值:
library(dplyr) library(FNN) library(tidyr)
第一步:处理数据里的NA
你的数据有不少NA,计算距离的时候得先搞定这个,我给两种方案:
- 过滤法:直接删掉带NA的行(适合NA占比低的情况)
- 填充法:用组内均值填充NA(保留更多数据)
先演示过滤法,顺便给每行加个唯一索引方便后续匹配:
df_clean <- df %>% mutate(row_id = row_number()) %>% # 给每行加原始索引 drop_na(A, B, C) # 删掉有NA的行
第二步:指定你要处理的行子集
假设你要找的是原始行里的第1、3、9行,先把它们提出来:
target_rows <- df_clean %>% filter(row_id %in% c(1, 3, 9))
第三步:分组计算最近邻
核心操作来了——按Group分组,对每个组里的目标行,找到同组内距离最近的非自身行(所以k=2,第一个最近邻是自身,取第二个):
nearest_neighbor_result <- df_clean %>% group_by(Group) %>% group_modify(function(group_data, group_info) { # 把当前组的数值列转成矩阵 num_data <- group_data %>% select(A, B, C) %>% as.matrix() # 找到当前组里属于目标子集的行的位置 target_positions <- which(group_data$row_id %in% target_rows$row_id) if (length(target_positions) == 0) return(tibble()) # 组里没有目标行就跳过 # 计算最近邻,k=2取第二个就是排除自身的最近邻 knn_output <- get.knn(num_data, k = 2) # 整理结果:目标行索引、最近邻行索引、距离 tibble( target_row_id = group_data$row_id[target_positions], nearest_row_id = group_data$row_id[knn_output$nn.index[target_positions, 2]], euclidean_distance = knn_output$nn.dist[target_positions, 2] ) }) %>% ungroup() # 把结果和原始数据关联,查看完整信息 final_result <- nearest_neighbor_result %>% left_join(df, by = c("target_row_id" = "row_id"), suffix = "_target") %>% left_join(df, by = c("nearest_row_id" = "row_id"), suffix = c("", "_nearest"))
结果说明
target_row_id:你指定的子集行的原始索引nearest_row_id:同组内距离它最近的行的原始索引euclidean_distance:两者之间的欧氏距离- 后面的列带
_target的是目标行的原始数据,带_nearest的是最近邻行的原始数据
可选:用填充法处理NA
如果不想删掉NA行,用组内均值填充:
df_filled <- df %>% mutate(row_id = row_number()) %>% group_by(Group) %>% mutate(across(c(A, B, C), ~ifelse(is.na(.), mean(., na.rm = TRUE), .))) %>% ungroup()
之后重复第二步和第三步就能得到结果啦。
内容的提问来源于stack exchange,提问作者Omry Atia
相关产品推荐
相关产品推荐

