heinheo
heinheo

Reputation: 565

Find nearest smaller number

I have a vector of numbers

f <- c(1, 3, 5, 8, 10, 12, 19, 27)

I want to compare the values in the vector to another number, and find the closest smaller value.

For example, if the input number is 18, then the closest, smaller value in the vector is 12 (position 6 in the vector). If the input is 19, then the result should be the value 19, i.e. the index 7.

Upvotes: 7

Views: 6156

Answers (7)

Richie Cotton
Richie Cotton

Reputation: 121057

In a functional programming style:

f <- c(1, 3, 6, 8, 10, 12, 19, 27)
x <- 18
Position(function(fi) fi <= x, f, right = TRUE)

Upvotes: 0

alexis_laz
alexis_laz

Reputation: 13122

There is findInterval:

findInterval(18:19, f)
#[1] 6 7

And building a more concrete function:

ff = function(x, table)
{
    ot = order(table)
    ans = findInterval(x, table[ot]) 
    ot[ifelse(ans == 0, NA, ans)]
}

set.seed(007); sf = sample(f)
sf
#[1] 27  6  1 12 10 19  8  3
ff(c(0, 1, 18, 19, 28), sf)
#[1] NA  3  4  6  1

Upvotes: 0

John
John

Reputation: 23758

I think this answer is pretty straightforward:

f <- c(1,3,6,8,10,12,19,27)
x <- 18

# find the value that is closest to x
maxless <- max(f[f <= x])
# find out which value that is
which(f == maxless)

Upvotes: 15

user227710
user227710

Reputation: 3194

Try this (not a perfect solution)

x<-c(1,3,6,8,10,12,19,27)
showIndex<-function(x,input){
 abs.diff<-abs(x-input)
 index.value<-unique(ifelse(abs.diff==0,which.min(abs.diff),which.min(abs.diff)-1))
return(index.value)
 }
 showIndex(x,12)
    [1] 6
showIndex(x,19)
[1] 7

Upvotes: 4

thelatemail
thelatemail

Reputation: 93813

Another one:

which.min(abs(18 - replace(f, f>18, Inf)))
#[1] 6

f[which.min(abs(18 - replace(f, f>18, Inf)))]
#[1] 12

Or as a function:

minsmaller <- function(x,value) which.min(abs(value - replace(x, x>value, Inf)))
minsmaller(f, 18)
#[1] 6
minsmaller(f, 19)
#[1] 7

Upvotes: 2

Gregor Thomas
Gregor Thomas

Reputation: 145765

If your vector f is always sorted, then you can do sum(f <= x)

f <- c(1,3,6,8,10,12,19,27)

x <- 18
sum(f <= x)
# [1] 6

x <- 19
sum(f <= x)
# [1] 7

Upvotes: 8

Steven Beaupr&#233;
Steven Beaupr&#233;

Reputation: 21621

You could try:

x <- 18
f <- c(1,3,6,8,10,12,19,27)

ifelse(x %in% f, which(f %in% x), which.min(abs(f - x)) - 1)

That way if x is not in f, it will return the nearest previous index. If x is in f, it will return x index.

Upvotes: 2

Related Questions