Finding the closest element to a number in a vector

Author
Published

September 24, 2015

A colleague came to my office the other day with an interesting question:

Is there a way in R to find the closest number to X in a list?

I knowing full well the power the power of R, I naturally said that surely there is such a function, but I have never used it. So I set out to find it because I am curious. It turns out there isn’t one off the shelf closest function. There are however a few solutions out there which I have collected and are bellow. To top it off there is a comparison of how fast each solution is.

solution 1

Source

Code
x=c(1:10^6)
your.number=90000.43
which(abs(x-your.number)==min(abs(x-your.number)))
[1] 90000

solution 2

Same source as before.

Code
which.min(abs(x-your.number))
[1] 90000

solution 3

From here. It requires data.table

Code
install.packages("data.table")
renv was unable to query available packages from the following repositories:
- # http://packages.deltarho.org/src/contrib -----------------------------------
error downloading 'http://packages.deltarho.org/src/contrib/PACKAGES.rds' [curl: (22) The requested URL returned error: 404]
error downloading 'http://packages.deltarho.org/src/contrib/PACKAGES.gz' [curl: (22) The requested URL returned error: 404]
error downloading 'http://packages.deltarho.org/src/contrib/PACKAGES' [curl: (22) The requested URL returned error: 404]


The following package(s) will be installed:
- data.table [1.14.8]
These packages will be installed into "~/Documents/projects/datalyst/renv/library/R-4.3/x86_64-pc-linux-gnu".

# Installing packages --------------------------------------------------------
- Installing data.table ...                     OK [linked from cache]
Successfully installed 1 package in 5.8 milliseconds.
Code
library(data.table)
dt = data.table(x, val = x) # you'll see why val is needed in a sec
setattr(dt, "sorted", "x")  # let data.table know that w is sorted
setkey(dt, x) # sorts the data

# binary search and "roll" to the nearest neighbour
# In the final expression the val column will have the you're looking for.
dt[J(your.number), roll = "nearest"]
          x   val
1: 90000.43 90000

Speed comparison

Code
## time:
# solution1
system.time(which(abs(x-your.number)==min(abs(x-your.number))))
   user  system elapsed 
  0.006   0.000   0.006 
Code
# solution2
system.time(which.min(abs(x-your.number)))
   user  system elapsed 
  0.002   0.000   0.002 
Code
# solution3
system.time(dt[J(your.number), roll = "nearest"])
   user  system elapsed 
  0.051   0.000   0.016 

To my surprise the base R functions perform pretty well, though in really large datasets data.table is worth a punt.

Reuse

Citation

BibTeX citation:
@online{domingues2015,
  author = {Domingues, António},
  title = {Finding the Closest Element to a Number in a Vector},
  date = {2015-09-24},
  url = {https://amjdomingues.com/posts/2015-09-24-finding-closest-element-to-a-number-in-a-list/},
  langid = {en}
}
For attribution, please cite this work as:
Domingues, António. 2015. “Finding the Closest Element to a Number in a Vector.” September 24, 2015. https://amjdomingues.com/posts/2015-09-24-finding-closest-element-to-a-number-in-a-list/.