cut
, если не заданы явные точки останова, делит значения на ячейки одинаковой ширины, в общем случае они не будут содержать равное количество элементов:
x <- c(1:4,10)
lengths(split(x, cut(x, 2)))
# (0.991,5.5] (5.5,10]
# 4 1
Hmisc::cut2
и ggplot2::cut_number
используйте квантили, которые обычно создают группы одинакового размера (с точки зрения количества элементов), если данные хорошо распределены и имеют приличный размер, однако это не всегда так.mltools::bin_data
может давать разные результаты, но также основывается на квантилях.
Эти функции не всегда дают точные результаты, когда данные содержат небольшое количество различных значений:
x <- rep(c(1:20),c(15, 7, 10, 3, 9, 3, 4, 9, 3, 2,
23, 2, 4, 1, 1, 7, 18, 37, 6, 2))
table(x)
# x
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# 15 7 10 3 9 3 4 9 3 2 23 2 4 1 1 7 18 37 6 2
table(Hmisc::cut2(x, g=4))
# [ 1, 6) [ 6,12) [12,19) [19,20]
# 44 44 70 8
table(ggplot2::cut_number(x, 4))
# [1,5] (5,11] (11,18] (18,20]
# 44 44 70 8
table(mltools::bin_data(x, bins=4, binType = "quantile"))
# [1, 5) [5, 11) [11, 18) [18, 20]
# 35 30 56 45
Этонеясно, было ли найдено оптимальное решение здесь.
Что такое лучший подход биннинга, это субъективный вопрос, но один разумный способ приблизиться к нему, это искать бины, которые минимизируютдисперсия вокруг ожидаемого размера корзины.
Функция smart_cut
из (моего) пакета cutr
предлагает такую функцию.Это вычислительно тяжело, хотя и должно быть зарезервировано для случаев, когда точки разреза и уникальные значения немногочисленны (что обычно имеет место в тех случаях, когда это имеет значение).
# devtools::install_github("moodymudskipper/cutr")
table(cutr::smart_cut(x, list(4, "balanced"), "g"))
# [1,6) [6,12) [12,18) [18,20]
# 44 44 33 45
Мы видим, что группы гораздо лучше сбалансированы.
"balanced"
в вызове фактически может быть заменено пользовательской функцией для оптимизации или ограничения бинов по желанию, если недостаточно метода, основанного на дисперсии.