У меня есть таблица данных, содержащая значения x, y, z 10000 точек (для этого примера) в единичном кубе, и каждая точка имеет соответствующий атрибут (называемый P
). Я использовал nn2
из пакета RANN
, чтобы найти k-соседей (до 50) индексов каждой точки в радиусе 0,075 единиц от исходного data.frame (который возвращается в виде матрицы).
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
, чтобы получить соответствующие значения P
из DATA
и вычислить среднее значение 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)
Я никогда в жизни не тратил столько времени, пытаясь эффективно векторизовать один цикл! Кроме того, я не против того, чтобы использовать punting и просто делать это с помощью c ++ и Rcpp, но я подумал, что сначала спрошу здесь, чтобы узнать, есть ли в R способ сделать его масштабируемым и быстрее. Заранее спасибо!
x = DATA[c(nn.idx), P]
- и найти среднее значение с помощьюby = row(nn.idx)[as.logical(nn.idx)]
:meanP = c(rowsum(x, by)) / tabulate(by)
- person alexis_laz   schedule 24.09.2017# bdemarest solution;
elapsed = 16.22
и# Uwe solution;
elapsed = 4.94
с соответствующими объектами размера:# Int_vec = 8,000,040 long = 1,200,007,392
- person Andre Sandor   schedule 24.09.2017