在R语言中计算分组数据占列总计的百分比
问题:计算分组月度数据占当月总计的百分比
原始数据
| 分组 | 1990年5月 | 1990年6月 | 1990年7月 |
|---|---|---|---|
| 1 | 581 | 552 | 465 |
| 2 | 193 | 184 | 176 |
| 3 | 207 | 177 | 165 |
| 总计 | 981 | 913 | 806 |
目标结果
需要计算每个分组的月度数据占对应月份总计的百分比,保留两位小数,得到如下表格:
| 分组 | 1990年5月 | 1990年6月 | 1990年7月 |
|---|---|---|---|
| 1 | 0.59 | 0.60 | 0.58 |
| 2 | 0.19 | 0.21 | 0.22 |
| 3 | 0.21 | 0.19 | 0.20 |
| 总计 | 1 | 1 | 1 |
出错的代码
df <- data.frame(group=c('1','2','3','Total'),may_1990=c(581,193,207,981),jun_1990=c(552,184,177,913),jul_1990=c(465,176,165,806)) total <- df %>% slice_tail(n = 1) z <- df %>% rowwise() %>% mutate(across(where(is.numeric), ~ .x/total[-1]))
问题分析
原代码存在两个核心问题:
- 误用
rowwise():across默认按列批量处理,逐行操作不仅降低效率,还会导致逻辑偏差; - 除法对象错误:
total[-1]是完整数据框,直接做除法会让每个数值列与整个总计数据框做广播运算,而非对应列的单个总计值,结果完全不符合预期。
修正方案
方法一:提取总计向量,按列匹配计算(适合多列场景)
library(dplyr) df <- data.frame( group=c('1','2','3','Total'), may_1990=c(581,193,207,981), jun_1990=c(552,184,177,913), jul_1990=c(465,176,165,806) ) # 提取总计行的数值并转为命名向量,确保列名匹配 total_vals <- df %>% slice_tail(n=1) %>% select(where(is.numeric)) %>% unlist() # 对每个数值列,除以对应月份的总计值 z <- df %>% mutate(across(where(is.numeric), ~ .x / total_vals[cur_column()])) # 保留两位小数,匹配目标格式 z <- z %>% mutate(across(where(is.numeric), ~ round(.x, 2)))
方法二:直接引用对应列的总计值(适合列数较少场景)
library(dplyr) df <- data.frame( group=c('1','2','3','Total'), may_1990=c(581,193,207,981), jun_1990=c(552,184,177,913), jul_1990=c(465,176,165,806) ) z <- df %>% mutate( may_1990 = may_1990 / may_1990[group == 'Total'], jun_1990 = jun_1990 / jun_1990[group == 'Total'], jul_1990 = jul_1990 / jul_1990[group == 'Total'] ) %>% mutate(across(where(is.numeric), ~ round(.x, 2)))
两种方法都能得到符合预期的结果,方法一更灵活,适合列数较多的数据集。
内容的提问来源于stack exchange,提问作者Mar
相关产品推荐
相关产品推荐

