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))
})
但是,我认为这对于这个具体案例来说不是很有效,原因如下:
dist
计算每个点之间的距离,但我只对其中10个距离感兴趣,或者只对x
和y
的每个点之间的距离感兴趣。我对y
点之间的内部距离不感兴趣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
fromcollapse
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))