R语言dplyr如何按条件最大值筛选分组数据?
问题描述
我有按测试及各测试内部子组分组的数据,采集了一系列比例值,以及用于判断各比例值显著性的p值,数据的基本结构如下:
testid <- paste0("T", c(rep(1, 5), rep(2, 5))) groupid <- rep(1:5, 2) prop <- c(0.98, 0.76, 0.54, 0.32, 0.1, 0.79, 0.32, 0.09, 0.04, 0.01) pval <- c(0.01, 0.02, 0.03, 0.04, 0.1, 0.03, 0.06, 0.25, 0.35, 0.45) library(dplyr) df <- tibble(testid, groupid, prop, pval) df # A tibble: 10 x 4 testid groupid prop pval <chr> <int> <dbl> <dbl> 1 T1 1 0.98 0.01 2 T1 2 0.76 0.02 3 T1 3 0.54 0.03 4 T1 4 0.32 0.04 5 T1 5 0.1 0.1 6 T2 1 0.79 0.03 7 T2 2 0.32 0.06 8 T2 3 0.09 0.25 9 T2 4 0.04 0.35 10 T2 5 0.01 0.45
需求是针对每个测试,提取p值小于0.05的所有子组中groupid数值最大的对应记录,预期输出结果如下:
desired <- df %>% filter((testid == "T1" & groupid == 4) | (testid == "T2" & groupid == 1)) desired # A tibble: 2 x 4 testid groupid prop pval <chr> <int> <dbl> <dbl> 1 T1 4 0.32 0.04 2 T2 1 0.79 0.03
之前编写的代码运行不符合预期,两个测试都仅返回了groupid为1的记录:
x <- df %>% group_by(testid) %>% filter(row_number() <= max(pval < 0.5)[1])
已确认每个测试至少存在一个p<0.05的子组,优先使用dplyr实现。
解决方案
原代码问题说明
- 阈值设置错误:代码中写的是
pval < 0.5,和需求的pval < 0.05不符 - 逻辑错误:
max(pval < 0.05)是对逻辑向量取最大值,只要组内存在符合p<0.05的记录就会返回TRUE,等价于数值1,因此row_number() <= 1只会返回每组的第一行记录,自然只能拿到groupid=1的结果。
正确实现代码
写法1:基础filter逻辑(兼容性最好)
result <- df %>% group_by(testid) %>% filter(pval < 0.05) %>% # 先筛选出当前测试下p值小于0.05的所有子组 filter(groupid == max(groupid)) %>% # 保留上述子组中groupid最大的记录 ungroup()
写法2:使用slice_max(dplyr 1.0.0及以上版本支持,更简洁)
result <- df %>% group_by(testid) %>% filter(pval < 0.05) %>% slice_max(order_by = groupid, n = 1) %>% # 直接按groupid降序取第一行 ungroup()
两种写法运行后得到的结果和预期输出完全一致。
内容的提问来源于stack exchange,提问作者markyoung
相关产品推荐
相关产品推荐

