【问题标题】:Data.Table: Aggregate by every two weeksData.Table:每两周汇总一次
【发布时间】:2018-01-13 11:44:36
【问题描述】:

那么让我们来看看下面的data.table。它有日期和一列数字。我想获取每个日期的星期,然后汇总(总和)每两周。

Date <- as.Date(c("1980-01-01", "1980-01-02", "1981-01-05", "1981-01-05", "1982-01-08", "1982-01-15", "1980-01-16", "1980-01-17", 
                  "1981-01-18", "1981-01-22", "1982-01-24", "1982-01-26"))
Runoff <- c(2, 1, 0.1, 3, 2, 5, 1.5, 0.5, 0.3, 2, 1.5, 4)
DT <- data.table(Date, Runoff)
DT

所以从日期,我可以很容易地得到年份和星期。

DT[,c("Date_YrWeek") := paste(substr(Date,1,4), week(Date), sep="-")][]

我正在苦苦挣扎的是每两周汇总一次。 我以为我会得到每周的第一个日期并使用这些值进行过滤。不幸的是,那太愚蠢了。

DT[,.(min(Date)),by=.(Date_YrWeek)][order(Date)]

最终结果将是每两周的总和。

weeks    sum_value
1 and 2  ...
3 and 4  ...
5 and 6  ...

任何人都有使用 data.table 的有效方法吗?

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    1) 将两周时间段定义为从最短日期开始。然后我们可以像这样得到每个此类时期的总径流。

    DT[, .(sum_value = sum(Runoff)), 
         keyby = .(Date = 14 * (as.numeric(Date - min(Date)) %/% 14) + min(Date))]
    

    给出以下内容,其中 Date 列是两周期间的第一天的日期。

             Date sum_value
    1: 1980-01-01       3.0
    2: 1980-01-15       2.0
    3: 1980-12-30       3.1
    4: 1981-01-13       2.3
    5: 1981-12-29       2.0
    6: 1982-01-12       6.5
    7: 1982-01-26       4.0
    

    2)如果您更喜欢问题中第一列显示的文字,那么:

    DT[, .(sum_value = sum(Runoff)), 
        keyby = .(two_week = as.numeric(Date - min(Date)) %/% 14)][
        , .(weeks = paste(2*two_week + 1, "and", 2*two_week + 2), sum_value)]
    

    给予:

             weeks sum_value
    1:     1 and 2       3.0
    2:     3 and 4       2.0
    3:   53 and 54       3.1
    4:   55 and 56       2.3
    5: 105 and 106       2.0
    6: 107 and 108       6.5
    7: 109 and 110       4.0
    

    更新:修订和添加 (2)。

    【讨论】:

      【解决方案2】:

      使用 tidyverse 和 lubridate:

      library(tidyverse)
      library(lubridate)
      
      summary <- DT %>% 
                    mutate(TwoWeeks = round_date(Date, "2 weeks")) %>%
                    group_by(TwoWeeks) %>%
                    summarise(sum_value = sum(Runoff))
      summary
      # A tibble: 9 × 2
          TwoWeeks sum_value
            <date>     <dbl>
      1 1979-12-30       3.0
      2 1980-01-13       1.5
      3 1980-01-20       0.5
      4 1981-01-04       3.1
      5 1981-01-18       0.3
      6 1981-01-25       2.0
      7 1982-01-10       2.0
      8 1982-01-17       5.0
      9 1982-01-24       5.5
      

      Lubridate 的 round_date() 将聚合您可以通过大小和单位指定的范围内的日期,在本例中为“2 周”。 round_date() 的输出是该期间的第一个日历日。

      【讨论】:

      • lubridate::round_date(..., "2 weeks") 使用Multi-unit not supported for weeks 发出警告,并且不执行所需的操作。而且由于 this 答案显示每周而不是每两周,因此似乎警告被禁止,这里使用的包至少有一年的历史(github.com/tidyverse/lubridate/commit/…),或者其他什么。请参阅stackoverflow.com/a/65688058/3358272 了解替代方案。
      猜你喜欢
      • 2012-11-13
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      • 2018-06-02
      • 2016-07-31
      • 1970-01-01
      • 2016-02-08
      相关资源
      最近更新 更多