【问题标题】:Fill incomplete time series in data.table在 data.table 中填充不完整的时间序列
【发布时间】:2020-07-19 07:40:39
【问题描述】:

问题:data.table 中有没有办法用零填充不完整的日期序列?例如,在玩具示例中,某些日期没有显示,我希望在这些情况下使用y = 0 获得完整的日期序列。有没有类似前向填充的东西?

备注:注意我不想使用合并,您首先创建完整的日期序列,然后将其合并回初始 data.table 对象(我认为这是低效且相当慢的) .

library(data.table)

dt <- data.table(
  x = c("2020-03-28", "2020-03-29", "2020-03-31", "2020-04-05"),
  y = c(1, 5, 3, 70)
)

## Output:
            x  y
1: 2020-03-28  1
2: 2020-03-29  5
3: 2020-03-31  3
4: 2020-04-05 70

## Desired Output:
            x  y
1: 2020-03-28  1
2: 2020-03-29  5
3: 2020-03-30  0
4: 2020-03-31  3
5: 2020-04-01  0
6: 2020-04-02  0
7: 2020-04-03  0
8: 2020-04-04  0
9: 2020-04-05 70

【问题讨论】:

    标签: r data.table time-series


    【解决方案1】:

    你也可以试试这个:

    dt[, x := as.IDate(x)]
    dt[.(seq(min(x), max(x), 1)), .(y = fifelse(is.na(y), 0, y)), .EACHI, on = "x"]
    
    #             x     y
    # 1: 2020-03-28     1
    # 2: 2020-03-29     5
    # 3: 2020-03-30     0
    # 4: 2020-03-31     3
    # 5: 2020-04-01     0
    # 6: 2020-04-02     0
    # 7: 2020-04-03     0
    # 8: 2020-04-04     0
    # 9: 2020-04-05    70
    

    【讨论】:

      【解决方案2】:

      使用CJtidyr::full_seq 创建连接数据表。

      dt[, x := as.Date(x)]                               # convert x to the Date type
      dt2 <- dt[CJ(x = tidyr::full_seq(x, 1)), on = .(x)] # create the full sequence
      dt2[is.na(y), y := 0]                               # fill NAs with 0s
      dt2
      
      #             x  y
      # 1: 2020-03-28  1
      # 2: 2020-03-29  5
      # 3: 2020-03-30  0
      # 4: 2020-03-31  3
      # 5: 2020-04-01  0
      # 6: 2020-04-02  0
      # 7: 2020-04-03  0
      # 8: 2020-04-04  0
      # 9: 2020-04-05 70
      

      【讨论】:

        【解决方案3】:

        这个怎么样?

        # convert to data.table's integer date type
        dt[ , x := as.IDate(x)]
        # find the range of dates
        date_bounds = range(dt$x)
        # construct a sequence of all dates
        #   NB: this will be integers as attributes are stripped
        all_dates = date_bounds[1L]:date_bounds[2L]
        
        # construct a table with the missing dates,
        #   with y filled to 0
        missing = data.table(
          # as.IDate uses the right origin for integer input
          x = as.IDate(setdiff(all_dates, dt$x)),
          y = 0
        )
        
        dt = rbind(dt, missing)
        #             x     y
        #        <IDat> <num>
        # 1: 2020-03-28     1
        # 2: 2020-03-29     5
        # 3: 2020-03-31     3
        # 4: 2020-04-05    70
        # 5: 2020-03-30     0
        # 6: 2020-04-01     0
        # 7: 2020-04-02     0
        # 8: 2020-04-03     0
        # 9: 2020-04-04     0
        

        之后,如果您希望日期井井有条,您可以setorder(dt, x)

        【讨论】:

          【解决方案4】:

          您可以使用 complete 中的 tidyr

          library(dplyr)
          library(tidyr)
          
          dt %>%
            mutate(x = as.Date(x)) %>%
            complete(x = seq(min(x), max(x), by = "day"), fill = list(y = 0))
          
          #     x           y
          #  <date>     <dbl>
          #1 2020-03-28     1
          #2 2020-03-29     5
          #3 2020-03-30     0
          #4 2020-03-31     3
          #5 2020-04-01     0
          #6 2020-04-02     0
          #7 2020-04-03     0
          #8 2020-04-04     0
          #9 2020-04-05    70
          

          【讨论】:

          • 谢谢,这里的问题是返回了一个tibble,我想将它保存在data.table 框架中(我不想一遍又一遍地使用as.data.table)。我认为data.table 中有这个任务的便利功能
          • 如果您不想创建完整的日期序列然后合并,我不知道在data.table 中执行此操作的任何其他方法。也许一些data.table 专家会知道。
          • 这似乎仍在进行合并
          猜你喜欢
          • 2021-09-15
          • 2020-09-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-21
          相关资源
          最近更新 更多