如何用dplyr或Base R按条件筛选数据框的唯一行?
按concat分组保留grpRnk最小的行
先创建测试数据框:
test <- data.frame(concat = c(1.1,1.2,2.1,2.1,2.2,2.2,3.1,3.2), grpRnk = c(1,1,3,2,3,2,4,4))
原始数据如下:
> test concat grpRnk 1 1.1 1 2 1.2 1 3 2.1 3 4 2.1 2 5 2.2 3 6 2.2 2 7 3.1 4 8 3.2 4
原来用test %>% distinct(concat, .keep_all = TRUE)会保留每组concat的第一行,导致2.1和2.2对应的grpRnk是3,不符合需求。我们需要每个concat只保留grpRnk最小的行,以下是两种实现方式:
dplyr 实现
可以用group_by分组后,通过slice_min直接提取每组最小的行,或者用filter筛选出等于最小值的行:
library(dplyr) # 方法1:slice_min 提取每组最小行 test %>% group_by(concat) %>% slice_min(grpRnk, n = 1) %>% ungroup() # 方法2:filter 匹配最小值 test %>% group_by(concat) %>% filter(grpRnk == min(grpRnk)) %>% ungroup()
两种方法都会得到相同结果:
# A tibble: 6 × 2 concat grpRnk <dbl> <dbl> 1 1.1 1 2 1.2 1 3 2.1 2 4 2.2 2 5 3.1 4 6 3.2 4
Base R 实现
可以用aggregate先找出每个concat对应的最小grpRnk,再合并回原数据;或者用split+lapply的方式逐组处理:
# 方法1:aggregate+merge 匹配最小值 min_rnk <- aggregate(grpRnk ~ concat, data = test, FUN = min) result <- merge(test, min_rnk, by = c("concat", "grpRnk")) # 方法2:split分组后筛选最小值行 result <- do.call(rbind, lapply(split(test, test$concat), function(x) { x[x$grpRnk == min(x$grpRnk), ] })) rownames(result) <- NULL # 重置行名
运行后得到的结果和dplyr方法完全一致。
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

