-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnnt.Rd
151 lines (135 loc) · 5.33 KB
/
nnt.Rd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/nearest_neighbours_on_a_torus.R
\name{nnt}
\alias{nnt}
\title{Nearest Neighbour Search with Variables on a Torus}
\usage{
nnt(
data,
query = data,
k = min(10, nrow(data)),
fn = RANN::nn2,
torus,
ranges,
method = 1,
...
)
}
\arguments{
\item{data}{An \eqn{M} by \eqn{d} numeric matrix or data frame. Each of the
\eqn{M} rows contains a \eqn{d}-dimensional observation.}
\item{query}{An \eqn{N} by \eqn{d} numeric matrix or data frame. Each row
contains an \eqn{d}-dimensional point that will be queried against
\code{data}.}
\item{k}{An integer scalar. The number of nearest neighbours, of the
points in the rows of \code{query}, to find.}
\item{fn}{The function with which to calculate the nearest neighbours.
The syntax of this function must be \code{fn(data, query, k, ...)}.
The default is \code{RANN::nn2}. Another possibility is
\code{nabor::knn}.}
\item{torus}{An integer vector with element(s) in
\{1, ..., \code{ncol(data)}\}. The corresponding variables are wrapped
on the corresponding range gives in \code{ranges}.}
\item{ranges}{A \code{length(torus)} by \code{2} numeric matrix.
Row \code{i} gives the range of variation of the variable indexed by
\code{torus[i]}. \code{ranges[i, 1]} and \code{ranges[i, 2]}
are equivalent values of the variable, such as 0 degrees and 360 degrees.
If \code{length(torus)} = 1 then \code{ranges} may be a vector of length
2.}
\item{method}{An integer scalar, equal to 1 or 2. See \strong{Details}.}
\item{...}{Further arguments to be passed to \code{fn}.}
}
\value{
An object (a list) of class \code{c("nnt", "donut")} containing the
following components.
\item{nn.idx}{An \eqn{N} by \eqn{d} integer matrix of the \code{k}
nearest neighbour indices, i.e. the rows of \code{data}.}
\item{nn.dists}{An \eqn{N} by \eqn{d} numeric matrix of the \code{k}
nearest neighbour distances.}
\item{data, query, k, fn}{The arguments \code{data}, \code{query},
\code{k} and \code{fn} (in fact \code{substitute(fn)}).}
\item{torus, ranges, method}{If \code{torus} is supplied, the
arguments \code{torus}, \code{ranges} and \code{method}.}
\item{call}{The call to \code{spm}.}
}
\description{
Uses a user-supplied function to find the \code{k} nearest neighbours of
specified points in a dataset, adding the option to wrap certain variables
on a torus.
}
\details{
If \code{method = 1} then the data are partially replicated, arranged
around the original data in a way that wraps the variables in \code{torus} on their respective
ranges in \code{ranges}. Then \code{fn} is called using this replicated
dataset as the argument \code{data}. If \code{k} is large and/or
\code{data} is a sparse dataset then it is possible that a single
observation contributes more than once to a set of nearest neighbours,
which is incorrect. If this occurs then \code{nnt} uses method 2 to
correct the offending rows in \code{nn.idx} and \code{nn.dists} in the
returned list object.
If \code{method = 2} then the
following approach is used for the point in each row in \code{query}.
The data indexed by \code{torus} are shifted (and wrapped) so that the
point is located at the respective midpoints of \code{ranges}.
Method 2 is efficient only if the number of points in \code{query} is
small.
If \code{torus} is missing then \code{fn} is called using
\code{fn(data = data, query = query, k = k, ...)}, so that a call to
\code{nnt} is equivalent to a call to the function chosen by \code{fn}.
}
\examples{
got_RANN <- requireNamespace("RANN", quietly = TRUE)
got_nabor <- requireNamespace("nabor", quietly = TRUE)
set.seed(20092019)
# 2D example from the RANN:nn2 documentation (L2 metric)
x1 <- runif(100, 0, 2 * pi)
x2 <- runif(100, 0, 3)
DATA <- data.frame(x1, x2)
if (got_RANN) {
nearest <- nnt(DATA, DATA)
}
# Suppose that x1 should be wrapped
ranges1 <- c(0, 2 * pi)
query1 <- rbind(c(6, 1.3), c(2 * pi, 3), c(3, 1.5), c(4, 0))
if (got_RANN) {
res1 <- nnt(DATA, query1, k = 8, torus = 1, ranges = ranges1)
plot(res1, ylim = c(0, 3))
}
# Suppose that x1 and x2 should be wrapped
ranges2 <- rbind(c(0, 2 * pi), c(0, 3))
query2 <- rbind(c(6, 1.3), c(2 * pi, 3), c(3, 1.5), c(4, 0))
if (got_RANN) {
res2 <- nnt(DATA, query2, k = 8, torus = 1:2, ranges = ranges2)
plot(res2)
}
# Use nabor::knn (L2 metric) instead of RANN::nn2
if (got_nabor) {
res3 <- nnt(DATA, query2, k = 8, fn = nabor::knn, torus = 1:2,
ranges = ranges2)
plot(res3)
}
# 1D example
ranges <- c(0, 2 * pi)
query <- c(4, 0.1)
if (got_RANN) {
res <- nnt(x1, query, torus = 1, ranges = ranges, method = 1)
plot(res)
}
}
\references{
Arya, S., Mount, D., Kemp, S. E. and Jefferis, G. (2019)
RANN: Fast Nearest Neighbour Search (Wraps ANN Library) Using L2
Metric. R package version 2.6.1.
\url{https://CRAN.R-project.org/package=RANN}
Elseberg J., Magnenat S., Siegwart R., Nuchter, A. (2012)
Comparison of nearest-neighbor-search strategies and implementations for
efficient shape registration. \emph{Journal of Software Engineering for
Robotics (JOSER)}, \strong{3}(1), 2-12
\url{https://CRAN.R-project.org/package=nabor}
}
\seealso{
\code{\link[RANN:nn2]{RANN::nn2}},
\code{\link[nabor:knn]{nabor::knn}}: nearest neighbour searches.
\code{\link{plot.nnt}} plot method for objects returned from
\code{\link{nnt}} (1 and 2 dimensional data only).
}