在大矩阵中计算欧氏距离的最有效方法

raf*_*ira 5 r distance matrix geospatial r-sf

我想找到在大矩阵上计算欧几里德距离的最有效的内存和时间效率的方法。我在下面运行了这个小基准测试,比较了我知道的几个软件包:parallelDistgeodist和。我还考虑过这个结合了和 的定制函数。这是我找到的结果(如下所示),但我想知道是否有其他有效的包/解决方案来完成此任务:fieldsstatsRcppbigmemory

结果

benchmrk
#>   package   time        alloc
#>1: parDist  0.298 5.369186e-04
#>2:  fields  1.079 9.486198e-03
#>3:    rcpp 54.422 2.161113e+00
#>4:   stats  0.770 5.788603e+01
#>5: geodist  2.513 1.157635e+02

# plot
ggplot(benchmrk, aes(x=alloc , y=time, color= package, label=package)) +
  geom_label(alpha=.5) +
  coord_trans(x="log10", y="log10") +
  theme(legend.position = "none")

Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

雷普莱克斯

library(parallelDist)
library(geodist)
library(fields)
library(stats)
library(bigmemory)
library(Rcpp)

library(lineprof)
library(geobr)
library(sf)
library(ggplot2)
library(data.table)


# data input
df <- geobr::read_weighting_area()
gc(reset = T)

# convert projection to UTM
df <- st_transform(df, crs = 3857)

# get spatial coordinates
coords <- suppressWarnings(st_coordinates( st_centroid(df) ))

# prepare customized rcpp function
sourceCpp("euc_dist.cpp")

bigMatrixEuc <- function(bigMat){
  zeros <- big.matrix(nrow = nrow(bigMat)-1,
                      ncol = nrow(bigMat)-1,
                      init = 0,
                      type = typeof(bigMat))
  BigArmaEuc(bigMat@address, zeros@address)
  return(zeros)
}




### Start tests
perf_fields  <- lineprof(dist_fields <- fields::rdist(coords) )
perf_geodist <- lineprof(dist_geodist <- geodist::geodist(coords, measure = "cheap") )
perf_stats   <- lineprof(dist_stats <- stats::dist(coords) )
perf_parDist <- lineprof(dist_parDist <- parallelDist::parDist(coords, method = "euclidean") )
perf_rcpp <- lineprof(dist_rcpp <- bigMatrixEuc( as.big.matrix(coords) ) )

perf_fields$package  <- 'fields'
perf_geodist$package <- 'geodist'
perf_stats$package   <- 'stats'
perf_parDist$package <- 'parDist'
perf_rcpp$package <- 'rcpp'


# gather results
benchmrk <- rbind(perf_fields, perf_geodist, perf_stats , perf_parDist, perf_rcpp)
benchmrk <- setDT(benchmrk)[, .(time  =sum(time), alloc = sum(alloc)), by=package][order(alloc)]
benchmrk

Run Code Online (Sandbox Code Playgroud)

And*_*dré 2

在这里,我尝试从“理论上”提出一个答案。

rccp我认为方法(此处)和parDist此处)的组合可能允许处理非常大的数据集,同时将执行时间保持在可接受的水平?

不幸的是,我还没有与合作rccp过。但 parDist 和 rccp-big.matrix 方法似乎建立在相同的“基础设施”之上。RcppParallelRcppArmadillo

也许一些更有经验的用户会接受挑战。