Stuart
Stuart

Reputation: 1492

Julia Language: findInterval

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:

Upvotes: 4

Views: 960

Answers (1)

Colin T Bowers
Colin T Bowers

Reputation: 18560

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.

Upvotes: 4

Related Questions