我在节点之间有symmetric
matrix
个距离:
set.seed(1)
dist.mat <- matrix(runif(10*10,0,1),10,10)
dist.mat[lower.tri(dist.mat)] <- t(dist.mat)[lower.tri(dist.mat)]
实际上这matrix
是40,000乘40,000
对于给定的半径范围:
radii <- seq(0,1,0.01)
对于每个节点,我想计算节点总数中的哪一部分位于该半径内,然后对所有节点进行平均。
这是我目前使用的,但我正在寻找更快的东西。
sapply(radii,function(r)
mean(apply(dist.mat,1,function(x) length(which(x <= r))/ncol(dist.mat)))
)
这是它的表现:
microbenchmark::microbenchmark(sapply(radii,function(r) mean(apply(dist.mat,1,function(x) length(which(x <= r))/ncol(dist.mat)))))
Unit: milliseconds
expr min
sapply(radii, function(r) mean(apply(dist.mat, 1, function(x) length(which(x <= r))/ncol(dist.mat)))) 2.24521
lq mean median uq max neval
2.548021 2.938049 2.748385 3.140852 7.233612 100
答案 0 :(得分:1)
这是一个不使用任何* apply的解决方案。
N <- 10
c(0, cumsum( table(cut(dist.mat, radii)) / (N*N) ))
cut
进入所需的时间间隔。
使用table
制表频率。
然后累积求和结果,因为小于prev半径的任何值也小于下一个大半径。然后平均所有节点。
第一个0是因为没有小于&lt; = 0的值。(请注意,这可能需要改进)
使用下三角矩阵可能有更好的解决方案。也许有人会出现并提供更快的解决方案。
编辑:更新时间
library(microbenchmark)
set.seed(1L)
N <- 10e2
dist.mat <- matrix(runif(N*N,0,1),N,N)
dist.mat[lower.tri(dist.mat)] <- t(dist.mat)[lower.tri(dist.mat)]
radii <- seq(0,1,0.01)
f1 <- function() {
sapply(radii,function(r)
mean(apply(dist.mat,1,function(x) length(which(x <= r))/ncol(dist.mat)))
)
}
f2 <- function() {
c(0, cumsum( table(cut(dist.mat, radii)) / (N*N) ))
}
microbenchmark(f1(),
f2(),
times=3L,
unit="relative")
#Unit: relative
# expr min lq mean median uq max neval
# f1() 8.580099 8.502072 8.501601 8.427282 8.464298 8.500692 3
# f2() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 3