我在编写代码时遇到了一些麻烦,这需要花费大量时间才能运行。有人可以给我些帮助吗?预先感谢!
all_dist=c()
ddim=dim(b)[1]
ddimi=ddim-1
for (k in 1:dim(b)[2]){
for (i in seq(1,ddimi,1)){
for (j in seq(i+1,ddim,1)){
ze=(b[i,k])-(b[j,k])*(b[i,k])-(b[j,k])
all_dist=c(all_dist,ze)
}}}
请注意:
str(b)
num [1:5,1:30007] -0.000292 -0.001384 -0.001412 -0.002603 -0.002848 ... -attr(*,“ dimnames”)=列表2 .. $:NULL .. $:chr [1:30007]“ V1”“ V2”“ V3”“ V4” ...
答案 0 :(得分:1)
set.seed(0)
b <- matrix(rnorm(5*30007), nrow=5)
all_dist=c()
ddim=dim(b)[1]
ddimi=ddim-1
system.time(
#With foor-Loop
for (k in 1:dim(b)[2]){
for (i in seq(1,ddimi,1)){
for (j in seq(i+1,ddim,1)){
ze=(b[i,k])-(b[j,k])*(b[i,k])-(b[j,k])
all_dist=c(all_dist,ze)
}}}
)
# User System verstrichen
# 104.568 3.636 108.206
#Vectorized with matrix indices
system.time({
K <- 1:dim(b)[2] #for (k in 1:dim(b)[2]){... creates this vector
I <- seq(1,ddimi,1) #for (i in seq(1,ddimi,1)){... creates this vector
J <- unlist(lapply(I+1, function(x) seq(x,ddim,1))) #for (j in seq(i+1,ddim,1)){... creates this vector
IK <- as.matrix(expand.grid(I, K)) #Get all combinations between I and K as you will have with the nested for loops of k and i
IK <- IK[rep(seq_len(nrow(IK)), rep((ddim-1):1,length.out=nrow(IK))),] #IK-rows need to be repeated, as it is used repeatedly in the "for (j in seq(i+1,ddim,1)){" loop
JK <- as.matrix(expand.grid(j=J, k=K)) #Get all combinations between J and K as you will have with the nested for loops of k and j
#Now you have all the indexes of your for loop as vectors and can make the calculations
tt <- b[IK] - b[JK] * b[IK] - b[JK]
})
# User System verstrichen
# 0.056 0.000 0.097
identical(all_dist, tt)
#[1] TRUE
当您仅在左侧使用k
而不与其他循环交互时,只需离开k循环和索引就可以部分向量化。
system.time({
tt=c()
for (i in seq(1,ddimi,1)){
for (j in seq(i+1,ddim,1)){
tt=c(tt, (b[i,])-(b[j,])*(b[i,])-(b[j,]))
}}
dim(tt) <- c(30007, 10)
tt <- as.vector(t(tt))
})
# User System verstrichen
# 0.017 0.000 0.017
identical(all_dist, tt)
#[1] TRUE
或者您可以将内部两个for循环替换为索引向量,并进行Apply循环,而不是k-for循环:
system.time({
I <- seq(1,ddimi,1)
J <- unlist(lapply(I+1, function(x) seq(x,ddim,1)))
I <- I[rep(seq_along(I), rep((ddim-1):1,length.out=length(I)))]
tt <- as.vector(apply(b, 2, function(x) {x[I] - x[J] * x[I] - x[J]}))
})
# User System verstrichen
# 0.085 0.000 0.085
identical(all_dist, tt)
#[1] TRUE
gersht中好的解决方案的使用时间:
system.time({
mat <- as.vector(sapply(as.data.frame(b), function(x) {y <- combn(x, 2); y[1,] - y[2,] * y[1,] - y[2,]}))
})
# User System verstrichen
# 1.083 0.000 1.082
identical(all_dist, mat)
#[1] TRUE
答案 1 :(得分:1)
For循环和使用c()
来增加向量会使您放慢速度。最好尝试利用矢量化的优势,并尽可能多地使用* apply(或map)功能。通过使用sapply
遍历各列,创建组合并计算这些组合的乘积和差异,可以完成以下两项工作:
mat <- sapply(b, function(x) {y <- combn(x, 2); y[1,] - y[2,] * y[1,] - y[2,]})
它应该很快-可能不如user10488504的非常有效的解决方案那么快,但仍然非常快。它还具有非常严格的语法,并且输出是矩阵,每个列对应于b
中的一列,您可能还会发现它很有用。
set.seed(12345)
b <- as.data.frame(matrix(runif(5*30007, -.001, -.0003), byrow = T, nrow = 5))