如何在R中创建一个从两个列表中获取两个参数的函数?

时间:2016-02-13 18:06:24

标签: r functional-programming aggregate plyr mapply

我想通过验证多个数据集上的多个模型来生成包含汇总统计数据(AUC,Gini,RMSE等)的数据框。 我有x个模型(分类器 - gbm,xgb,rf等 - 所有内置在caret包中)都包含在ListOfModels中,以及y个数据集( ListOfDatasets中包含的包含多个数据点上相同变量的数据帧。

我可以通过在fun_modelStats内运行自定义函数ldply(使用模型和数据集作为参数提取模型统计数据)来创建所需数据框的简短版本 - 但是只能通过ListOfModels和一个特定的数据集或ListOfDatasets只有一个特定的模型,如下所示:

modelStats_by_model <- ldply(ListOfModels, function(model) {
  modelStats <- fun_modelStats(model, B97_2012SU_2013) 
})

modelStats_by_dataset <- ldply(ListOfDatasets, function(dataset) {
  modelStats <- fun_modelStats(gbmFit1, dataset) 
})

带有模型统计信息的结果数据框有xy行数,我无法理解使用x*y行构建此数据框的方式,即在所有数据集上验证的所有模型的统计数据。

我确实尝试了Mapmapply以及for loop,但无济于事。 使用Map我得到奇怪的错误输出:

modelStats_all <- Map(fun_modelStats, ListOfModels, ListOfDatasets)

for loop确实使用下面的代码生成所需的输出,但仅作为控制台中的纯文本,而我需要它作为数据帧。

for(i in names(ListOfModels)) {
  for(j in names(ListOfDatasets)) {
    modelStats <- fun_modelStats(ListOfModels[[i]], ListOfDatasets[[j]]) 
    print(modelStats) 
  }
} 

非常感谢您的帮助!

P.S。进一步搜索SO(How to write a function that takes a model as an argument in R - 例如此帖子)显示使用aggregate.formulaaggregate.data.framerbind.data.frame可能有所帮助,但我无法弄清楚如何。

以下是解决方案,以防任何人遇到类似问题:

fun_multiModelStats <- function(ListOfModels, ListOfDatasets) {
  multiModelStats <- data.frame()
  for(i in names(ListOfModels)) { 
    for(j in names(ListOfDatasets)) {
      model <- ListOfModels[[i]]
      dataset <- ListOfDatasets[[j]]
      modelStats <- fun_modelStats(model, dataset) 
      modelName <- names(ListOfModels[i]) 
      datasetName <- names(ListOfDatasets[j])
      modelStats <- cbind(modelName, datasetName, modelStats)
      multiModelStats <- rbind(multiModelStats, modelStats)
    }
  }
  return(multiModelStats)
} 

然而,我想找到一个没有双for循环的解决方案,而是来自apply函数族的东西。

1 个答案:

答案 0 :(得分:0)

如果您将for循环修改为以下内容会发生什么:

modelStats <- data.frame()
for(i in names(ListOfModels)) {
  for(j in names(ListOfDatasets)) {
    modelStats[i,j] <- fun_modelStats(ListOfModels[[i]], ListOfDatasets[[j]]) 
    print(modelStats) 
  }
}