快速测量图矩阵中有多少个节点是邻居的方法

时间:2018-04-06 07:04:42

标签: r matrix dplyr data.table apply

我在节点之间有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

1 个答案:

答案 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