3
votes

The Question: I was hoping to find a function like findInterval in R which gives inputs a scalar and a vector representing interval starting points and returns the index of what interval the scalar falls in. For instance in R:

findInterval(x = 2.6, vec = c(1.1,2.1,3.1,4.1))
#[1] 2

In this exchange someone gave a function that does this functionality in Julia (See next section). Apparently the base indexin function does this task though. I was wondering how to get indexin function (or another base function) to do this. I know Julia loops are fast and I could write a function but I would rather not do that if there is an inbuilt function and this should be a common problem.

When I try the indexin function with the same numbers I used in R above I get:

indexin([2.6], [1.1 2.1 3.1 4.1])
# 1-element Array{Int64,1}:
# 0

Which just indicates that 2.6 is not in the vector as it (as I understand) is looking to match values rather than placing a scaler in an interval.

Function from above referenced link (with my changes to input\output datatypes)

function findInterval(x::Float64,vec::Array{Float64})
    out = zeros(Int,length(x))
    vec = unique(vec)
    sort!(vec)

    for j in 1:length(x)
        if x[j] < vec[1]
            out[1] = 0
        elseif x[j] > vec[end]
            out[end] = 0
        else
            out[j] = searchsortedfirst(vec,x[j])-1 
        end
    end
    return out
end

Which works as intended:

findInterval(2.6, [1.1 2.1 3.1 4.1])
# 1-element Array{Int64,1}:
# 2

Related Questions from SO: Other questions on SO look for finding the index of exact matches between an input value and a vector:

1
Is there a question you're looking to get answered here? Or do you intend for the findInterval definition to be the answer? If so, it'd be clearer if you removed that from the question section and instead post it as an answer to your own question. This is ok! And even encouraged! meta.stackoverflow.com/questions/250204/…mbauman
Hi Matt, I was looking for how to do something like that findInterval function with a base Julia function. Based on the link above there should exist a way to do this without having to write a custom function.Stuart
If your input vector is always sorted then searchsortedlast will do what you want, although you might want to wrap it in your own function that checks for a return of 0 or length(vec) and performs whatever behaviour you want when the input x is smaller than (or greater than) every element in vec.Colin T Bowers
Hi thanks @ColinTBowers. That works great. searchsortedlast( [1.1, 2.1, 3.1, 4.1], 2.6) does the job.Stuart
No probs. I'll turn it into an answer.Colin T Bowers

1 Answers

1
votes

If your input vector is always sorted, then searchsortedlast will do what you want, e.g.

vec = [1.1, 2.1, 3.1, 4.1]
x = 2.6
searchsortedlast(vec, x)

However, note that searchsortedlast will return 0 if x < vec[1], and will return length(vec) if x > vec[end]. So you might want to write your own custom behaviour that checks for these outcomes, e.g. if you want to always return 0 if x is not in any of the intervals in vec, you could write:

function find_interval(vec, x)
    i = searchsortedlast(vec, x)
    i == length(vec) && (i = 0)
    return(i)
 end

Also, if you work a lot with sorted vectors, you might be interested in a package I've written for sorted vectors in Julia, but have never gotten around to adding to METADATA. The source of SortedVectors package is here.