Заполните неполный временной ряд в data.table - PullRequest
1 голос
/ 07 апреля 2020

Вопрос: В 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

Ответы [ 4 ]

4 голосов
/ 07 апреля 2020

Как насчет этого?

# 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), если хотите, чтобы даты были в порядке

2 голосов
/ 07 апреля 2020

Используйте CJ и tidyr::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
0 голосов
/ 08 апреля 2020

Вы также можете попробовать это:

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
0 голосов
/ 07 апреля 2020

Вы можете использовать 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
...