簡體   English   中英

使用 CUT 和 Quartile 在 R 函數中生成中斷

[英]Using CUT and Quartile to generate breaks in R function

遵循之前的一些重要建議,我現在正在編寫我的第二個 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列出。 剩下的 3 個是NA

現在,有些 clientID 的五分位數為“NA”。 似乎如果它們處於最低中斷位置,在本例中為 1,則它們不包含在 cut 函數中。

有沒有辦法讓cut包含所有觀察結果?

嘗試以下操作:

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 

我在你的 cut 函數中包含了include.lowest=TRUE ,這似乎讓它起作用了。 有關詳細信息,請參閱?cut

在古老的 Hmisc 包中也有cut2 它進行分位數削減。

來自幫助:

像 cut 一樣的函數,但左端點是包含在內的,標簽的形式是 [lower, upper),除了最后一個間隔是 [lower,upper]。 如果給出了削減,默認情況下將確保削減包括 x 的整個范圍。 此外,如果未給出切割,會將 x 切割成分位數組(g 給定)或具有給定最小觀察數 (m) 的組。 cut 創建一個類別對象,而 cut2 創建一個因子對象。

您可以使用OneR 包bin函數中的content方法輕松地自動完成此操作:

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

(完全披露:我是這個包的作者)

我對我的數據使用了類似的函數,我很擔心,因為我的五分位數箱有不同數量的觀察:這樣可以嗎? 謝謝!

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 

我想要一些可以工作的東西dplyrgroup_by 我需要使用指定范圍的切割標簽。 這是我得到的

Get.breaks <- function(f, cuts, digits = 2)
{
  x <- round(quantile(f, probs = seq(1/cuts, 1 - 1/cuts, 1/cuts), names = F), digits)
  x <- sort(unique(c(0, x, Inf)))
  rm(f, cuts, digits)
  return(x)
}

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

cut <- df %>%
        mutate(lower = cut(orders, right = F
                           , breaks = Get.breaks(orders, cuts = 10, digits = 0)
                           , labels = head(Get.breaks(orders, cuts = 10, digits = 0), -1)
                           )
               , lower = as.numeric(as.character(lower))
               ) %>% 
        group_by(lower) %>% 
        summarise(.groups = "drop", N = n())

cut2 from Hmisc does de job(參數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 

適用於所有數據的簡單函數:

    cutD <- function(x,n) {
  cut(x, breaks=c(quantile(x, probs = seq(0, 1, by = 1/n),na.rm = T)), 
      include.lowest=TRUE)
}

gtools::quantcut做得很好

這會根據按Species分組的Sepal.Length變量的分位數0.33 和 0.66創建低、中和高標簽

library(dplyr)
library(gtools)
tt <- iris %>%
  group_by(Species) %>%
  mutate(
    Sepal.Length.Band = quantcut(Sepal.Length, q = c(0, 0.33, 0.66, 1), 
                                 labels = c("low", "mid", "high"))
  )

table(tt$Species, tt$Sepal.Length.Band)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM