在some great advice from before之后,我正在编写我的第二个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
现在,有一些对于五分位数有'NA'的clientID。看起来如果他们处于最低休息时间,在这种情况下为1,那么他们就不会被包含在切割功能中。
有没有办法让cut
包含所有观察结果?
答案 0 :(得分:20)
尝试以下方法:
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
。
答案 1 :(得分:6)
古老的Hmisc包中也有cut2。它会进行分位数削减。
来自帮助:
像剪切一样的功能,但左端点是包含的,标签是 形式[下,上],除了最后一个区间是[下,上]。 如果给出剪切,默认情况下将确保剪切包括整个剪切 x的范围。此外,如果没有给出剪切,则将x剪切为分位数 组(给定)或具有给定最小观察数的组 (M)。 cut创建了一个类别对象,而cut2创建了一个因子 对象
答案 2 :(得分:3)
您可以使用OneR package中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
(完全披露:我是这个包的作者)
答案 3 :(得分: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
答案 4 :(得分:0)
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)
答案 5 :(得分:0)
一个适用于所有数据的简单函数:
cutD <- function(x,n) {
cut(x, breaks=c(quantile(x, probs = seq(0, 1, by = 1/n),na.rm = T)),
include.lowest=TRUE)
}
答案 6 :(得分:0)
我想要一些可以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())