R语言:按分组批量统计多列中'yes'的占比
按分组统计多列中"yes"的占比(tidyverse高效实现)
需求说明
按group列分组,统计数据框中其余每一列里"yes"出现的占比(忽略NA值,结果保留两位小数),示例数据及期望结果如下:
示例数据:
df <- data.frame(group = c("a","a","a","a","b","b","b","b"), female = c("yes","no","yes","no","yes","yes","yes","no"), alcohol = c("yes","no",NA,"no","yes","yes","no","no"))
期望结果:
> df_result group female alcohol 1 a 0.50 0.33 2 b 0.75 0.50
解决方案
使用tidyverse中的dplyr包,通过group_by()+summarise()+across()组合实现,无需逐一指定列名:
library(tidyverse) # 示例数据 df <- data.frame(group = c("a","a","a","a","b","b","b","b"), female = c("yes","no","yes","no","yes","yes","yes","no"), alcohol = c("yes","no",NA,"no","yes","yes","no","no")) # 核心代码 df_result <- df %>% group_by(group) %>% # 对所有非分组列计算yes的占比,忽略NA summarise(across(everything(), ~ mean(.x == "yes", na.rm = TRUE))) %>% ungroup() %>% # 保留两位小数,匹配示例格式 mutate(across(-group, ~ round(.x, 2))) # 查看结果 df_result
代码解释
group_by(group):按group列进行分组across(everything(), ~ mean(.x == "yes", na.rm = TRUE)):across(everything()):自动遍历除分组列外的所有列,无需手动列名.x == "yes":将列中每个元素转为逻辑值(等于"yes"为TRUE,否则FALSE)mean(..., na.rm = TRUE):逻辑值的均值即为TRUE的占比,na.rm = TRUE忽略NA值(和示例中a组alcohol的计算逻辑一致:3个非NA值里1个yes,占比1/3≈0.33)
ungroup():取消分组状态,避免后续操作受分组影响mutate(across(-group, ~ round(.x, 2))):对除group外的列保留两位小数,匹配期望结果格式
扩展说明
如果只想统计特定类型的列(比如仅字符型列),可以把across(everything())改成:
across(where(is.character), ~ mean(.x == "yes", na.rm = TRUE))
如果需要排除某几列,比如排除group和另一列xxx,可以用:
across(-c(group, xxx), ~ mean(.x == "yes", na.rm = TRUE))
内容的提问来源于stack exchange,提问作者BPeif
相关产品推荐
相关产品推荐

