I need a function like xtile in Stata, that given a vector, it returns which quantile each obs belongs to. So if the function is defined as

function xtile(vector; q= 4) #q = 4 by default returns quartiles *** returns a vector with the same size as "vector", indicating which quantile each obs belongs to. end 

I want to use it in:

@pipe df |> transform(:height => xtile => :quantiles) 

I know Stella.jl provides such functionality. But I can't install that package and now I'm wondering if there is another package for it. Or maybe I can implement it myself.

2 Answers

While using the CategoricalArrays package is a good solution and has the added benefit of actually showing what the quantiles mean, it is very easy to implement xtile using just the Julia standard library:

using Statistics function xtile(x; n=4) q = quantile(x, LinRange(0, 1, n + 1)) map(v -> min(searchsortedlast(q, v), n), x) end 

A ready-made solution can be found with the cut method provided by the CategoricalArrays.jl package, as long as you are okay with an AbstractVector of Strings:

using CategoricalArrays x = rand(10); cut(x, 4) # 10-element CategoricalArray{String,1,UInt32}: # "Q4: [0.565838, 0.85564]" # "Q2: [0.333373, 0.393529)" # "Q4: [0.565838, 0.85564]" # "Q3: [0.393529, 0.565838)" # "Q1: [0.0381196, 0.333373)" # "Q3: [0.393529, 0.565838)" # "Q4: [0.565838, 0.85564]" # "Q1: [0.0381196, 0.333373)" # "Q1: [0.0381196, 0.333373)" # "Q2: [0.333373, 0.393529)" 

If you want the quantiles as numbers, you can get the level codes by broadcasting levelcode:

a = cut(x, 4); levelcode.(a) # 10-element Array{Int64,1}: # 4 # 2 # 4 # 3 # 1 # 3 # 4 # 1 # 1 # 2 

This can be easily converted to a function that works in a pipe:

xtile(x; n=4) = levelcode.(cut(x, n)); xtile(x) # 10-element Array{Int64,1}: # 4 # 2 # 4 # 3 # 1 # 3 # 4 # 1 # 1 # 2 xtile(x, n=5) # 10-element Array{Int64,1}: # 4 # 2 # 5 # 4 # 1 # 3 # 5 # 2 # 1 # 3 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.