【问题标题】:Map arguments in ... to each function in summarise(.funs = funs(f1, f2), ...)将 ... 中的参数映射到 summarise(.funs = funs(f1, f2), ...) 中的每个函数
【发布时间】:2019-07-22 10:29:44
【问题描述】:

我需要从一个数字向量中计算几个分位数并为此使用dplyr::summarise。这是我所拥有的:

library(dplyr)
library(rlang)

quantiles <- function(data, group, ...){
  group <- enquo(group)
  value_vars <- quos(...)
  data %>%
    group_by(!!group) %>%
    summarise_at(vars(!!!value_vars), funs(
      median = median,
      q1 = quantile(., probs = 0.25),
      q3 = quantile(., probs = 0.75))
    ) %>%
    ungroup()
}
quantiles(data = iris, group = Species, Sepal.Length, Petal.Width)

它可以工作,但在检查包时会触发变量'.'没有可见绑定的注释。所以我正在寻找一种方法来摆脱函数中的.。我可以将mutate_at 替换为summarise_at,然后用first 进行总结,但它会变得很重:

quantiles <- function(data, group, ...){
  group <- enquo(group)
  value_vars <- quos(...)
  data %>%
    group_by(!!group) %>%
    mutate_at(vars(!!!value_vars), funs(median = median)) %>%
    mutate_at(vars(!!!value_vars), funs(q1 = quantile), probs = 0.25) %>%
    mutate_at(vars(!!!value_vars), funs(q3 = quantile), probs = 0.75) %>%
    summarise_at(vars(matches('(median|q1|q3)$')), first) %>%
    ungroup()
}
quantiles(data = iris, group = Species, Sepal.Length, Petal.Width)

编辑:使用purrr:map2

我可以使用所需的辅助参数值构建函数列表:

quantile_funs <- purrr::map2(
  .x = list(median = median, q1 = quantile, q3 = quantile),
  .y = list(NULL, 0.25, 0.75),
  .f = function(fun, arg){
    function(x) fun(x, probs = arg)
  }
)

quantiles <- function(data, group, ...){
  group <- enquo(group)
  value_vars <- quos(...)
  data %>%
    group_by(!!group) %>%
    summarise_at(vars(!!!value_vars), .funs = quantile_funs) %>%
    ungroup()
}
quantiles(data = iris, group = Species, Sepal.Length, Petal.Width)

这很好用,但由于运气好,mean 有一个 ... 参数,它允许我实际执行 mean(x, probs = NULL) 而它没有任何 probs 参数。

我尝试了以下方法,但没有成功:

quantile_funs <- purrr::map2(
  .x = list(median = median, q1 = quantile, q3 = quantile),
  .y = list(list(NULL = NULL), list(probs = 0.25), list(probs = 0.75)),
  .f = function(fun, arg){
    function(x) fun(x, splice(arg))
  }
)

【问题讨论】:

  • 我建议你使用purrr 包。有很多地图功能,它们与dplyr 配合得很好。
  • 谢谢,我尝试了一些将函数映射到参数并返回部分的方法,它确实有效但有点幸运..
  • 不是一个骗子,但我不久前问了一个类似的question 并得到了很好的答案
  • 谢谢,我看了一下,确实很接近,主要区别在于我使用了不同的 mutate/summarise 函数而不是一个,不是吗?我将深入研究您提供的解决方案,我很可能会在那里找到解决方案

标签: r dplyr


【解决方案1】:

这是使用mapply 函数的一个选项:

library('data.table')
quantiles <- function(data, group, v.names, quantile = c(.25, 0.5, .75)){
  data <- as.data.table(data)
  gLevels <- levels(data[, get(group)])
  quantileDT <- as.data.table(
    expand.grid(v.name = v.names, grp = gLevels, quantile = quantile,
                stringsAsFactors = FALSE))
  quantileDT[, Value:= 
               mapply(function(v, g, q) quantile(data[get(group) == g, get(v)],  q),
                      v = v.name, 
                      g = grp, 
                      q = quantile)]

  dcast(quantileDT, grp ~ v.name + quantile, value.var = 'Value')
}

quantiles(data = iris, group = 'Species', v.names = c('Sepal.Length', 'Petal.Width'))

也许可以进行一些清理——例如使用dataquantile 作为变量名并不是一个好主意。这是你得到的输出:

          grp Petal.Width_0.25 Petal.Width_0.5 Petal.Width_0.75 Sepal.Length_0.25 Sepal.Length_0.5 Sepal.Length_0.75
1:     setosa              0.2             0.2              0.3             4.800              5.0               5.2
2: versicolor              1.2             1.3              1.5             5.600              5.9               6.3
3:  virginica              1.8             2.0              2.3             6.225              6.5               6.9

【讨论】:

  • 这确实有效,谢谢,但由于 tidyverse 的大量使用,我习惯于编写不带引号的变量名,所以我不是一个大粉丝或将它们作为字符串传递:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
  • 1970-01-01
  • 2019-04-08
相关资源
最近更新 更多