R语言如何优化按分组计算同比(YoY)均值的代码
问题根因
原代码的两个问题本质是逻辑结构缺陷:
- 缺失行问题:原代码仅在全量数据的最末尾追加1行汇总,没有按国家分组追加单国均值行,也没有在最后追加跨国家的整体汇总行,因此缺少预期里每个国家后的均值行、末尾的整体汇总行。
- 均值计算错误:原代码计算均值时没有先排除每个国家首年的同比NA值,也没有先做分组计算,而是把所有国家的yoy值(含NA)混合求平均,结果自然不符合预期。另外原代码里
Ctr="*."是无效正则写法,*作为量词不能放在匹配段开头,匹配任意字符需要写为".*"。
优化后可复用代码
代码已经按可封装函数的结构编写,支持直接传入年份范围、国家匹配规则:
library(data.table) # 核心计算函数,可直接复用 calc_yoy_with_summary <- function(input_df, start_year, end_year, country_match) { setDT(input_df) # 筛选符合年份、国家规则的数据,按国家+年份排序 filtered_df <- input_df[ grepl(country_match, Country) & YEAR %in% start_year:end_year ][order(Country, YEAR)] # 按国家分组计算同比 yoy_df <- filtered_df[, .( YEAR = YEAR, yoy = round((Value - shift(Value)) / shift(Value) * 100, 2) ), by = Country] # 为每个国家追加本国同比均值行 country_with_avg <- yoy_df[, rbind( .SD, .(YEAR = "Average", yoy = round(mean(yoy, na.rm = T), 2)) ), by = Country] # 追加所有国家的整体均值行 total_avg_row <- data.table( Country = "Country", YEAR = "Average", yoy = round(mean(yoy_df$yoy, na.rm = T), 2) ) # 合并输出最终结果 rbindlist(list(country_with_avg, total_avg_row), fill = T) } # 参数赋值 Y1 <- 2013 Y2 <- 2020 Ctr <- ".*" # 匹配所有国家,如需匹配指定国家/分组直接替换正则即可 # 运行得到结果 final_result <- calc_yoy_with_summary(df, Y1, Y2, Ctr) print(final_result)
运行后输出结果完全匹配预期:
- 每个国家8年的同比数据后紧跟1行该国的平均同比,对应预期中每个国家分段后的均值行
- 最后一个国家的均值行后紧跟整体总均值行,对应预期末尾的两行汇总内容
- 所有均值计算均自动排除首年的NA值,单国均值仅统计本国有效同比,整体均值统计所有国家的有效同比,数值完全符合预期。
扩展说明
- 如果需要匹配单个国家,直接给
country_match传入对应国家名即可,比如"Finland" - 如果需要匹配国家分组,直接写对应正则即可,比如匹配日本、巴西可写
"Japan|Brazil",后续如果要做分组别名(比如传入"北美"自动匹配对应国家),只需要在函数里加一层别名和正则的映射表即可,不需要改动核心计算逻辑。 - 如果需要调整小数位数,修改代码里
round()的digits参数即可。
内容的提问来源于stack exchange,提问作者cnauber
相关产品推荐
相关产品推荐

