我的问题有working solution,但我无法使用它,因为它太慢了(我的计算预测整个模拟需要2 - 3年!)。因此,我正在寻找更好(更快)的解决方案。这(实质上)是我正在使用的代码:
N=4
x <-NULL
for (i in 1:N) { #first loop
v <-sample(0:1, 1000000, 1/2) #generate data
v <-as.data.frame(v) #convert to dataframe
v$t <-rep(1:2, each=250) #group
v$p <-rep(1:2000, each=500) #p.number
# second loop
for (j in 1:2000) { #second loop
#count rle for group 1 for each pnumber
x <- rbind(x, table(rle(v$v[v$t==1&v$p==j])))
#count rle for group 2 for each pnumber
x <- rbind(x, table(rle(v$v[v$t==2&v$p==j])))
} #end second loop
} #end first loop
#total rle counts for both group 1 & 2
y <-aggregate(x, list(as.numeric(rownames(x))), sum)
单词:代码生成一个硬币翻转模拟(v
)。生成组因子(1&amp; 2)。生成p.number因子(1:2000)。对于组1和组1,每个p.number(1:2000)记录运行长度。第2组(每个p.number都在两组中运行)。在N
循环(第一个循环)之后,总运行长度表示为一个表(聚合)(即每个组的运行长度,对于每个p.number,超过N
循环总计)。
我需要第一个循环,因为我正在使用的数据来自单个文件(因此我正在加载文件,计算各种统计信息等,然后加载下一个文件并执行相同操作)。我对第二个循环的依赖性要小得多,但无法弄清楚如何用更快的东西替换它。
第二个循环可以做些什么(希望,很多)更快?
答案 0 :(得分:8)
你承诺在R中for()
循环内生长一个物体的主要罪行。不要(我重复不)这样做。在开始时为x
分配足够的存储空间,然后在出发时填写x
。
x <- matrix(nrow = N * (2000 * 2), ncol = ??)
然后在内循环
x[ii, ] <- table(rle(....))
其中ii
是一个循环计数器,在第一个循环之前初始化为1
并在第二个循环中递增:
x <- matrix(nrow = N * (2000 * 2), ncol = ??)
ii <- 1
for(i in 1:N) {
.... # stuff here
for(j in 1:2000) {
.... # stuff here
x[ii, ] <- table(rle(....))
## increment ii
ii <- ii + 1
x[ii, ] <- table(rle(....))
## increment ii
ii <- ii + 1
} ## end inner loop
} ## end outer loop
另请注意,您正在重复使用()i
i loops which will not work.
for(is just a normal R object and so both
j`的机器人中的索引loops will be overwriting it as the progress. USe
作为第二个循环,如上所述。
首先尝试这种简单的优化,看看是否允许真实模拟在可接受的时间内完成。如果没有,请返回显示最新代码的新Q,我们可以考虑其他优化。上面的优化很简单,优化table()
和rle()
可能需要做更多的工作。注意到,您可能会查看tabulate()
函数,该函数在table()
中执行繁重工作,这可能是优化该特定步骤的一种途径。
答案 1 :(得分:2)
如果您只想分别为rle
和table
的每个值组合运行v$t
和v$p
,则无需第二个循环。它以这种方式更快:
values <- v$v + v$t * 10 + v$p * 100
runlength <- rle(values)
runlength$values <- runlength$values %% 2
x <- table(runlength)
y <- aggregate(unclass(x), list(as.numeric(rownames(x))), sum)
整个代码看起来像这样。如果N
低至4,则不断增长的对象x
将不会成为严重问题。但一般来说,我同意@GavinSimpson,它不是一个好的编程技术。
N=4
x <-NULL
for (i in 1:N) { #first loop
v <-sample(0:1, 1000000, 1/2) #generate data
v <-as.data.frame(v) #convert to dataframe
v$t <-rep(1:2, each=250) #group
v$p <-rep(1:2000, each=500) #p.number
values <- v$v + N * 10 + v$t * 100 + v$p * 1000
runlength <- rle(values)
runlength$values <- runlength$values %% 2
x <- rbind(x, table(runlength))
} #end first loop
y <-aggregate(x, list(as.numeric(rownames(x))), sum) #tota