我想在数据框中的多个列上应用多个函数。我已经研究了如何将一个函数应用于数据框中的所有列,但我很难尝试使用invoke_map来应用函数列表。我玩过quo和enquo,但我没有正确的组合(或者我还在掌握)。
玩具示例设置:
library(tidyverse)
library(RcppRoll)
library(purrr)
ID <- letters[1:26]
var1 <- sample(1:100, 26, replace= T)
var2 <- sample(100:200, 26, replace= T)
temp <- cbind(ID, var1, var2) %>% data.frame()
这适用于一个函数:
roll.var <- function(name) {
label <- enquo(name)
map_df(temp[, 2:3], ~ name(.x, 5, fill= NA)) %>%
rename_all(funs(paste0(., '.', (!!label)))) %>%
cbind(temp, .)
}
test <- roll.var(roll_sdr)
这是我尝试使用invoke_map将函数列表应用于所选列:
roll.func <- c("roll_sdr", "roll_varr")
invoke_map(roll.var, .x= roll.func)
它返回:名称错误(.x,51,fill = NA):找不到函数“name”
第二个问题是,在第一个例子生成的'test'数据框中,第一个变量命名不正确(var1 .~),而第二个变量命名为我的预期(var2.roll_sdr),可以任何一个告诉我为什么?
非常感谢任何解决方案和/或教育!
编辑:
结合Mike的解释,invoke_map需要一个列表列表,以生成我想要的完整代码:
library(tidyverse)
library(purrr)
library(RcppRoll)
library(plyr)
options(stringsAsFactors= F)
ID <- letters[1:26] %>% data.frame(ID= .)
var1 <- sample(1:100, 26, replace= T) %>% data.frame(var1= .)
var2 <- sample(100:200, 26, replace= T) %>% data.frame(var2= .)
temp <- bind_cols(ID, var1, var2)
roll.func <- list(list(roll_sdr, 'roll_sdr'),
list(roll_varr, 'roll_varr'))
roll.var <- function(name, vname) {
map_df(temp[, 2:3], ~ name(.x, 5, fill= NA)) %>%
rename_all(funs(paste0(., '.', vname))) %>%
cbind(temp, .)
}
df <- invoke_map(roll.var, roll.func)
## plyr statrment works much faster than purrr:reduce
df2 <- join_all(df, by= c('ID', 'var1', 'var2'))
是否可以在roll.var函数中添加一个语句,以便不必在roll.func中重复使用vname?以某种方式在函数内部引用名称?我玩过enquo和rlang包,我没想出正确的组合。
roll.func <- list(list(roll_sdr),
list(roll_varr))
既可以作为函数调用,也可以将标签附加到变量名。
答案 0 :(得分:1)
这有两个问题。
第一个问题是构造map_df(temp[, 2:3], ~ name(.x, 5, fill= NA))
- 这不起作用,因为它不知道name
指的是什么。在这些类型的情况下,您会发现只传递函数对象更容易,而不是函数的名称 - 也就是说,不要将它放在引号中。
第二个问题是你的构造roll.func
不正确。仔细阅读invoke_map
的文档 - 该参数必须是一个列表。列表的每个元素必须是一个列表,其元素将作为参数传递给函数。所以,这个简单的例子有效:
library(purrr)
var1 <- sample(1:100, 26, replace= T) %>% as.numeric
var2 <- sample(100:200, 26, replace= T) %>% as.numeric
temp <- cbind(var1, var2) %>% data.frame()
simple_example <- function(func) map(temp, func)
roll.func <- list(
list(mean),
list(sum)
)
invoke_map(simple_example, roll.func)
#> [[1]]
#> [[1]]$var1
#> [1] 53.42308
#>
#> [[1]]$var2
#> [1] 140.6154
#>
#>
#> [[2]]
#> [[2]]$var1
#> [1] 1389
#>
#> [[2]]$var2
#> [1] 3656
你应该能够根据自己的需要进行调整。