如何用map函数自动批量调用自定义R函数处理多列数据?
批量调用自定义函数生成新列的解决方案
我实现了自定义函数my_function,它接收三个参数,目前通过dplyr的mutate手动为Store、Mall、Grocery分别传入对应参数生成新列。但实际场景中有大量此类列,无法手动逐个处理,希望借助map函数实现自动化批量处理,得到与手动操作一致的结果。
原代码如下:
library(dplyr) df<-data.frame( Year=c("2000","2001","2002","2003","2004","2005","2006","2007","2008","2009"), Sales=c(100,200,300,400,500,600,100,300,200,200), Store=c(100,400,300,800,900,400,800,400,300,100), Mall=c(100,600,300,200,200,300,200,500,200,400), Grocery=c(100,600,300,200,200,300,200,500,200,400), Building_Store=c(100,200,300,400,500,600,100,300,200,400), Building_Mall=c(100,400,300,800,900,400,800,400,300,600), Building_Grocery=c(100,600,300,200,200,300,200,500,200,400)) my_function <- function(x,y,z){((x-(y*lag(z))))} # 手动调用代码 estimation<-mutate(df, df_Store=my_function(Store,Sales,Building_Store), df_Mall=my_function(Mall,Sales,Building_Mall), df_Grocery=my_function(Grocery,Sales,Building_Grocery))
方法一:结合purrr::map实现批量处理
利用map思想遍历所有需要处理的类别,动态生成列名并调用函数,最终整合结果:
library(dplyr) library(purrr) # 定义需要处理的类别集合 categories <- c("Store", "Mall", "Grocery") # 使用reduce+map逻辑批量生成新列 estimation_auto <- categories %>% reduce(function(data, cat) { # 动态获取当前类别对应的列名 col_x <- sym(cat) col_z <- sym(paste0("Building_", cat)) new_col_name <- paste0("df_", cat) # 调用自定义函数生成新列 data %>% mutate(!!new_col_name := my_function(!!col_x, Sales, !!col_z)) }, .init = df)
方法二:用dplyr::across更简洁实现
如果列名命名规则固定(如Building_+类别名),可以直接用across实现,代码更简洁高效:
estimation_auto <- df %>% mutate( # 遍历指定的类别列 across(c(Store, Mall, Grocery), # 对每个列调用my_function,动态匹配对应的Building_列 ~my_function(.x, Sales, get(paste0("Building_", cur_column()))), # 指定新列的命名格式 .names = "df_{.col}") )
验证结果
两种方法生成的estimation_auto和手动生成的estimation完全一致,可通过all.equal(estimation, estimation_auto)验证。
内容的提问来源于stack exchange,提问作者silent_hunter
相关产品推荐
相关产品推荐

