行数据的高效稀疏线性插值

问题描述:

当所需插值点与可用数据相比稀疏时,线性插值的最有效方法是什么?我有一个非常长的数据框,其中包含许多列,其中一列表示时间戳,其余为变量,对此我感兴趣的是插入时间戳很少。例如,考虑两个变量的情况:行数据的高效稀疏线性插值

microbenchmark::microbenchmark(approx(1:2, 1:2, 1.5)$y) 
# Unit: microseconds 
# expr min  lq  mean median  uq  max neval 
# ... 39.629 41.3395 46.80514 42.195 52.8865 138.558 100 

microbenchmark::microbenchmark(approx(seq_len(1e6), seq_len(1e6), 1.5)$y) 
# Unit: milliseconds 
# expr  min  lq  mean median  uq  max neval 
# ... 129.5733 231.0047 229.3459 236.3845 247.3096 369.4621 100 

我们看到,虽然只有一个插值(在t = 1.5)需要,增加对(x, y)的数量可以在运行时间引起幅度差几个数量级。

另一个例子,这个时候带一个数据表。

library(data.table) 
tmp_dt <- data.table(time = seq_len(1e7), a = seq_len(1e7), b = seq_len(1e7), c = seq_len(1e7)) 

运行tmp_dt[, lapply(.SD, function(col) {approx(time, col, 1.5)$y}), .SDcols = c("a", "b", "c")]产生一行数据表,但它需要一段时间。

我在想,必须通过删除数据表中不需要插值的所有行来获得一些效率。

+1

如果线性插值仅使用两个方向上最近的两个点(?),那么您可以执行两个滚动连接或排序并使用findInterval来查找这两个点并进行计算,我想。对于滚动连接,您不能在整数上加入浮点数,但是... – Frank

+0

线性插值仅需要两个方向上的两个最近点。 – Alex

如果你的线性插值是weighted.mean(c(x0, x1), c(t1-t, t-t0)),其中(t0, x0)是最近点以下和以上(t1, x1)最近...

# fix bad format 
tmp_dt[, names(tmp_dt) := lapply(.SD, as.numeric)] 

# enumerate target times 
tDT = data.table(t = seq(1.5, 100.5, by=.5)) 

# handle perfect matches 
tDT[, a := tmp_dt[.SD, on=.(time = t), x.a]] 

# handle interpolation 
tDT[is.na(a), a := { 
    w = findInterval(t, tmp_dt$time) 
    cbind(tmp_dt[w, .(t0 = time, a0 = a)], tmp_dt[w+1L, .(t1 = time, a1 = a)])[, 
    (a0*(t1-t) + a1*(t-t0))/(t1-t0)] 
}] 

扩展到更多的列是一个有点乱,但可在这里被硬塞。

某种滚动,如w = tmp_dt[t, on=.(time), roll=TRUE, which=TRUE],可能会比findInterval快,但我没有看过它。