将表达式传递给`mapply`的`MoreArgs`

时间:2017-10-30 19:26:05

标签: r dplyr quosure

我正在使用dplyr进行一些编程,并且很好奇如何将表达式(特别是MoreArgs)参数传递给mapply

考虑一个简单的函数F,它根据某些data.frameidstime_range进行子集,然后根据其他列{{1}输出汇总统计信息}。

x

我们可以组成一些示例数据,我们可以将函数应用到require(dplyr) F <- function(ids, time_range, df, date_column, x) { date_column <- enquo(date_column) x <- enquo(x) df %>% filter(person_id %chin% ids) %>% filter(time_range[1] <= (!!date_column) & (!!date_column) <= time_range[2]) %>% summarise(newvar = sum(!!x)) }

F

我们可以成功地将我们的功能应用于每个输入。

person_ids <- lapply(1:2, function(i) sample(letters, size = 10))
time_ranges <- lapply(list(c("2014-01-01", "2014-12-31"),
                           c("2015-01-01", "2015-12-31")), as.Date)

require(data.table)
dt <- CJ(person_id = letters,
         date_col  = seq.Date(from = as.Date('2014-01-01'), to = as.Date('2015-12-31'), by = '1 day'))
dt[, z := rnorm(nrow(dt))]  # The variable we will later sum over, i.e. apply F to.

所以如果我想,我可以编写一个简单的for循环来解决我的问题。但是如果我们尝试应用语法糖并将所有内容包装在F(person_ids[[1]], time_ranges[[1]], dt, date_col, z) F(person_ids[[2]], time_ranges[[2]], dt, date_col, z) 中,我们就会收到错误。

mapply

1 个答案:

答案 0 :(得分:3)

mapply中,MoreArgs作为列表提供,但R尝试评估列表元素,从而导致错误。正如@Gregor建议的那样,您可以quote我们不想立即评估的那些MoreArgs,防止错误并允许函数继续进行。这可以使用基础quotedplyr quo

来完成
mapply(F, person_ids, time_ranges, MoreArgs = list(dt, quote(date_col), quote(z)))

mapply(F, person_ids, time_ranges, MoreArgs = list(dt, quo(date_col), quo(z)))

另一种选择是使用map2包中的purrrtidyverse包含两个输入向量的mapply等效tidyversemapply函数设置为使用非标准评估,这样可以避免使用library(purrr) map2(person_ids, time_ranges, F, dt, date_col, z) 时出现的错误,而无需引用参数:

[[1]]
    newvar
1 40.23419

[[2]]
    newvar
1 71.42327
pmap

更一般地说,你可以使用pmap(list(person_ids, time_ranges), F, dt, date_col, z) ,它在任意数量的输入向量上并行迭代:

loss = 0
loss += loss_function(pred_A, label_A)
loss += loss_function(pred_B, label_B)

loss.backward()