如何为各地区的变量列添加占该地区总和的百分比列?
计算各地区变量占比的实现方案
需求说明
现有一份包含9个地区(District 1至District 9)、10个变量(1至10)计数的数据集,需要为每个地区新增10个百分比列(命名为pct1至pct10),每个列对应原变量值占该地区所有变量总和的百分比,且每个地区的百分比列总和需为100%。
原始数据
df = structure(list(LONGNAME = c("District 1", "District 2", "District 3", "District 4", "District 5", "District 6", "District 7", "District 8", "District 9"), `1` = c(42065L, 49367L, 37063L, 27360L, 36424L, 26415L, 28010L, 35001L, 30510L), `2` = c(1667L, 3598L, 3989L, 6762L, 2125L, 2660L, 3912L, 4258L, 4089L), `3` = c(6004L, 7672L, 9245L, 10118L, 5554L, 5520L, 7853L, 8716L, 7554L), `4` = c(6712L, 2656L, 4700L, 6868L, 2560L, 3452L, 4838L, 4656L, 3458L), `5` = c(5626L, 4823L, 5086L, 10852L, 4700L, 4239L, 5032L, 7864L, 5623L), `6` = c(5737L, 9123L, 10042L, 20704L, 10119L, 13243L, 11144L, 12049L, 14064L ), `7` = c(4669L, 4338L, 3859L, 12530L, 4453L, 8099L, 3658L, 4049L, 6360L), `8` = c(2212L, 2980L, 1647L, 11298L, 4611L, 13664L, 1139L, 2132L, 6879L), `9` = c(302L, 830L, 700L, 6476L, 675L, 20224L, 357L, 588L, 907L), `10` = c(14L, 25L, 12L, 1087L, 6L, 2916L, 2L, 23L, 5L)), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame"))
实现方法
方法1:使用tidyverse工具链(dplyr + tidyr)
代码可读性强,适合结构化数据处理场景:
library(tidyverse) # 计算每行总和,生成百分比列,保留原数据列 df_with_pct <- df %>% rowwise() %>% mutate(total = sum(c_across(`1`:`10`))) %>% mutate(across(`1`:`10`, ~ .x / total * 100, .names = "pct{col}")) %>% ungroup() %>% select(-total) # 可选:不需要总和列则删除此行
方法2:使用Base R
无需加载额外包,适合习惯原生R语法的用户:
# 提取数值列 num_cols <- df[, paste0(1:10)] # 计算每行总和 row_totals <- rowSums(num_cols) # 生成百分比矩阵 pct_matrix <- t(t(num_cols) / row_totals) * 100 # 重命名百分比列 colnames(pct_matrix) <- paste0("pct", 1:10) # 合并原数据与百分比列 df_with_pct <- cbind(df, pct_matrix)
验证百分比总和
可快速验证每个地区的百分比总和是否为100%:
# tidyverse方式验证 df_with_pct %>% rowwise() %>% mutate(pct_total = sum(c_across(pct1:pct10))) %>% select(LONGNAME, pct_total) # Base R方式验证 rowSums(df_with_pct[, paste0("pct", 1:10)])
内容的提问来源于stack exchange,提问作者Ed_Gravy
相关产品推荐
相关产品推荐

