ntile() equivalent for equal ranges

Viewed 36

I would like to split a column of a data frame into equal sized bins. For instance, looking at a vector instead I could do

# I know it's also possible to use base cut though I always found that ugly
library(dplyr)
library(purrr)
library(magrittr)
set.seed(1234)

bins <- 4

vec <- sample(1:100, 20)

binsize <- (max(vec) - min(vec)) / bins

bin_limits <- binsize * 1:bins + min(vec)

equi_range_ntiles <- map_dbl(vec, function(x, lims = bin_limits) min(which(x <= lims)))
equi_range_ntiles

c.f. what I do not want is ntiles of equal size of groups, e.g.

ntiles <- ntile(vec, bins)
ntiles

If there is an efficient and clean way to do this I would be appreciative. From the vector I can probably generalise it but for added context my actual use case is more akin to

df <- data.frame(
  grouping = sample(1:2, 20, replace = TRUE),
  val = sample(1:100, 20)
)

df_ntiles <- df %>%
  group_by(grouping) %>%
  mutate(ntile = ntile(val, bins))

where instead of ntile I use the equivalent function from the first section. It could be the cleanest way is just to wrap my code from the first part into a function and apply that but would be surprised if there isn't something built in that I'm missing

1 Answers

You can use my package:

library(santoku)

vec <- sample(1:100, 20)
chop_evenly(vec, 10) # for 10 groups
 [1] [4, 13.5)  [42, 51.5) [32.5, 42) [70.5, 80) [70.5, 80) [89.5, 99]
 [7] [51.5, 61) [89.5, 99] [89.5, 99] [4, 13.5)  [32.5, 42) [42, 51.5)
[13] [4, 13.5)  [13.5, 23) [4, 13.5)  [13.5, 23) [23, 32.5) [32.5, 42)
[19] [61, 70.5) [80, 89.5)
10 Levels: [4, 13.5) [13.5, 23) [23, 32.5) [32.5, 42) [42, 51.5) ... [89.5, 99]

chop_evenly(vec, 4)
 [1] [4, 27.75)    [27.75, 51.5) [27.75, 51.5) [51.5, 75.25) [51.5, 75.25)
 [6] [75.25, 99]   [51.5, 75.25) [75.25, 99]   [75.25, 99]   [4, 27.75)   
[11] [27.75, 51.5) [27.75, 51.5) [4, 27.75)    [4, 27.75)    [4, 27.75)   
[16] [4, 27.75)    [27.75, 51.5) [27.75, 51.5) [51.5, 75.25) [75.25, 99]  
Levels: [4, 27.75) [27.75, 51.5) [51.5, 75.25) [75.25, 99]
Related