如何在dplyr分组聚合时对含B的列取分位数,其余列取均值?
解决方案
你可以通过两种方式实现需求,无需创建额外的dataframe,直接在原dplyr管道中完成:
方法一:单across内按列名判断逻辑
利用cur_column()获取当前处理的列名,在across的函数中通过条件判断选择计算方式:
library(dplyr) df <- data.frame(mydate=as.Date(c("2000-01-15", "2000-02-15", "2000-03-15")), columnA=c(2, 4, 5), columnB=c(3, 6, 7)) df %>% mutate(year = format(mydate, "%Y")) %>% group_by(year) %>% summarise( across( where(is.numeric), ~ if_else(grepl("B", cur_column(), fixed = TRUE), quantile(.x, probs = 0.9, na.rm = TRUE), mean(.x, na.rm = TRUE)) ), .groups = "drop" # 可选,聚合后取消分组状态 )
cur_column()是dplyr内置函数,用于在across内部获取当前列的名称if_else根据列名是否包含"B",分别执行分位数计算或均值计算.groups = "drop"可以避免后续操作受分组状态影响,按需添加
方法二:拆分across分别处理列
这种方式可读性更强,通过matches("B")匹配列名,拆分两个across分别处理不同列:
df %>% mutate(year = format(mydate, "%Y")) %>% group_by(year) %>% summarise( # 处理列名含"B"的数值列 across( where(is.numeric) & matches("B"), ~ quantile(.x, probs = 0.9, na.rm = TRUE) ), # 处理其余数值列 across( where(is.numeric) & !matches("B"), ~ mean(.x, na.rm = TRUE) ), .groups = "drop" )
matches("B")用于匹配列名包含"B"的列,结合where(is.numeric)筛选出目标数值列- 两个
across分别执行不同的聚合逻辑,结果会自动合并到同一结果集中
说明
你之前的错误在于试图用ifelse包裹整个summarise操作,这不符合dplyr的管道逻辑。正确的做法是将条件判断放在across内部的列级处理逻辑中,或是拆分across分别处理不同列组。
内容的提问来源于stack exchange,提问作者Martin Liungman
相关产品推荐
相关产品推荐

