Использование CUT и Quartile для генерации разрывов в функции R

Следуя отличным советам до, я сейчас пишу свою вторую функцию R и использую подобную логику. Тем не менее, я пытаюсь автоматизировать немного больше и может быть слишком умным для моего собственного блага.

Я хочу разбить клиентов на квинтили на основе количества заказов. Вот мой код для этого:

# sample data
clientID <- round(runif(200,min=2000, max=3000),0)
orders <- round(runif(200,min=1, max=50),0)

df <- df <- data.frame(cbind(clientID,orders))

#function to break them into quintiles
ApplyQuintiles <- function(x) {
  cut(x, breaks=c(quantile(df$orders, probs = seq(0, 1, by = 0.20))), 
      labels=c("0-20","20-40","40-60","60-80","80-100"))
}

#Add the quintile to the dataframe
df$Quintile <- sapply(df$orders, ApplyQuintiles)

table(df$Quintile)

0-20   20-40   40-60    60-80   80-100 
40     39      44       38      36

Вы увидите здесь, что в моих образцовых данных я создал 200 наблюдений, но только 197 перечислены через table. Три оконечных значения: NA

Теперь есть несколько идентификаторов клиентов, у которых есть "NA" для квинтиля. Кажется, если они были на самом низком разрыве, в этом случае 1, то они не были включены в функцию разреза.

Есть ли способ сделать cut включением всех наблюдений?

Ответ 1

Попробуйте следующее:

set.seed(700)

clientID <- round(runif(200,min=2000, max=3000),0)
orders <- round(runif(200,min=1, max=50),0)

df <- df <- data.frame(cbind(clientID,orders))

ApplyQuintiles <- function(x) {
  cut(x, breaks=c(quantile(df$orders, probs = seq(0, 1, by = 0.20))), 
      labels=c("0-20","20-40","40-60","60-80","80-100"), include.lowest=TRUE)
}
df$Quintile <- sapply(df$orders, ApplyQuintiles)
table(df$Quintile)

0-20  20-40  40-60  60-80 80-100 
  40     41     39     40     40 

Я включил include.lowest=TRUE в вашу функцию разреза, которая, похоже, заставляет ее работать. Подробнее см. ?cut.

Ответ 2

Существует также cut2 в почтенном пакете Hmisc. Он выполняет квантильные сокращения.

С помощью:

Функция, подобная разрезанным, но левым конечным точкам, включает форма [нижняя, верхняя), за исключением того, что последний интервал [нижний, верхний]. Если даны сокращения, по умолчанию убедитесь, что разрезы включают в себя весь диапазон х. Кроме того, если разрезы не заданы, вырезает x в квантиль групп (g) или групп с заданным минимальным числом наблюдений (М). Если разрез создает объект категории, cut2 создает фактор объект.

Ответ 3

Я использую аналогичную функцию для своих данных, и меня беспокоит, потому что у моих квинтильных ящиков разное количество наблюдений: это нормально? Спасибо!

jobs02.vq <- cut(meaneduc02v, breaks=c(quantile(meaneduc02v,  probs = seq(0,        1, by=0.20), 
                          na.rm=TRUE, names=TRUE, include.lowest=TRUE, right = TRUE, 
                          labels=c("1","2","3","4","5")))) # makes quintiles

И я получаю вывод:

 table(jobs02.vq, useNA='ifany')
 jobs02.vq
 [1.00,2.00) [2.00,2.51) [2.51,3.34) [3.34,4.45) [4.45,5.33]        <NA> 
     82          54          69          64          67         123 

Ответ 4

Вы можете легко выполнить это автоматически с помощью метода content в bin в OneR-пакете:

library(OneR)
set.seed(700)

clientID <- round(runif(200, min = 2000, max = 3000), 0)
orders <- round(runif(200, min = 1, max = 50), 0)
df <- data.frame(cbind(clientID, orders))

df$Quintiles <- bin(df$orders, method = "content")
table(df$Quintile)
## 
## (0.952,9.8]    (9.8,19]   (19,31.4] (31.4,38.2]   (38.2,49] 
##          40          41          39          40          40

(Полное раскрытие: я являюсь автором этого пакета)

Ответ 5

cut2 из Hmisc выполняет свою работу (параметр g определяет количество групп квантилей)

set.seed(700)

clientID <- round(runif(200,min=2000, max=3000),0)
orders <- round(runif(200,min=1, max=50),0)

df <- data.frame(cbind(clientID,orders))

library(Hmisc)
df$Quintile <- cut2(df$orders, g =5)
levels(df$Quintile) <-  c("0-20", "20-40", "40-60", "60-80", "80-100")

table(df$Quintile)
##  0-20  20-40  40-60  60-80 80-100 
##    40     41     39     40     40