【问题标题】:Efficient sparse linear interpolation of row by row data逐行数据的高效稀疏线性插值
【发布时间】:2017-09-26 08:58:10
【问题描述】:

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

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")] 会生成一个单行数据表,但需要一段时间。

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

【问题讨论】:

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

标签: r data.table


【解决方案1】:

如果您的线性插值是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 更快,但我还没有研究过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    相关资源
    最近更新 更多