【问题标题】:dplyr pass function name to summarizedplyr 传递函数名来总结
【发布时间】:2018-03-20 17:30:33
【问题描述】:

我有一个使用 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")

【问题讨论】:

  • 你可以使用get
  • 为什么将名称作为字符串传递,而不是传递实际函数?

标签: r dplyr


【解决方案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

【讨论】:

  • 为什么是“……ish”? R 中的函数和其他值之间几乎没有区别(函数带有一些特殊属性——它们的定义环境——但这不是限制)。
  • 好吧,我不认为“一流”有一个普遍接受的数学定义,但我会说某些限制证明“-ish”是合理的(例如,您可以将它们存储在列表中但不能一个原子向量或一个数据框)。我会说像 Haskell 这样的 R 远亲具有一流的功能,而没有“-ish”。至少我是这么想的,这件事可能不是柏拉图式的事实!
  • 还有很多其他的东西也不能存储在向量和 DF 中;至少:列表、配对列表和环境(但这些确实不是一流的)。你不考虑在 R 中列出一等公民吗?
  • 嗯,是的,我再次认为这里的术语不是很精确。取决于我想的“头等舱”的概念。我的 R 心智模型肯定会像对待任何其他值一样对待函数,但这更像是一个直观的概念,而不是一个主张!
【解决方案2】:

您可以使用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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2021-01-19
    • 2017-06-06
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多