【问题标题】:Faster alternative to for loop in R which calls a function with another loopR 中 for 循环的更快替代方案,它使用另一个循环调用函数
【发布时间】:2014-08-27 06:26:17
【问题描述】:

我正在尝试将一个巨大的数据集解析为 R (1.3Gb)。原始数据是一个包含 400 万个字符的列表,每个字符都是对 137 个变量的观察。

首先,我创建了一个函数,该函数根据数据集中提供的键分隔字符,其中“d”是每个字符。出于这个问题的目的,假设 d 具有这种形式

“2005400d”

关键是

varName <- c("YEAR","AGE","GENDER","STATUS")
varIn   <- c(1,5,7,8)
varEND  <- c(4,6,7,8)

其中 varIn 和 varEnd 跟踪分裂点。创建的函数是。

parseLine<-function(d){
  k<-unlist(strsplit(d,""))
  vec<-rep(NA,length(varName))
  for (i in 1:length(varName)){
    vec[i]<-paste(k[varIn[i]:varEnd[i]],sep="",collapse="")
  }
  return(vec)
}

然后为了遍历所有可用数据,我创建了一个 for 循环。

df<-data.frame(matrix(ncol=length(varName)))
names(df)<-as.character(varName)

for (i in 1:length(data)){
  df<-rbind(df,parseLine(data[i]))
}

但是,当我检查 1,000 次迭代的函数时,我得到了 10.82 秒的系统时间,但是当我将它增加到 10,000 而不是 108.2 秒时,我得到了 614.77 的时间,这表明作为数字迭代次数增加所需的时间将成倍增加。

对加快进程有什么建议吗?我尝试使用库 foreach,但它没有像我预期的那样使用并行。

m<-foreach(i=1:10,.combine=rbind) %dopar% parseLine(data[i])
df<-a
names(df)<-as.character(varName)

【问题讨论】:

  • 在你的第一个循环中,你是在做substring("2005400d", varIn, varEND) 吗?如果没有,您似乎可以使用类似的东西(也更快)
  • 你的原始数据是固定宽度的吗?那么this post 可能是相关的。
  • 不要将rbinding 保留在数据框中;创建单个数据框的列表,然后 do.call(rbind,ListOfDataFrames)

标签: r performance parsing for-loop foreach


【解决方案1】:

为什么要重新发明轮子?使用utils包中的read.fwf(默认附上)

> dat <- "2005400d"
> varName <- c("YEAR","AGE","GENDER","STATUS")
> varIn   <- c(1,5,7,8)
> varEND  <- c(4,6,7,8)
> read.fwf(textConnection(dat), col.names=varName, widths=1+varEND-varIn)
  YEAR AGE GENDER STATUS
1 2005  40      0      d

如果您指定 colClasses,您应该会获得更高的效率,但我试图证明这一点的努力未能显示出差异。也许这个建议只适用于read.table 和表亲。

【讨论】:

  • 我太笨了……非常感谢我不知道read.fwf函数……真的谢谢!!
猜你喜欢
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 2023-01-17
  • 1970-01-01
相关资源
最近更新 更多