使用dplyr :: summarize_each_的函数列表

Bro*_*ieG 8 r dplyr

我想的编程选择功能的列表应用于数据帧的每一列使用dplyr.为了便于说明,这是我的功能列表:

fun_list <- lapply(iris[-5], function(x) if(var(x) > 0.7) median else mean)
Run Code Online (Sandbox Code Playgroud)

我认为这会奏效:

iris %>% group_by(Species) %>% summarise_each_(funs_(fun_list), names(iris)[-5])
Run Code Online (Sandbox Code Playgroud)

根据?funs_参数应该是哪些状态,除其他外:

由...指定的函数列表函数本身,意思是

但这失败了,错误:

Error in UseMethod("as.lazy") : 
  no applicable method for 'as.lazy' applied to an object of class "function"
Run Code Online (Sandbox Code Playgroud)

似乎funs_实际上期望符号列表对应于在适当环境中定义的函数,而不是实际函数.在我的应用程序中虽然我只获取函数,而不是它们的符号名称(此外,函数可能是匿名的).

有没有一种方法来通过实际的功能,summarise_eachdplyr?注意我正在寻找dplyr答案,因为我知道如何用其他工具解决这个问题.

ber*_*ant 3

如果fun_list是函数列表,则可以在 dplyr 函数中使用它之前将其转换为“惰性对象”列表。

library(lazyeval)

fun_list2 <- lapply(fun_list, function(f) lazy(f(.)))
Run Code Online (Sandbox Code Playgroud)

或者

fun_list2 <- lapply(fun_list, function(f) lazy_(quote(f), env = environment()))
Run Code Online (Sandbox Code Playgroud)

但我不确定这是否是100%防水的方法。

更新

根据评论(每列有一个函数):

dispatch <- lazy_(quote((fun_list[[as.character(substitute(.))]](.))), env = environment())

iris %>% group_by(Species) %>% summarise_each_(funs_(dispatch), names(iris)[-5])
Run Code Online (Sandbox Code Playgroud)

这个想法是使用summarise_each_但不使用函数列表,而是使用单个调度函数。该函数接受一个变量,从原始 fun_list 中找到正确的函数(按其名称!)并使用该变量作为输入。

如果函数列表的名称与变量的名称匹配,则该解决方案有效。

还可以动态定义调度和函数列表(在这种情况下,环境不是全局的):

get_dispatch <- function(fun_list) {
    return(lazy_(quote((fun_list[[as.character(substitute(.))]](.))), env = environment())) 
}

dispatch <- get_dispatch(lapply(iris[-5], function(x) if(var(x) > 0.7) median else mean))
Run Code Online (Sandbox Code Playgroud)