【问题标题】:How to compute quantiles on groups如何计算组的分位数
【发布时间】:2017-08-29 00:49:35
【问题描述】:

我想按数据分成分位数,和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 这样做的方式?

【问题讨论】:

    标签: r


    【解决方案1】:

    使用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 类似,并且应该给出相同的结果。

    【讨论】:

    • ntile 函数会任意中断关系,所以我会坚持使用cut。我同意你的观点:使用group_by 然后mutate。谢谢!
    • 我同意@Uwe,该代码适用于示例数据,但会在一个多月的同一天给出不正确的答案。只需group_by(date) 即可。
    【解决方案2】:

    为了完整起见(并纠正错误答案),这里还有一个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) 分组,后者将聚合月份中的某天,例如,1 月 1 日、2 月 1 日、3 月 1 日,等等

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

    【讨论】:

      猜你喜欢
      • 2021-11-29
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      • 2020-10-07
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多