R语言如何用dplyr分组创建新列并计算数值列百分比占比
示例数据构造
no <- rep(1:5, each=2) type <- rep(LETTERS[1:2], times=5) set.seed(4) value <- round(runif(10, 10, 30)) df <- data.frame(no, type, value)
原始数据结构
打印数据框df输出如下:
df no type value 1 1 A 22 2 1 B 10 3 2 A 16 4 2 B 16 5 3 A 26 6 3 B 15 7 4 A 24 8 4 B 28 9 5 A 29 10 5 B 11
需求说明
按no字段分组,统计每组的value总和作为total_value列,同时分别计算每组中type为A、B的value值占该组总value的百分比,生成pct_A、pct_B两个独立列,预期输出如下:
no pct_A pct_B total_value 1 1 68.75000 31.25000 32 2 2 50.00000 50.00000 32 3 3 63.41463 36.58537 41 4 4 46.15385 53.84615 52 5 5 72.50000 27.50000 40
原有实现(繁琐版)
原有可运行但流程冗余的代码如下:
df %>% group_by(no) %>% mutate(total_value= sum(value))-> df df %>% mutate(pct_A=ifelse(type=='A', (value/total_value) *100, 0), pct_B=ifelse(type=='B', (value/total_value) *100, 0)) %>% group_by(no) %>% summarise(pct_A=sum(pct_A), pct_B=sum(pct_B)) %>% ungroup() %>% merge(df) %>% distinct(no, .keep_all = T) %>% select(-type, -value)
优化dplyr实现方案
直接在分组后的summarise步骤完成所有计算,单管道一次输出结果,无需额外合并、去重操作:
library(dplyr) df %>% group_by(no) %>% summarise( total_value = sum(value), pct_A = sum(value[type == "A"]) / total_value * 100, pct_B = sum(value[type == "B"]) / total_value * 100 )
注:使用sum()包裹对应类型的value取值是为了兼容同组内同type存在多条记录的场景,若确定每组内A、B各只有1条记录,可省略sum()直接写value[type == "A"]。
内容的提问来源于stack exchange,提问作者Shibaprasad
相关产品推荐
相关产品推荐

