将...中的参数映射到summarise(.funs = funs(f1,f2),...)中的每个函数

时间:2019-02-28 13:27:23

标签: r dplyr

我需要从一个数字矢量计算几个分位数,并为此使用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。 / p>

我尝试了以下操作,但没有成功:

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))
  }
)

1 个答案:

答案 0 :(得分:0)

以下是使用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