27

根据之前的一些很好的建议,我现在正在编写我的第二个 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

现在,有些客户端 ID 的五分位数为“NA”。似乎如果它们处于最低中断,在本例中为 1,那么它们不包含在 cut 函数中。

有没有办法cut包容所有的观察?

4

7 回答 7

29

尝试以下操作:

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更多详细信息,请参阅。

于 2012-07-30T19:49:06.113 回答
7

古老的 Hmisc 包中还有cut2。它进行分位数切割。

从帮助:

函数类似于 cut 但左端点包含在内,标签的形式为 [lower, upper),除了最后一个区间是 [lower,upper]。如果给出切割,默认情况下会确保切割包括 x 的整个范围。此外,如果未给出切割,则将 x 切割成分位数组(g 给定)或具有给定最小观察数(m)的组。cut 创建一个类别对象,而 cut2 创建一个因子对象。

于 2015-01-21T19:49:40.107 回答
5

您可以使用OneR 包中的函数中的content方法非常轻松地自动完成此操作:bin

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

(完全披露:我是这个包的作者)

于 2016-08-13T11:18:11.697 回答
2

我对我的数据使用了类似的函数,我很担心,因为我的五分之一箱有不同数量的观察:可以吗?谢谢!

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 
于 2015-11-13T22:49:36.650 回答
1

我想要一些可行的东西,dplyr并且group_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())
于 2021-01-23T03:19:14.290 回答
0

适用于所有数据的简单函数:

    cutD <- function(x,n) {
  cut(x, breaks=c(quantile(x, probs = seq(0, 1, by = 1/n),na.rm = T)), 
      include.lowest=TRUE)
}
于 2020-12-02T14:12:36.173 回答
-1

来自 Hmisc 的cut2确实有效(参数 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 
于 2019-07-18T11:35:38.127 回答