【发布时间】:2017-09-24 01:03:04
【问题描述】:
我有一个 data.table,其中包含单位立方体中 10,000 个点(对于此示例)的 x、y、z 值,每个点都有一个相应的属性(称为P)。我已经使用RANN 包中的nn2 来查找距原始data.frame 0.075 单位半径内的每个点的k-neighbors(最多50 个)索引(以矩阵形式返回)。
library(RANN)
library(data.table)
set.seed(1L) # for reproducible data
DATA <- data.table(runif(10000, 0,1),
runif(10000, 0,1),
runif(10000, 0,1),
runif(10000, 10,30))
colnames(DATA)<-c("x","y","z","P")
nn.idx <- nn2(DATA[,1:3], DATA[,1:3], k=50,
treetype = "kd", searchtype = "radius",
radius = 0.075)$nn.idx
下面的for 循环完成了这项工作,但我想知道是否有任何方法可以通过矢量化来加速它,因为这在应用到数百万个点时不会缩放?简单地说,我想使用nn.idx 从DATA 中获取对应的P 值并计算平均P,然后将其分配给DATA 中名为mean.P 的新列
for(index in 1:nrow(DATA))
DATA$mean.P[index]<-mean(DATA[nn.idx[index,], P])
出于说明目的,以下代码说明了我要计算的内容 - 对于所有点(灰点),计算给定点(红点)周围球体中所有点(橙色 + 红点)的平均值) 并将其分配给该点(红点)。迭代所有点,但以一种有效的方式进行,以适应大数据集。
library(rgl)
rgl.open()
rgl.points(DATA[1500,1], DATA[1500,2], DATA[1500,3], color ="red")
rgl.points(DATA[nn.idx[1500,],1:3], color ="orange", add=T)
rgl.points(DATA[,1:3], color ="lightgray", alpha=0.1, add=T)
在我的生活中,我从来没有花这么多时间尝试有效地矢量化一个循环!另外,我不反对直接用 c++ 和 Rcpp 来做,但我想我会先在这里问一下 R 中是否有一种方法可以使其规模化和更快。提前致谢!
【问题讨论】:
-
如果可以使用更大的数据在内存方面进行处理,您可以一次提取所有值 -
x = DATA[c(nn.idx), P]- 并通过by = row(nn.idx)[as.logical(nn.idx)]找到平均值:meanP = c(rowsum(x, by)) / tabulate(by) -
到目前为止,这两种解决方案似乎都是可行的,因此我需要进行更多测试。在我的机器(2016 Dell w/Xeon E5-2620 2.10GHz)上对它们进行基准测试,Uwe 的解决方案以牺牲第二个 data.table(确实变得巨大)为代价最快,并且 bdemarest 足够快更便宜的载体。所以 1Mil pts 和 k=100:
# bdemarest solution;elapsed = 16.22和# Uwe solution;elapsed = 4.94对应大小的对象:# Int_vec = 8,000,040 long = 1,200,007,392
标签: r matrix data.table nearest-neighbor