如何按区域子集计算各年度列中Brand B1的占比
问题:按区域计算Brand B1在各年度列的占比
样本数据
dff4 <- data.frame(stringsAsFactors = FALSE, check.names = FALSE, Region = c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C"), Brand = c("B1", "B2", "B3", "B4", "B5", "B1", "B2", "B3", "B4", "B5", "B1", "B2", "B3", "B4", "B5"), `2018` = c(2923, 2458, 2812, 2286, 1683, 1085, 2805, 3214, 1059, 1866, 3280, 2481, 2016, 1230, 1763), `2019` = c(2497, 2306, 2264, 3602, 3381, 1778, 2470, 2249, 2297, 3264, 1071, 2345, 3815, 3685, 1381), `2020` = c(3458, 1448, 2033, 1021, 2275, 1527, 1316, 2229, 3029, 1054, 3590, 2978, 2633, 3531, 2608), `2021` = c(1496, 2196, 1448, 2344, 3853, 3499, 1681, 3282, 1693, 2102, 2235, 2007, 3796, 3394, 2421), `2022` = c(3759, 3371, 2908, 3222, 1720, 2862, 3767, 2544, 3299, 3961, 1030, 1268, 2652, 3656, 3053))
需求说明
计算不同区域中Brand B1在2018-2022各年度列的占比,即每个区域内,B1的数值占该区域对应年度所有品牌总和的比例(类似Excel数据透视表中基于父级总计的占比计算)。
已尝试的方法及问题
- 方法1:按整列总计计算占比,未按Region子集分组
dff4 %>% mutate(across(where(is.double), ~./sum(.), .names = "perc_{.col}"))
问题:sum(.)计算的是整列的总和,不是当前区域内的总和,结果不符合需求。
- 方法2:能得到单年度正确结果,但无法批量处理所有年度列
transform(dff4, percent = ave(dff4$`2018`, dff4$Region, FUN = prop.table))
问题:只能单独处理某一列,需要为每个年度列重复编写代码,效率低。
解决方案
方案1:保留所有品牌数据,批量生成占比列
使用dplyr的group_by结合across,按区域分组后批量计算各年度列的占比:
library(dplyr) # 按Region分组,批量计算各年度列的区域内占比 dff4_result <- dff4 %>% group_by(Region) %>% mutate(across(`2018`:`2022`, ~ .x / sum(.x), .names = "perc_{.col}")) %>% ungroup() # 过滤出Brand B1的结果 dff4_b1 <- dff4_result %>% filter(Brand == "B1")
说明:group_by(Region)确保计算总和时仅针对当前区域,across(2018:2022)批量处理所有年度列,~ .x / sum(.x)计算当前行数值在区域内该年度的占比,最后过滤出B1的行即可得到目标结果。
方案2:直接生成B1的区域占比(更简洁)
如果只需要Brand B1的占比结果,无需保留其他品牌数据,可以直接在summarise中计算:
dff4_b1_perc <- dff4 %>% group_by(Region) %>% summarise(across(`2018`:`2022`, ~ .x[Brand == "B1"] / sum(.x), .names = "perc_{.col}"))
说明:.x[Brand == "B1"]提取当前区域内B1的数值,除以该区域对应年度的总和,直接得到每个区域B1的年度占比。
内容的提问来源于stack exchange,提问作者Himanshu M
相关产品推荐
相关产品推荐

