我有一个包含大约400万行数据的数据集需要循环遍历。数据结构是,有重复的ID,这些ID彼此依赖,但是ID之间的数据是独立的。对于每个ID,[i+1]行依赖于[i]行。以下是一个可重现的示例。我知道这个示例在内部函数方面并不实用,但它只是展示我所拥有的结构。
set.seed(123)
id1 = rep(1,5)
id2 = rep(2,5)
id3 = rep(3,5)
ids = c(id1,id2,id3)
month = rep(seq(1,5),3)
x = round(rnorm(15,2,5))
y = rep(0,15)
df = as.data.frame(cbind(ids,month,x,y))
for (i in 1:nrow(df)){
if(i>1 && df[i,1]==df[i-1,1]){
#Main functions go here
df[i,4] = df[i-1,4]^2+df[i,3]
}
else {
df[i,4] = 1
}
}
实际上,真实函数的1000个循环需要大约90秒,因此处理400万行需要数天。这种方式对我来说是不可行的。然而,这些ID是独立的,不需要一起运行。我的问题是:是否有一种方法可以并行运行此类循环?一个非常不优雅的解决方案是将文件分成50个部分,而不会分割ID,并在50个子文件上运行相同的代码。我想应该有一种编码的方法来解决这个问题。
编辑:添加月份列以显示为什么行彼此相关。回答下面两个评论:
1)实际上有6-7行函数要运行。我能用ifelse()和多个函数吗? 2)期望的输出将是完整的数据框。实际上有更多的列,但我需要数据框中的每一行。
ids month x y
1 1 1 -1 1
2 1 2 1 2
3 1 3 10 14
4 1 4 2 198
5 1 5 3 39207
6 2 1 11 1
7 2 2 4 5
8 2 3 -4 21
9 2 4 -1 440
10 2 5 0 193600
11 3 1 8 1
12 3 2 4 5
13 3 3 4 29
14 3 4 3 844
15 3 5 -1 712335
编辑2:我尝试使用另一篇帖子中的foreach()包,但似乎不起作用。这段代码能够运行,但我认为问题在于行是如何在核心之间分配的。如果每行都按顺序发送到不同的核心,则相同的ID永远不会在同一个核心中。
library(foreach)
library(doParallel)
set.seed(123)
id1 = rep(1,5)
id2 = rep(2,5)
id3 = rep(3,5)
ids = c(id1,id2,id3)
month = rep(seq(1,5),3)
x = round(rnorm(15,2,5))
y = rep(0,15)
df = as.data.frame(cbind(ids,month,x,y))
#setup parallel backend to use many processors
cores=detectCores()
cl <- makeCluster(cores[1]-1) #not to overload your computer
registerDoParallel(cl)
finalMatrix <- foreach(i=1:nrow(df), .combine=cbind) %dopar% {
for (i in 1:nrow(df)){
if(i>1 && df[i,1]==df[i-1,1]){
#Main functions go here
df[i,4] = df[i-1,4]^2+df[i,3]
}
else {
df[i,4] = 1
}
}
}
#stop cluster
stopCluster(cl)
ifelse
是矢量化的。 - Sotos