如何用dplyr基于列表中的公式批量创建新变量?
批量基于公式列表生成新变量的dplyr实现
问题描述
我需要基于一个动态长度的公式列表,用dplyr的mutate自动生成对应新变量。手动逐个指定公式的方式可行,但希望实现批量处理,无需关注列表长度。尝试过across(但它依赖现有变量)和map封装函数(未成功),现有代码如下:
可运行的手动代码
library("dplyr") library("purrr") library("formula.tools") t <- 10 # 需在管道中调用的常量 ut <- list( # 存储公式的列表 v1 = V.1 ~ A * B*t, v2 = V.2 ~ A+B) data <- tibble(A=rnorm(10),B=runif(10)) %>% mutate(!!lhs(ut[["v1"]]) := !!rhs(ut[["v1"]]), !!lhs(ut[["v2"]]) := !!rhs(ut[["v2"]]))
尝试失败的代码
by_formula <- function(equation){ !!lhs(equation) := !!rhs(equation) } data <- tibble(A=rnorm(10),B=runif(10)) %>% mutate(map(ut,by_formula))
可行批量处理方案
方案1:用purrr::reduce迭代添加变量
通过reduce遍历公式列表,每次为数据集添加一个新变量,适合逐步调试或需要中间步骤的场景:
library("dplyr") library("purrr") library("formula.tools") t <- 10 ut <- list( v1 = V.1 ~ A * B*t, v2 = V.2 ~ A+B) data <- tibble(A=rnorm(10),B=runif(10)) %>% reduce(ut, .f = function(df, eq) { df %>% mutate(!!lhs(eq) := !!rhs(eq)) }, .init = .)
方案2:预生成表达式后批量执行
先将所有公式转换为mutate可识别的赋值表达式,再用!!!展开一次性执行,效率最高:
library("dplyr") library("purrr") library("formula.tools") library("rlang") t <- 10 ut <- list( v1 = V.1 ~ A * B*t, v2 = V.2 ~ A+B) # 生成所有赋值表达式的列表 mutate_exprs <- map(ut, ~ expr(!!lhs(.x) := !!rhs(.x))) data <- tibble(A=rnorm(10),B=runif(10)) %>% mutate(!!!mutate_exprs)
方案3:用imap_dfc批量生成后合并
利用imap_dfc为每个公式生成包含新变量的数据集,最后合并去重:
library("dplyr") library("purrr") library("formula.tools") t <- 10 ut <- list( v1 = V.1 ~ A * B*t, v2 = V.2 ~ A+B) data <- tibble(A=rnorm(10),B=runif(10)) %>% imap_dfc(ut, ~ mutate(., !!lhs(.x) := !!rhs(.x))) %>% select(-starts_with(".")) # 移除imap_dfc生成的冗余列
内容的提问来源于stack exchange,提问作者Julian Sagebiel
相关产品推荐
相关产品推荐

