【问题标题】:Using dplyr within a function, non-standard evaluation在函数中使用 dplyr,非标准评估
【发布时间】:2016-10-13 09:47:27
【问题描述】:

试图了解Non-Standard Evaluation as used by dplyr,但没有成功。我想要一个简短的函数,它返回一组指定变量的汇总统计数据(N、平均值、标准差、中位数、IQR、最小值、最大值)。

我的函数的简化版本...

my_summarise <- function(df = temp,
                         to.sum = 'eg1',
                         ...){
    ## Summarise
    results <- summarise_(df,
                          n = ~n(),
                          mean = mean(~to.sum, na.rm = TRUE))
    return(results)
}

并使用一些虚拟数据运行它...

set.seed(43290)
temp <- cbind(rnorm(n = 100, mean = 2, sd = 4),
              rnorm(n = 100, mean = 3, sd = 6)) %>% as.data.frame()
names(temp) <- c('eg1', 'eg2')
mean(temp$eg1)
  [1] 1.881721
mean(temp$eg2)
  [1] 3.575819
my_summarise(df = temp, to.sum = 'eg1')
    n mean
1 100   NA

计算了N,但均值没有,不知道为什么。

最终,我希望我的功能更通用,类似于...

my_summarise <- function(df = temp,
                         group.by = 'group'
                         to.sum = c('eg1', 'eg2'),
                         ...){
    results <- list()
    ## Select columns
    df <- dplyr::select_(df, .dots = c(group.by, to.sum))
    ## Summarise overall
    results$all <- summarise_each(df,
                                  funs(n = ~n(),
                                       mean = mean(~to.sum, na.rm = TRUE)))
    ## Summarise by specified group
    results$by.group <- group_by_(df, ~to.group) %>%
                        summarise_each(df,
                                       funs(n = ~n(),
                                       mean = mean(~to.sum, na.rm = TRUE)))        
    return(results)
}

...但是在我进入这个更复杂的版本之前(我使用this example 进行指导),我需要首先在简单版本中进行评估,因为这是绊脚石,调用dplyr::select()工作正常。

感谢任何关于我哪里出错的建议。

提前致谢

【问题讨论】:

标签: r dplyr nse


【解决方案1】:

基本思想是您必须自己实际构建适当的调用,使用lazyeval 包最容易完成。

在这种情况下,您希望以编程方式创建一个类似于~mean(eg1, na.rm = TRUE) 的调用。方法如下:

my_summarise <- function(df = temp,
                         to.sum = 'eg1',
                         ...){
  ## Summarise
  results <- summarise_(df,
                        n = ~n(),
                        mean = lazyeval::interp(~mean(x, na.rm = TRUE),
                                                x = as.name(to.sum)))
  return(results)
}

当我努力工作时,我会这样做:

  1. 请记住,就像您已经拥有的 ~n() 一样,呼叫必须以 ~ 开头。
  2. 用实际变量编写正确的调用,看看它是否有效 (~mean(eg1, na.rm = TRUE))。
  3. 使用lazyeval::interp 重新创建该调用,并通过仅运行interp 来检查它以直观地查看它在做什么。

在这种情况下,我可能会经常写interp(~mean(x, na.rm = TRUE), x = to.sum)。但是运行它会给我们~mean("eg1", na.rm = TRUE),它将eg1视为一个字符而不是变量名。所以我们使用as.name,就像在vignette("nse")中教给我们的那样。

【讨论】:

  • 谢谢,我曾(盲目地)尝试使用波浪号开始对mean() 的调用,但没有发现需要使用lazyeval::interp()。是时候再看一遍小插曲了。干杯。
猜你喜欢
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
  • 2015-03-10
相关资源
最近更新 更多