如何向数据框列表批量应用带多参数的自定义函数?
处理数据框列表时的函数应用问题
问题场景
我有一个包含大量列标题完全一致的数据框的列表,希望对每个数据框应用同一个处理函数。尝试将单个数据框的处理代码封装成函数后,用purrr::map()应用到列表时,多次出现“Epoch或Event不存在”的错误,用.或~作为占位符也没用。
示例数据
df <- data.frame(Epoch = c(99,126,136,148,150,200,228,247,268,269,285,285,294,308,309,319,320,324,326,337,338,352,353,380,382,418,419,424,431,437,440,447,449,470,515,548,550,550,561,589,590,596,598,603,612,616,623,626,633,655,663,668,682,687,704,708,717,730,744,752,771,794,810,811,816,819,825,832,832,841,847,851,853,868,871,881,893,915,918,922,935,943), Event = c( "hypopnea","auto_trig","double_trig","auto_trig","double_trig" , "double_trig" ,"hypopnea" ,"hypopnea","auto_trig" ,"double_trig","auto_trig","double_trig" , "double_trig" ,"auto_trig", "double_trig","auto_trig", "double_trig","auto_trig", "double_trig" , "double_trig", "hypopnea","hypopnea" ,"double_trig","double_trig","hypopnea", "double_trig" ,"hypopnea" , "double_trig", "high_leak", "auto_trig", "double_trig", "auto_trig" ,"double_trig", "double_trig", "double_trig", "hypopnea", "auto_trig", "double_trig", "hypopnea", "double_trig", "auto_trig", "double_trig", "auto_trig","double_trig","double_trig","auto_trig", "auto_trig","hypopnea", "double_trig", "double_trig", "double_trig", "auto_trig", "double_trig","auto_trig", "hypopnea" , "double_trig", "double_trig", "double_trig", "double_trig", "ineffective_eff", "ineffective_eff", "double_trig", "double_trig", "high_leak", "double_trig", "hypopnea", "auto_trig", "hypopnea", "double_trig", "high_leak", "double_trig", "high_leak", "auto_trig", "double_trig", "double_trig", "double_trig", "double_trig", "auto_trig", "double_trig", "double_trig", "double_trig", "double_trig")) df2 <- data.frame(Epoch = c(98,99,126,135,141,181,183,200,236,247,257,284,308,353,353,354,380,382,418,418,431,561,733,751,841,851), Event = c("double_trig", "hypopnea", "auto_trig", "hypopnea", "hypopnea", "double_trig", "hypopnea", "double_trig", "hypopnea", "hypopnea", "hypopnea", "double_trig", "hypopnea", "double_trig", "hypopnea", "double_trig", "hypopnea", "high_leak", "hypopnea", "hypopnea", "ineffective_eff", "high_leak", "high_leak", "double_trig", "double_trig", "ineffective_eff")) List1 <- list(df, df2)
单个数据框的处理逻辑
df3 <- data.frame(Section = seq(1, max(df$Epoch/10+1), by = 1), Epoch5 = seq(1, max(df$Epoch), by =10), Epoch51 = seq(11, max(df$Epoch)+10, by = 10)) sp <- split(df$Epoch, df$Event) nms <- names(sp) E <- c(df3$Epoch5, max(df3$Epoch51)) df3 <- df3 |> cbind( sapply(nms, \(i) { sec <- findInterval(sp[[i]], E) df3$Section %in% sec |> as.integer() }) ) rm(sp, nms, E)
解决方案
错误原因
你封装函数时,大概率没有把代码中所有引用df的地方替换成函数的参数,导致函数在全局环境中查找df,而非使用map传入的每个数据框,因此触发“Epoch或Event不存在”的错误。
正确的函数封装与调用
将处理逻辑封装成接受单个数据框参数的函数,内部所有依赖原数据框的部分都改用参数引用:
library(purrr) # 封装处理函数 process_df <- function(x) { # 创建初始分组数据框 df3 <- data.frame( Section = seq(1, max(x$Epoch/10 + 1), by = 1), Epoch5 = seq(1, max(x$Epoch), by = 10), Epoch51 = seq(11, max(x$Epoch) + 10, by = 10) ) # 按Event拆分Epoch sp <- split(x$Epoch, x$Event) nms <- names(sp) E <- c(df3$Epoch5, max(df3$Epoch51)) # 绑定统计列 df3 <- df3 |> cbind( sapply(nms, \(i) { sec <- findInterval(sp[[i]], E) as.integer(df3$Section %in% sec) }) ) # 清理临时变量(可选,函数内的变量会自动回收) rm(sp, nms, E) return(df3) } # 应用到数据框列表 result_list <- map(List1, process_df)
验证结果
运行上述代码后,result_list中的每个元素就是对应数据框处理后的结果,不会再出现找不到列的错误。
内容的提问来源于stack exchange,提问作者AR459
相关产品推荐
相关产品推荐

