The kdtools package can be used to search for multidimensional points in a boxed region and find nearest neighbors in 1 to 9 dimensions. The package uses binary search on a sorted sequence of values. The current package is limited to matrices of real values. If you are interested in using string or mixed types in different dimensions, see the methods vignette.
Using kdtools is straightforward. There are four steps:
library(kdtools)
x = matrix(runif(3e3), nc = 3)
y = matrix_to_tuples(x)
y[1:3, c(1, 3)]
#> [,1] [,2]
#> [1,] 0.5733677 0.2927593
#> [2,] 0.4294718 0.0954285
#> [3,] 0.2323039 0.7440393
The arrayvec object can be manipulated as if it were a matrix.
kd_sort(y, inplace = TRUE, parallel = TRUE)
#> [,1] [,2] [,3]
#> [1,] 0.03935708 0.04483850 0.13760671
#> [2,] 0.11428433 0.02433274 0.14941402
#> [3,] 0.16392801 0.01743901 0.20978731
#> [4,] 0.02957904 0.05786965 0.18513709
#> [5,] 0.15379162 0.12197657 0.03686287
#> (continues for 995 more rows)
rq = kd_range_query(y, c(0, 0, 0), c(1/4, 1/4, 1/4)); rq
#> [,1] [,2] [,3]
#> [1,] 0.03935708 0.04483850 0.13760671
#> [2,] 0.11428433 0.02433274 0.14941402
#> [3,] 0.16392801 0.01743901 0.20978731
#> [4,] 0.02957904 0.05786965 0.18513709
#> [5,] 0.15379162 0.12197657 0.03686287
#> (continues for 12 more rows)
i = kd_nearest_neighbor(y, c(0, 0, 0)); y[i, ]
#> [1] 0.03935708 0.04483850 0.13760671
nns = kd_nearest_neighbors(y, c(0, 0, 0), 100); nns
#> [,1] [,2] [,3]
#> [1,] 0.5153098 0.08972472 0.249656803
#> [2,] 0.4661511 0.05807004 0.325241522
#> [3,] 0.3772204 0.40081950 0.151412885
#> [4,] 0.5428706 0.17446339 0.008342001
#> [5,] 0.2905980 0.47746206 0.110719993
#> (continues for 95 more rows)
nni = kd_nn_indices(y, c(0, 0, 0), 10); nni
#> [1] 10 3 20 17 9 5 4 2 8 1
The kd_nearest_neighbor
and kd_nn_indices
functions return row-indices. The other functions return arrayvec objects.
head(tuples_to_matrix(rq))
#> [,1] [,2] [,3]
#> [1,] 0.03935708 0.04483850 0.13760671
#> [2,] 0.11428433 0.02433274 0.14941402
#> [3,] 0.16392801 0.01743901 0.20978731
#> [4,] 0.02957904 0.05786965 0.18513709
#> [5,] 0.15379162 0.12197657 0.03686287
#> [6,] 0.14158469 0.24998390 0.15683866
head(tuples_to_matrix(nns))
#> [,1] [,2] [,3]
#> [1,] 0.5153098 0.08972472 0.249656803
#> [2,] 0.4661511 0.05807004 0.325241522
#> [3,] 0.3772204 0.40081950 0.151412885
#> [4,] 0.5428706 0.17446339 0.008342001
#> [5,] 0.2905980 0.47746206 0.110719993
#> [6,] 0.3655101 0.43035417 0.005276581
If you pass a matrix instead of an arrayvec object to any of the functions, it will be converted to an arrayvec object internally and results will be returned as matrices. This is slower and provided for convenience.