我正在使用dplyr
进行一些编程,并且很好奇如何将表达式(特别是MoreArgs
)参数传递给mapply
?
考虑一个简单的函数F
,它根据某些data.frame
和ids
对time_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
答案 0 :(得分:3)
在mapply
中,MoreArgs
作为列表提供,但R尝试评估列表元素,从而导致错误。正如@Gregor建议的那样,您可以quote
我们不想立即评估的那些MoreArgs
,防止错误并允许函数继续进行。这可以使用基础quote
或dplyr
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
包中的purrr
,tidyverse
包含两个输入向量的mapply
等效tidyverse
。 mapply
函数设置为使用非标准评估,这样可以避免使用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()