用于data.table的填补缺失日期的最快方法

14
我正在从 CSV 文件中加载一个 `data.table`,其中包含日期、订单、金额等字段。
输入文件偶尔不会包含所有日期的数据。例如,如下所示:
> NADayWiseOrders
           date orders  amount guests
  1: 2013-01-01     50 2272.55    149
  2: 2013-01-02      3   64.04      4
  3: 2013-01-04      1   18.81      0
  4: 2013-01-05      2   77.62      0
  5: 2013-01-07      2   35.82      2

在上述数据中,01月03日和01月06日没有任何条目。
希望使用默认值(例如订单、金额等为零),或者将最后一个值向前传递(例如,01月03日将重复02月01日的值,01月06日将重复05月01日的值等)来填充缺失的条目。
如何用最佳/最优方法填补这些缺失日期数据的空缺?
答案here建议使用allow.cartesian = TRUEexpand.grid来处理缺失的工作日 - 这可能适用于工作日(因为它们只是7天的一周) - 但不确定这是否是处理日期的正确方法,特别是如果我们正在处理多年的数据。
3个回答

17

惯用的data.table方式(使用滚动连接)如下:

setkey(NADayWiseOrders, date)
all_dates <- seq(from = as.Date("2013-01-01"), 
                   to = as.Date("2013-01-07"), 
                   by = "days")

NADayWiseOrders[J(all_dates), roll=Inf]
         date orders  amount guests
1: 2013-01-01     50 2272.55    149
2: 2013-01-02      3   64.04      4
3: 2013-01-03      3   64.04      4
4: 2013-01-04      1   18.81      0
5: 2013-01-05      2   77.62      0
6: 2013-01-06      2   77.62      0
7: 2013-01-07      2   35.82      2

1
谢谢。有用的。如果我们想使用默认值(比如0),而不是滚动以前的值,该怎么做? - Gopalakrishna Palem
是的,请问如何自动将其设置为零?谢谢。 - Tavi
3
请使用参数roll=0,然后运行NADayWiseOrders[is.na(orders), orders:=0]代码。该代码的作用是将NADayWiseOrders数据框中缺失值所对应的orders列填充为0。 - Murta
6
有没有办法在分组上实现这个操作?比如,在每个分组内按最小日期到最大日期的顺序进行seq操作,并在分组内执行滚动连接操作? - RoyalTS
在组内填补空缺被发布为另一个答案。 - Jthorpe

10

以下是如何填补子群中的空白:

# a toy dataset with gaps in the time series
dt <- as.data.table(read.csv(textConnection('"group","date","x"
"a","2017-01-01",1
"a","2017-02-01",2
"a","2017-05-01",3
"b","2017-02-01",4
"b","2017-04-01",5')))
dt[,date := as.Date(date)]

# the desired dates by group
indx <- dt[,.(date=seq(min(date),max(date),"months")),group]

# key the tables and join them using a rolling join
setkey(dt,group,date)
setkey(indx,group,date)
dt[indx,roll=TRUE]

#>    group       date x
#> 1:     a 2017-01-01 1
#> 2:     a 2017-02-01 2
#> 3:     a 2017-03-01 2
#> 4:     a 2017-04-01 2
#> 5:     a 2017-05-01 3
#> 6:     b 2017-02-01 4
#> 7:     b 2017-03-01 4
#> 8:     b 2017-04-01 5

非常有帮助。 - JS1204

7

不确定是否是最快的方法,但如果数据中没有NA,它可以工作:

# just in case these aren't Dates. 
NADayWiseOrders$date <- as.Date(NADayWiseOrders$date)
# all desired dates.
alldates <- data.table(date=seq.Date(min(NADayWiseOrders$date), max(NADayWiseOrders$date), by="day"))
# merge
dt <- merge(NADayWiseOrders, alldates, by="date", all=TRUE)
# now carry forward last observation (alternatively, set NA's to 0)
require(xts)
na.locf(dt)

谢谢。对于将NA替换为0,我想知道是否有任何更快的方法(也许使用data.table的特殊语法),而不是在每个字段上进行常规的dt$orders[is.na(dt$orders)] <- 0 替换。 - Gopalakrishna Palem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接