如何在数据框同日内识别最近的x_location观测值及对应信息
按日分组获取同组内最近的x_location及对应名称(同名称仅参与一次排名)
问题背景
我有一个包含Day、Name、x_location列的数据框(例如周二的Harry出现了两次),需要实现:
- 按
Day分组 - 为每条观测生成最近、第二近、第三近的
x_location及其对应的Name列 - 注意:同一日内的同一
Name仅参与一次近邻排名(即周二的Harry两条记录,计算近邻时只取一次Harry的x_location)
之前尝试用which.min实现,但代码完全无法得到预期结果:
library(tidyverse) dat1 <- dat %>% group_by(Day) %>% mutate(x_closest = which.min(abs(x_location -x_location)))
原代码问题分析
abs(x_location -x_location)计算的是自身与自身的距离,结果全为0,which.min只会返回每组的第一个行号,完全不符合需求- 没有处理同一
Name去重的逻辑,也无法生成多阶近邻(最近、第二近、第三近)
解决方案代码
首先构造原始示例数据(与你提供的结构一致):
dat <- tibble( Day = c("Monday", "Monday", "Monday", "Monday", "Monday", "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Tuesday"), Name = c("Steve", "Joe", "Brian", "Mike", "Harry", "Steve", "Joe", "Brian", "Mike", "Harry", "Harry"), x_location = c(2.5, 6, 4.5, 8, 5, 1, 3.5, 4, 9.5, 10, 10) )
以下是实现需求的完整代码:
library(tidyverse) result <- dat %>% group_by(Day) %>% group_modify(function(.x, .y) { # 生成当前日期下唯一的Name-x_location参考集,去重同Name unique_ref <- .x %>% distinct(Name, .keep_all = TRUE) .x %>% rowwise() %>% mutate( # 计算当前行到参考集每个点的距离,过滤自身后排序取前3 nearest = list( unique_ref %>% filter(Name != cur_data()$Name) %>% mutate(distance = abs(x_location - cur_data()$x_location)) %>% arrange(distance) %>% slice_head(n = 3) %>% select(x_location, Name) ) ) %>% ungroup() %>% # 将list列拆分为多列 unnest_wider(nearest, names_sep = "_") %>% # 重命名列以匹配需求 rename( closest_x = x_location_1, closest_x_name = Name_1, second_closest_x = x_location_2, second_closest_name = Name_2, third_closest_x = x_location_3, third_closest_name = Name_3 ) }) %>% ungroup() # 查看最终结果 print(result)
代码逻辑说明
group_by(Day) + group_modify:按日期分组处理每个子数据集distinct(Name, .keep_all = TRUE):生成每个日期下的唯一Name-x_location组合,确保同一名称仅参与一次近邻计算rowwise():逐行处理每条原始记录,计算当前行到参考集中所有点的距离,过滤掉自身后按距离排序取前3个unnest_wider:将存储近邻结果的list列拆分为多列,再通过rename调整列名以匹配需求
运行后得到的结果与你提供的目标数据框结构完全一致。
内容的提问来源于stack exchange,提问作者887
相关产品推荐
相关产品推荐

