首页 文章

dplyr传递函数名称来总结

提问于
浏览
0

我有一个使用dplyr来汇总变量的函数 . 我希望能够将摘要函数的名称作为参数传递 . 下面的方法有效(使用match.fun) . 我想知道是否有更好/更简单的方法?

exampleFunction <- function(df, var, function_name, ...){
var <- enquo(var)

apply_some_function <-function(data, function_name, ...){
   FUN <- match.fun(function_name)
   FUN(data,...)
}

results <- df %>%
   summarize (result=apply_some_function(!!var, function_name,...))
}
exampleFunction(iris, Sepal.Width, "mean")
exampleFunction(iris, Sepal.Width, "min")

2 回答

  • 1

    通常不需要在R中通过其名称传递函数 - 因为函数是第一类(ish),所以几乎总是可以只传递函数本身!

    例如:

    library(dplyr)
    
    # data to illustrate
    iris <- iris[1:10, ]
    iris$Sepal.Length[1:3] <- NA
    
    # the custom summary function 
    custom_summary <- function(df, var, summary_func, ...){
      var <- enquo(var)
      df %>% summarize(res = summary_func(!!var, ...))
    }
    
    # check that we can pass params to `summary_func` via `...`:
    custom_summary(iris, var=Sepal.Length, summary_func=mean)
    custom_summary(iris, var=Sepal.Length, summary_func=mean, na.rm=TRUE)
    
    # double-check result against same thing in global env: 
    iris %>% summarize(res = mean(Sepal.Length))
    iris %>% summarize(res = mean(Sepal.Length, na.rm=TRUE))
    

    请注意,虽然在 dplyr:: 中将列名称传递给函数是令人讨厌和复杂的,但将函数作为参数传递给其他函数在R中是非常自然的事情 . 特别是当与 magrittr:: 管道结合使用时,这会启用超紧凑的摘要 . 只举一个例子:

    funcs <- c(mean=mean, mdn=median, lu=function(x) length(unique(x)))
    cols <- c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width")
    
    funcs %>% sapply(function(f) iris[, cols] %>% sapply(f))
    ##                  mean  mdn lu
    ## Petal.Length 3.758000 4.35 43
    ## Petal.Width  1.199333 1.30 22
    ## Sepal.Length 5.843333 5.80 35
    ## Sepal.Width  3.057333 3.00 23
    
  • 3

    你可以使用 summarize_at

    exampleFunction2 <- function(df, var, function_name, ...){
      var <- enquo(var)
      results <- df %>%
        summarize_at(vars(!!var), .funs = function_name,...) %>%
        setNames("result")
    }
    identical(exampleFunction2(iris, Sepal.Width, "mean"), 
              exampleFunction(iris, Sepal.Width, "mean"))
    # [1] TRUE
    

相关问题