如何计算组的分位数

时间:2017-08-29 00:49:35

标签: r

我希望将数据分成分位数,与this great question

相同

问题是我想每天按时间顺序进行:

set.seed(123)
temp.all <- data.frame(date = c(rep(Sys.Date() - 1, 12), rep(Sys.Date(), 12)), 
    name=letters[c(1:12, 1:12)], value=rnorm(24))

目前,我正在使用for循环解决问题:

library(dplyr)
for (d in unique(temp.all$date)) {
    temp = filter(temp.all, date == d)
    temp$quartile <- with(temp, factor(
                        findInterval( val, c(-Inf,
                           quantile(val, probs=c(0.25, .5, .75)), Inf) , na.rm=TRUE), 
                        labels=c("Q1","Q2","Q3","Q4")
  ))
  # ...and doing rbind on 'temp' to reconstruct temp.all with quartiles
}

关于如何避免可怕的for循环的任何想法?可能有group_by方式吗?

2 个答案:

答案 0 :(得分:4)

使用group_by即可:

library(lubridate)

temp.all = temp.all %>%
    # lubridate::date(date) might be necessary if you have datetimes
    group_by(date) %>%
    mutate(quartile = cut(value, breaks = 4, labels = paste0("Q", 1:4)))

dplyr还有一个函数ntile,其行为应与cut类似,并且应该给出相同的结果。

答案 1 :(得分:1)

为了完整(并纠正错误的答案),这里也是一个data.table解决方案:

library(data.table)
setDT(temp.all)[, quartile := cut(value, breaks = 4L, labels = paste0("Q", 1:4)), by = date]
temp.all
          date name       value quartile
 1: 2017-08-28    a -0.56047565       Q1
 2: 2017-08-28    b -0.23017749       Q2
 3: 2017-08-28    c  1.55870831       Q4
 4: 2017-08-28    d  0.07050839       Q2
 5: 2017-08-28    e  0.12928774       Q2
 6: 2017-08-28    f  1.71506499       Q4
...
18: 2017-08-29    f -1.96661716       Q1
19: 2017-08-29    g  0.70135590       Q3
20: 2017-08-29    h -0.47279141       Q2
21: 2017-08-29    i -1.06782371       Q1
22: 2017-08-29    j -0.21797491       Q2
23: 2017-08-29    k -1.02600445       Q2
24: 2017-08-29    l -0.72889123       Q2
          date name       value quartile

请注意,结果按照OP的要求按date进行分组,而不是day(date)按{em>}汇总日期,例如1月1日,2月1日,3月1日等等。

进一步注意,只有一个额外的列quartile被添加到temp.all 到位,即不复制整个数据集以节省内存和时间(在处理大型数据集时可能会变得相关。)