使用rlang与purrr基于现有列子集创建新列
批量生成年份占比列的解决方案
针对你需要批量处理多年份列、避免手动逐个生成pct_good列的需求,可以结合purrr和rlang实现动态变量引用与列生成,具体步骤如下:
完整代码实现
library(dplyr) library(purrr) library(rlang) library(stringr) # 用于提取年份,也可替换为基础R方法 # 原始数据框 df <- tibble(good_2018 = 0, bad_2018 = 1, id_2018 = 0, good_2019 = 3, bad_2019 = 1, id_2019 = 1) # 提取所有唯一年份(从列名中匹配4位数字) years <- colnames(df) %>% str_extract("\\d{4}") %>% unique() %>% na.omit() # 批量生成pct_good列并合并到原数据框 df_with_pct <- df %>% bind_cols( map_dfc(years, function(year) { # 动态创建各年份对应的变量符号 good_col <- sym(paste0("good_", year)) bad_col <- sym(paste0("bad_", year)) id_col <- sym(paste0("id_", year)) # 计算占比并生成新列,动态命名列名 transmute( ., !!paste0("pct_good_", year) := if_else(!!id_col == 0, 0, 100 * !!good_col / (!!good_col + !!bad_col)) ) }) ) # 查看最终结果 print(df_with_pct)
关键步骤解释
提取年份:
从数据框的列名中提取出所有4位数字的年份,去重后得到需要处理的年份列表。如果不想依赖stringr,可以用基础R的正则替换实现:years <- sub(".*_(\\d{4})", "\\1", colnames(df)) %>% unique() %>% na.omit()动态变量与列生成:
- 用
sym()将拼接好的列名(如good_2018)转换为符号对象,让dplyr能够识别这些动态生成的列名。 - 用
!!(解引用运算符)将符号对象转换为实际的列引用,在if_else和计算式中调用对应年份的列。 - 用
:=实现动态列命名,将pct_good_年份作为新列的名称。 map_dfc会将每个年份生成的单列数据框按列合并,最终和原数据框通过bind_cols组合。
- 用
输出结果
运行代码后得到的结果与手动生成的完全一致:
#> # A tibble: 1 × 8 #> good_2018 bad_2018 id_2018 good_2019 bad_2019 id_2019 pct_good_2018 pct_good_2019 #> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 0 1 0 3 1 1 0 75
内容的提问来源于stack exchange,提问作者nicholas
相关产品推荐
相关产品推荐

