R语言按treatment筛选最接近目标stage值的唯一观测值问题
按组筛选最接近目标值的唯一观测
原始数据集
data_a <- read.csv(text = " date,treatment,stage 1,a,1 2,a,10 3,a,20 4,a,30 5,a,60 6,a,70 7,a,89 8,a,91 9,a,92 1,b,1 2,b,10 3,b,20 4,b,30 5,b,59.8 6,b,60.2 7,b,88.8 8,b,90.2 9,b,92 1,c,1 2,c,10 3,c,20 4,c,60 5,c,66 6,c,70 7,c,80 8,c,85 9,c,85")
需求说明
在每个treatment分组内,为目标值10、60、89分别筛选出stage值最接近的唯一观测:
- 若存在精确匹配的
stage值,直接选取该观测 - 若有多个观测与目标值的差值相同,仅保留其中一个(参考期望输出,选取
date较小的观测)
现有代码问题
原代码使用多条件筛选,当多个观测与目标值的绝对差值相等时,会将所有符合条件的观测都保留,不符合“唯一观测”的要求:
filtered_data <- data_a %>% group_by(treatment) %>% filter(abs(stage - 10) == min(abs(stage - 10)) | abs(stage - 60) == min(abs(stage - 60)) | abs(stage - 89) == min(abs(stage - 89)))
解决方案
通过对每个分组和每个目标值单独处理,找到最接近的观测后合并结果。使用purrr::map_dfr遍历目标值,结合slice_min在差值最小时选取date最小的观测:
library(dplyr) library(purrr) targets <- c(10, 60, 89) filtered_data <- map_dfr(targets, function(target) { data_a %>% group_by(treatment) %>% mutate(diff = abs(stage - target)) %>% slice_min(order_by = diff, n = 1, with_ties = FALSE) %>% select(-diff) }) %>% arrange(treatment, date)
验证输出结果与期望一致:
print(filtered_data) # date treatment stage # 1 2 a 10.0 # 2 5 a 60.0 # 3 7 a 89.0 # 4 2 b 10.0 # 5 5 b 59.8 # 6 7 b 88.8 # 7 2 c 10.0 # 8 4 c 60.0 # 9 8 c 85.0
代码说明
map_dfr:遍历每个目标值,处理后按行合并结果mutate(diff = abs(stage - target)):计算每个观测与当前目标值的绝对差值slice_min(order_by = diff, n = 1, with_ties = FALSE):在每个分组内选取差值最小的1个观测,with_ties = FALSE确保即使有多个相同差值的观测,也只保留原数据中靠前的(即date较小的)arrange(treatment, date):最后按分组和日期排序,与期望输出格式一致
内容的提问来源于stack exchange,提问作者Giuseppe Petri
相关产品推荐
相关产品推荐

