R中按列唯一值筛选分组计算最小值并保留全部观测
问题原因
- 最初的dplyr代码丢数,是因为分组后直接调用
filter()会把所有不满足筛选条件的原始行直接从结果集中剔除,而非仅在计算最小值时使用这些条件筛选行,因此所有不符合「跨阵营配对、fr_loc毗邻边界」的观测都会被删掉。 - 手写的for循环存在两个明显错误:一是循环维度写为
ncol()即遍历所有列,和按user_loc分组计算的需求完全不匹配;二是循环内没有赋值操作,计算结果既没有修改原数据也没有输出,逻辑上也重复了提前筛行的错误,自然无法得到正确结果。
正确实现方案
两种方案都可以保留全部原始观测,同时给每个user_loc匹配对应的最小边界距离:
方案1:分组内直接条件计算(代码最简洁)
直接在mutate()中指定计算最小值的行范围,不需要提前筛选行,计算结果会自动填充到分组内所有行:
library(dplyr) nuts2_dist_germ2 <- nuts2_dist_germ %>% group_by(user_loc) %>% mutate( min_border_dist = min( distance[country_1990_user != country_1990_fr & ew_border_fr == 1], na.rm = TRUE ) ) %>% ungroup()
方案2:先计算参考表再关联(逻辑更直观,适合复杂计算场景)
先单独筛选符合条件的行计算每个user_loc对应的最小距离,再通过左连接把结果匹配回原始表,完全不会改动原始表的行数:
library(dplyr) # 计算每个user_loc对应的最小边界距离参考表 min_dist_lookup <- nuts2_dist_germ %>% filter(country_1990_user != country_1990_fr, ew_border_fr == 1) %>% group_by(user_loc) %>% summarise(min_border_dist = min(distance, na.rm = TRUE)) # 将结果匹配回原始数据 nuts2_dist_germ2 <- nuts2_dist_germ %>% left_join(min_dist_lookup, by = "user_loc")
注意:如果存在部分
user_loc没有任何符合筛选条件的配对行,方案1中对应值会返回Inf,方案2中对应值会返回NA,可根据实际研究需求用ifelse()替换为需要的取值。
内容的提问来源于stack exchange,提问作者beaner0228
相关产品推荐
相关产品推荐

