我有一个问题,我想进行模拟研究,模拟取决于两个变量x
和y
。在我的模拟研究中,x
和y
是我想要评估的潜在值的向量(如此不同的组合)。此外,对于x
和y
的每个组合,我想要多次重复(因为那里有一个随机项,x
和y
的每次运行都会有所不同。
举一个我正在处理的例子,我有以下简化的例子:
x = 1:10
y = 11:20
iterations = 2000
iter = 1
solution = array(NA,c(length(x),3,iterations))
for(i in x){
for(j in y){
for(k in 1:iterations){
z = rnorm(3) + c(i,j,1)
solution[i,,k] = z
}
}
}
然而,在我的实际问题中,在for循环中得到的代码评估起来要小得多。但是,输入结构和输出结构相同。
所以我想知道,使用上面的例子说,按顺序设置循环是最有效的,还是让k in 1:iterations
成为最外层的循环并尝试使用一些更好因为我将在网格outer()
和z
上评估函数(在此示例中为x
),所以在该1循环中排序y
命令?
此外,我对完全不同的设置和设计非常开放。在一天结束时,我希望能够获得基于x
和y
的解决方案,并对所有迭代进行平均,即apply(solution, c(1,2),mean)
正如我所建议的,这是我正在使用的实际代码。
library(survival)
iter = 2000
n = 120
base = 2
hr = 0.5
m.x = 3
m.y = m.x/hr
ANS = NULL
for (vecX in c(0.3, 0.5, 0.6, 0.7)){
out = NULL
for (vecY in c(0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95)){
m.x.p = m.x/vecX
m.y.p = m.y/vecX
m.x.n = m.x
m.y.n = m.y
n.t = round(n*base/(base+1))
n.c = n - n.t
for (ii in 1:iter){
n.t.p = rbinom(1, n.t, vecY)
n.t.n = n.t - n.t.p
n.c.p = rbinom(1, n.c, vecY)
n.c.n = n.c - n.c.p
S = c(rexp(n.t.p, log(2)/m.y.p), rexp(n.t.n, log(2)/m.y.n), rexp(n.c.p, log(2)/m.x.p), rexp(n.c.n, log(2)/m.x.n))
data1 = data.frame(Group = c(rep("T", n.t), rep("C", n.c)), dx = c(rep("P", n.t.p), rep("N", n.t.n), rep("P", n.c.p), rep("N", n.c.n)), S)
fit = survfit(Surv(data1$S)~data1$Group)
coxfit = coxph(Surv(data1$S)~data1$Group)
HR = exp(coxfit$coefficients)
p.val=summary(coxfit)$logtest["pvalue"]
out = rbind(out, c(vecX, vecY, n.t.p, n.t.n, n.c.p, n.c.n, HR, p.val))
}
}
colnames(out) = c("vecX", "vecY", "n.t.p", "n.t.n", "n.c.p", "n.c.n", "HR", "p.val")
ans = as.data.frame(out)
ANS = rbind(ANS, ans)
}
答案 0 :(得分:7)
是的,我相信理论上应该有所作为(见下面的例子)。
R使用像Fortran这样的列主要排序(与C不同),因此为了最大限度地减少缓存未命中,您希望遍历列。因此,对于填充矩阵,最佳方法是外循环具有列索引的方法。
对于n维数组,您也要记住这一点。在n = 3
的情况下,我想这意味着让图层成为最外面的循环,然后是列,然后是行。不过,我可能会在这里弄错。
我通过5000
矩阵用5000
运行了这个快速示例。我们看到差异大约50秒,fill_matrix2()
更快。
n <- 5000
A <- matrix(NA, n, n)
B <- matrix(NA, n, n)
fill_matrix1 <- function(X, val) {
for (i in 1:nrow(X)) {
for (j in 1:ncol(X)) {
X[i, j] <- val
}
}
return(X)
}
fill_matrix2 <- function(X, val) {
for (j in 1:ncol(X)) {
for (i in 1:nrow(X)) {
X[i, j] <- val
}
}
return(X)
}
system.time(fill_matrix1(A, 0))
system.time(fill_matrix2(B, 0))
答案 1 :(得分:4)
循环的顺序实际上与此无关。如果您对代码进行了分析(请参阅help("Rprof")
),您会发现CPU时间花费在survfit
和coxph
等功能上。当然在增长out
,你应该避免。预先分配out
到它的最终大小并填充它而不是增长它。