【问题标题】:improve for loop within R function改进 R 函数中的 for 循环
【发布时间】:2012-08-07 12:35:30
【问题描述】:

我已经构建了一个基本函数来从我对几个变量感兴趣的 3 个模型中提取 AIC 和 BIC 值。但是,当它运行时,我的计算机经常停止并说它无法为向量分配 200MB(我正在使用一个大型数据集 - 超过 500K 案例,是的,我已将内存限制增加到最大 4000)。

如果我一次选择几个变量,我实际上已经设法运行它。我有兴趣一口气实际运行该函数,但也改进了我的函数代码,这样我就不必在运行它之前删除其他所有内容,也可能不必等待 30 分钟。我可能会使用修改后的 AIC 和 BIC 公式并添加其他内容,因此我宁愿保持 AIC 和 BIC 向量化不变,而不是切换到其他逻辑回归函数。我已经玩过它并添加了诸如 rm(model1) 之类的东西,但它可能几乎没有什么区别。您能否建议解决内存分配问题并可能加快功能的代码?

非常感谢

功能:

myF<-function(mydata,TotScore,group){
  BIC2<-BIC1<-BIC0<-AIC2<-AIC1<-AIC0<-rep(NA,length(ncol(mydata)))
  for (i in (1:ncol(mydata))){
    M0<-glm(mydata[,i] ~ TotScore,family=binomial,data=mydata,x=F,y=F,model=F)
    AIC0[i]<-extractAIC(M0)[2]
    BIC0[i]<-extractAIC(M0,k=log(length(M0$fitted.values)))[2]
    rm(M0)
    M1<-glm(mydata[,i] ~ TotScore+group,family=binomial,data=mydata,x=F,y=F,model=F)
    AIC1[i]<-extractAIC(M1)[2]
    BIC1[i]<-extractAIC(M1,k=log(length(M1$fitted.values)))[2]
    rm(M1)
    M2<-glm(mydata[,i] ~ TotScore+group+TotScore*group,family=binomial,data=mydata,x=F,y=F,model=F)
    AIC2[i]<-extractAIC(M2)[2]
    BIC2[i]<-extractAIC(M2,k=log(length(M2$fitted.values)))[2]
    rm(M2)
  }
  Results<-cbind(AIC0,AIC1,AIC2,BIC0,BIC1,BIC2)
  rownames(Results)<-names(mydata)
  return(Results) 
}

附:该模型可以尝试使用

##Random dataset example
v1<-sample(0:1, 500000, replace=TRUE, prob=c(.80,.20))
v2<-sample(0:1, 500000, replace=TRUE, prob=c(.85,.15))
v3<-sample(0:1, 500000, replace=TRUE, prob=c(.95,.05))
mydata<-as.data.frame(cbind(v1,v2,v3))
TotScore=rowSums(mydata)
group<-(rep (1:5,100000))
myF(mydata,TotScore,group)

【问题讨论】:

  • 欢迎来到 StackOverflow。也许如果您创建了一个 reproducible example 来展示您的问题/问题,人们会发现它更容易回答。
  • 抱歉,附上小数据集示例。

标签: r function loops


【解决方案1】:

具有离散预测变量的二项式数据的好处是您可以在不丢失信息的情况下聚合数据

set.seed(12345)
v1<-sample(0:1, 500000, replace=TRUE, prob=c(.80,.20))
v2<-sample(0:1, 500000, replace=TRUE, prob=c(.85,.15))
v3<-sample(0:1, 500000, replace=TRUE, prob=c(.95,.05))
mydata<-as.data.frame(cbind(v1,v2,v3))
mydata$TotScore <- rowSums(mydata)
mydata$group <- rep (1:5,100000)

library(reshape)
myFun2 <- function(Y, dataset){
  tmp <- as.data.frame(table(TotScore = dataset$TotScore, group = dataset$group, Response = dataset[, Y]))
  levels(tmp$Response) <- c("Failure", "Succes")
  tmp <- cast(TotScore + group ~ Response, data  = tmp, value = "Freq")
  tmp$TotScore <- as.numeric(levels(tmp$TotScore))[tmp$TotScore]
  output <- rep(NA, 6)
  names(output) <- paste(rep(c("AIC", "BIC"), 3), rep(0:2, each = 2), sep = "")
  m <- glm(cbind(Succes, Failure) ~ TotScore, data = tmp, family = binomial,
           model = FALSE, x = FALSE, y = FALSE)
  output[1:2] <- c(AIC(m), BIC(m))
  m <- glm(cbind(Succes, Failure) ~ TotScore + group, data = tmp, family = binomial,
           model = FALSE, x = FALSE, y = FALSE)
  output[3:4] <- c(AIC(m), BIC(m))
  m <- glm(cbind(Succes, Failure) ~ TotScore * group, data = tmp, family = binomial,
           model = FALSE, x = FALSE, y = FALSE)
  output[5:6] <- c(AIC(m), BIC(m))
  output
}


system.time({
  sapply(colnames(mydata)[1:3], myFun, dataset = mydata)
})
   user  system elapsed 
  3.10    0.06    3.15 

【讨论】:

  • 亲爱的蒂埃里,感谢您的所有努力。将数据减少为表格格式确实在时间和内存方面大大改善了事情。但是,简化(表)数据的 AIC 和 BIC 值与完整数据集的值不同,所以我认为它们与其他分析、经验法则等没有真正可比性。如果您尝试 BIC() 函数在表格数据和普通数据上,你会明白我的意思。 BIC 特别(“坏”),因为完整数据和表格数据的差异不一样(而模型之间的 AIC 差异是相同的,因为它不包括样本量)。
【解决方案2】:
library(difR)
data(verbal)
verbal$TotScore <- rowSums(verbal[, c(1:24)])
verbal$group <- with(verbal, factor(Gender):factor(Anger > 20))

myFun <- function(Y, dataset){
  output <- rep(NA, 6)
  names(output) <- paste(rep(c("AIC", "BIC"), 3), rep(0:2, each = 2), sep = "")
  m <- glm(as.formula(paste(Y, "~ TotScore")), data = dataset, family = binomial,
      model = FALSE, x = FALSE, y = FALSE)
  output[1:2] <- c(AIC(m), BIC(m))
  m <- glm(as.formula(paste(Y, "~ TotScore + group")), data = dataset, 
     family = binomial, model = FALSE, x = FALSE, y = FALSE)
  output[3:4] <- c(AIC(m), BIC(m))
  m <- glm(as.formula(paste(Y, "~ TotScore * group")), data = dataset, 
      family = binomial, model = FALSE, x = FALSE, y = FALSE)
  output[5:6] <- c(AIC(m), BIC(m))
  output
}

sapply(colnames(verbal)[1:2], myFun, dataset = verbal)

【讨论】:

  • 我无法显示任何速度提升(我做了类似的事情,但出于这个原因没有发布)。您能否详细说明您的解决方案如何解决内存或速度问题?
  • 你可能是对的,但这是我的错,我应该给你一个更大的数据集来尝试它,这样你就可以测试大小和时间。我现在修改了问题(见上文)。不幸的是,Thierry 的建议仍然让我的电脑死机,但还是感谢您改进了功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 2021-11-09
  • 2021-08-30
  • 2020-08-27
相关资源
最近更新 更多