R中矩阵对象间的距离函数

R中矩阵对象间的距离函数,r,R,我有一个非常简单的问题 给定一个由x表示的N维点(例如,每个元素表示一个维度的向量)和一个由y表示的MxN维矩阵(或一组具有N个维度的M点!) set.seed(999) data <- matrix(runif(1100), nrow = 11, ncol = 10) x <- data[1, ] y <- data[2:nrow(data), ] distances <- apply(y, MARGIN = 1, function(a, b = x) { s

我有一个非常简单的问题

给定一个由
x
表示的N维点(例如,每个元素表示一个维度的向量)和一个由
y
表示的MxN维矩阵(或一组具有N个维度的M点!)

set.seed(999)
data <- matrix(runif(1100), nrow = 11, ncol = 10)

x <- data[1, ]
y <- data[2:nrow(data), ]
distances <- apply(y, MARGIN = 1, function(a, b = x) {
   sqrt(sum((a - b)^2))
})
但是,我认为这对于这个具体案例来说不是很有效,原因如下:

  • 我需要使用rbind,这是非常昂贵的内存
  • dist
    计算每个点之间的距离,但我只对其中10个距离感兴趣,或者只对
    x
    y
    的每个点之间的距离感兴趣。我对
    y
    点之间的内部距离不感兴趣
  • 由于(2)的原因,我需要手动选择距离矩阵的最后一行,以获得实际需要的距离
  • 我想到的一个可能的解决方案是通过
    y
    手动循环应用距离测量

    set.seed(999)
    data <- matrix(runif(1100), nrow = 11, ncol = 10)
    
    x <- data[1, ]
    y <- data[2:nrow(data), ]
    
    distances <- apply(y, MARGIN = 1, function(a, b = x) {
       sqrt(sum((a - b)^2))
    })
    

    distance一个选项是
    dapply
    from
    collapse

     library(collapse)
     func3 <- function(x, y) {
         dapply(y, function(a, b = x) {
                 sqrt(sum((a-b)^2))
              }, MARGIN = 1)
      }
    

    或者可以复制向量并在减去后使用
    行和

    func7 <- function(x, y) sqrt(rowSums((y-x[col(y)])^2))
    microbenchmark::microbenchmark(func1(x, y), func3(x, y), func4(x, y), func7(x, y))
    #Unit: microseconds
    #        expr    min      lq     mean  median      uq      max neval cld
    # func1(x, y) 37.605 39.7475 61.17471 40.7595 42.1865 1955.888   100   a
    # func3(x, y) 22.212 23.5945 68.63660 24.8320 25.8670 4333.933   100   a
    # func4(x, y) 21.089 22.7930 24.11542 23.5945 24.2315   58.050   100   a
    # func7(x, y)  7.731  8.9135 44.45935 10.0615 10.9500 3415.959   100   a
    

    func7更新2:如果我们假设我们有完整的数据,并且准确度高,我们可以使用rcpp实现更快的距离版本。我在下面添加了这个,最快的版本使用字节码编译器。对于那些有RcppParallel经验的人,这可能会得到进一步改进

    更新:fields包中的函数rdist是迄今为止发现的最快的方法。(见附件)。在不使用字节码编译器的情况下,它似乎速度最快

    简单地对之前的结果执行一些测试,我发现使用字节码编译器时,vapply比所有其他方法都要快(在第一次运行之后,当它第一次编译函数时,这就是为什么在字节码运行期间maxtime更大)

    我也在这里尝试了@akrun和@ThomasIsCoding的方法

    库(微基准)
    库(编译器)
    图书馆(折叠)
    图书馆(字段)
    图书馆(Rcpp)
    种子集(999)
    数据函数8(x,y)18.901 22.5510 27.91699 24.9015 29.3010 73.301 100
    编译器::enableJIT(3)
    #> [1] 0
    微基准::微基准(
    func1(x,y),
    func2(x,y),
    func3(x,y),
    函数4(x,y),
    函数5(x,y),
    函数6(x,y),
    函数7(x,y),
    函数8(x,y)
    )
    #>单位:微秒
    #>expr最小lq平均uq最大neval
    #>func1(x,y)32.100 35.9510 85.49213 39.4015 44.2510 4298.002 100
    #>func2(x,y)19.701 23.6010 45.11697 26.0505 29.6005 1732.702 100
    #>func3(x,y)19.80122.251576.96108 24.80127.6510523.201 100
    #>func4(x,y)16.30219.251077.4609420.301021.8005564.701100
    #>func5(x,y)6.201 8.5010 41.53397 9.4510 11.0510 3032.301 100
    #>func6(x,y)1.4012.30113.95802 2.7005 3.0020 1101.80100
    #>func7(x,y)14.201 16.7010 64.09999 18.6510 21.0015 4307.901 100
    #>func8(x,y)19.201 22.4500 64.33288 24.8510 27.5010 3776.101 100
    
    由(v2.0.0)于2021-04-04创建

    只是结果而已

    #普通编译器
    #>单位:微秒
    #>expr最小lq平均uq最大neval
    #>func1(x,y)37.001 42.8010 50.53103 45.4520 53.6515 138.302 100
    #>func2(x,y)20.201 25.3510 30.23096 27.8515 31.4010 70.401100
    #>func3(x,y)23.901 27.6510 55.45699 30.0010 35.7505 2248.902 100
    #>func4(x,y)20.501 23.2010 28.20101 24.6020 31.4010 119.501 100
    #>func5(x,y)6.100 8.6020 19.27804 9.6515 11.4510 891.001 100
    #>func6(x,y)1.501 2.4010 11.60706 2.9010 3.4510 848.102 100
    #>func7(x,y)14.40117.250527.7379319.751023.2510596.002 100
    #>func8(x,y)18.901 22.5510 27.91699 24.9015 29.3010 73.301 100
    #字节码编译器
    #>单位:微秒
    #>expr最小lq平均uq最大neval
    #>func1(x,y)32.100 35.9510 85.49213 39.4015 44.2510 4298.002 100
    #>func2(x,y)19.701 23.6010 45.11697 26.0505 29.6005 1732.702 100
    #>func3(x,y)19.80122.251576.96108 24.80127.6510523.201 100
    #>func4(x,y)16.30219.251077.4609420.301021.8005564.701100
    #>func5(x,y)6.201 8.5010 41.53397 9.4510 11.0510 3032.301 100
    #>func6(x,y)1.4012.30113.95802 2.7005 3.0020 1101.80100
    #>func7(x,y)14.201 16.7010 64.09999 18.6510 21.0015 4307.901 100
    #>func8(x,y)19.201 22.4500 64.33288 24.8510 27.5010 3776.101 100
    
    这里是另一个基本R

    sqrt(colSums((t(y) - x)^2))
    

    速度快吗?base R中有其他选择吗?@eduardokapp它比ApplyOW快!速度非常快。非常有趣。我尝试使用
    vapply
    ,但我不知道您必须使用
    I
    @eduardokapp“索引”,默认情况下,它是按列的,就像sappy/lappy一样。因此,我们正在循环rowsGreat贡献序列。我已经用更快的Rcpp方法更新了它。我希望这会有所帮助。这与使用
    dist
    相同。正如我在问题中所说,你只是对结果进行了细分。@eduardokapp对不起,我的错。请看我的update@JoelKandiah您是否愿意将此替代方案包括在您的基准测试中?谢谢。@eduardokapp我已经更新了我的帖子,包含到目前为止找到的所有解决方案
    sqrt(colSums((t(y) - x)^2))