R语言基于type列actual/budget值高效新增计算数据框指标变量
R数据框多条件分组计算指标简洁实现方案
问题背景
数据框的type列包含actual(实际值)、budget(预算值)两类取值,需要新增变量计算对应业务指标,现有逐行硬编码筛选的写法繁琐冗余,适配新数据时容易出错,需要更简洁高效的实现方案。
示例原始数据
ori_data <- data.frame( category=c("A","A","A","B","B","B"), year=c(2021,2022,2022,2021,2022,2022), type=c("actual","actual","budget","actual","actual","budget"), sales=c(100,120,130,70,80,90), profit=c(3.7,5.52,5.33,2.73,3.92,3.69) )
指标计算规则
- 销售额同比增长率(sales inc%):针对
type为actual的2022年记录,计算逻辑为 当年实际销售额 / 上年同品类实际销售额 - 1
原有冗余实现代码:ori_data$sales_inc_or_budget_acheved[category=='A'&year=='2022'&type=='actual'] <- ori_data$sales[category=='A'&year=='2022'&type=='actual']/ ori_data$sales[category=='A'&year=='2021'&type=='actual']-1 - 销售额预算完成率(budget acheved%):针对
type为budget的2022年记录,计算逻辑为 当年实际销售额 / 当年同品类预算销售额
原有冗余实现代码:ori_data$sales_inc_or_budget_acheved[category=='A'&year=='2022'&type=='budget'] <- ori_data$sales[category=='A'&year=='2022'&type=='actual']/ ori_data$sales[category=='A'&year=='2022'&type=='budget']
预期结果示例
简洁实现方案
核心思路是按category分组提取基准计算值,避免逐品类硬编码筛选,新增品类时无需修改代码。
方案1:dplyr实现(推荐,代码可读性高)
library(dplyr) ori_data <- ori_data %>% group_by(category) %>% mutate( # 提前提取分组内的基准值 last_year_actual = sales[type == "actual" & year == 2021], cur_year_actual = sales[type == "actual" & year == 2022], # 按条件匹配计算规则 sales_inc_or_budget_acheved = case_when( year == 2022 & type == "actual" ~ sales / last_year_actual - 1, year == 2022 & type == "budget" ~ cur_year_actual / sales, TRUE ~ NA_real_ ) ) %>% # 删除计算用的中间辅助列 select(-last_year_actual, -cur_year_actual) %>% ungroup()
方案2:基础R实现(无需安装第三方包)
# 初始化目标列 ori_data$sales_inc_or_budget_acheved <- NA_real_ # 按品类遍历计算,自动适配所有品类 for (cat in unique(ori_data$category)) { cat_filter <- ori_data$category == cat # 提取当前品类的基准值 ly_actual_sales <- ori_data$sales[cat_filter & ori_data$year == 2021 & ori_data$type == "actual"] cy_actual_sales <- ori_data$sales[cat_filter & ori_data$year == 2022 & ori_data$type == "actual"] # 定位需要赋值的行 cy_actual_row <- cat_filter & ori_data$year == 2022 & ori_data$type == "actual" cy_budget_row <- cat_filter & ori_data$year == 2022 & ori_data$type == "budget" # 批量赋值 ori_data$sales_inc_or_budget_acheved[cy_actual_row] <- ori_data$sales[cy_actual_row] / ly_actual_sales - 1 ori_data$sales_inc_or_budget_acheved[cy_budget_row] <- cy_actual_sales / ori_data$sales[cy_budget_row] }
两种方案运行后得到的结果和原有硬编码逻辑完全一致,且后续新增品类、扩展年份时只需要调整少量判断条件即可,维护成本远低于原始写法。
内容的提问来源于stack exchange,提问作者anderwyang
相关产品推荐
相关产品推荐

