【发布时间】:2015-01-28 17:03:07
【问题描述】:
我爱do.call。我喜欢能够将函数参数存储在列表中,然后将它们分配给给定的函数。
例如,我经常发现自己使用这种模式来拟合不同预测模型的列表,每个模型都有一些共享的和一些独特的参数:
library(caret)
global_args <- list(
x=iris[,1:3],
y=iris[,4],
trControl=trainControl(
method='cv',
number=2,
returnResamp='final',
)
)
global_args$trControl$index <- createFolds(
global_args$y,
global_args$trControl$number
)
model_specific_args <- list(
'lm' = list(method='lm', tuneLength=1),
'nn' = list(method='nnet', tuneLength=3, trace=FALSE),
'gbm' = list(
method='gbm',
verbose=FALSE,
tuneGrid=expand.grid(
n.trees=1:100,
interaction.depth=c(2, 3),
shrinkage=c(.1, .01)
)
)
)
list_of_models <- lapply(model_specific_args, function(args){
return(do.call(train, c(global_args, args), quote=TRUE))
})
resamps <- resamples(list_of_models)
dotplot(resamps, metric='RMSE')
global_args 包含对所有模型都相同的参数,model_specific_args 包含特定于模型的参数列表。我遍历model_specific_args,将每个元素与global_args 连接起来,然后使用do.call 将最终的参数列表传递给模型拟合函数。
虽然这段代码在视觉上很优雅,但它的性能却很糟糕:do.call 将整个 x 数据集直接序列化为文本,然后将其传递给模型拟合函数。如果 x 是几 GB 的数据,这会使用大量的 RAM,并且通常会失败。
print(list_of_models[[1]]$call)
有没有任何方法可以将参数列表传递给 R 中的函数,而不使用 do.call 或 call?
【问题讨论】:
-
您是否尝试过 plyr 包中的 rbind.fill。我还没有阅读代码以了解最终产品是否是数据帧,但如果是,则 rbind.fill 比等效的 do.call(rbind, ...) 快得多。在其他情况下,我也成功使用了 Reduce(.)
-
@jimmyb 我认为
rbind.fill或Reduce在这里不合适。我不是在尝试合并data.frames,而是在尝试将参数列表传递给函数。 -
this 有帮助吗?
-
@r2evans 添加
quote=TRUE会有所帮助,但do.call仍在序列化整个数据集,然后再将其传递给train。