【问题标题】:Interpolate time series (replace NAs) using growth rate of another time series使用另一个时间序列的增长率插值时间序列(替换 NA)
【发布时间】:2020-11-22 16:38:16
【问题描述】:

假设我有一个这样的数据集:

trt <- data.table(group = rep(c("a","b"), each = 5), 
                  val1= c(60,62,NA,NA,71, NA, 21,22,NA,25),
                  val2 = c(1,1,1,NA,2, 1,1,NA,NA,2),
                  reflev = rep(c(1.01, 1.03, 1.061, 1.104,1.159), 2))
trt[ , ref:= round(reflev/shift(reflev), 2), by = group]


> trt
    group val1 val2 reflev  ref
 1:     a   60    1  1.010   NA
 2:     a   62    1  1.030 1.02
 3:     a   NA    1  1.061 1.03
 4:     a   NA   NA  1.104 1.04
 5:     a   71    2  1.159 1.05
 6:     b   NA    1  1.010   NA
 7:     b   21    1  1.030 1.02
 8:     b   22   NA  1.061 1.03
 9:     b   NA   NA  1.104 1.04
10:     b   25    2  1.159 1.05

在每个组中,我想通过将之前的可用值(例如 shift(val1)lag(val1))与ref 列中的值。如果在一个非 NA 值之后有多个 NA 出现在一个序列中,则应使用之前的插值作为起点对它们进行插值。

所以,这是我想象的计算方式:

    group val1          val2         reflev  ref
 1:     a   60            1           1.010   NA
 2:     a   62            1           1.030 1.02
 3:     a   62*1.03       1           1.061 1.03
 4:     a   62*1.03*1.04  1*1.04      1.104 1.04
 5:     a   71            2           1.159 1.05
 6:     b   NA            1           1.010   NA
 7:     b   21            1           1.030 1.02
 8:     b   22           1*1.03       1.061 1.03
 9:     b   22*1.04      1*1.03*1.04  1.104 1.04
10:     b   25            2           1.159 1.05

有什么想法吗?我能想到的一切都非常肮脏,并且会涉及两个循环,一个用于组,一个用于所需的列。

【问题讨论】:

  • 如果refval1 都是NA 怎么办?如果val1[1]NA 怎么办?
  • 在这些情况下,不可能/不需要插值,因此这些 NA 应该保持 NA

标签: r time-series data.table interpolation na


【解决方案1】:

这是我的“快速肮脏”解决方案。很高兴听到改进的可能性:

interpolate <- function(data, int.column){

  for(row in 2:nrow(data)){
    if(is.na(data[row,get(int.column)]) & !is.na(data[row-1, get(int.column)])){
      data[[int.column]][row] <- data[row,ref]*data[[int.column]][row-1]
      }
  }
  return(data[ , get(int.column)])
}

我对@9​​87654322@(要插入的列的名称)进行了如此奇怪的调用,因为我没有设法从适当的环境中调用 int.column 并且总是出错)。

然后 trt[ , val1:= interpolate(.SD,"val1"), by = group] 用于单列的插值或

columns.to.int <- c("val1", "val2")
trt[ , (columns.to.int):= lapply(columns.to.int, function(x)interpolate(.SD,x)), by = group]

多个。

有没有更好的办法?

【讨论】:

    【解决方案2】:

    这是另一种选择:

    cols <- paste0("val", 1L:2L)
    trt[, paste0("prev", cols) := lapply(.SD, nafill, type="locf"), group, .SDcols=cols]
    
    trt[, outval1 := fifelse(is.na(val1), prevval1 * cumprod(ref), val1), .(group, rleid(is.na(val1)))]
    
    trt[, outval2 := fifelse(is.na(val2), prevval2 * cumprod(ref), val2), .(group, rleid(is.na(val2)))]
    

    编辑多个val 列。也许是这样的:

    cols <- paste0("V", 1L:30L)
    for (x in cols) {
        trt[, c("prev", "ri") := {
                v <- get(x)
                .(nafill(v, "locf"), rleid(is.na(v)))
            }, group]
        trt[, paste0("out", x) := {
                v <- get(x)
                fifelse(is.na(v), prev * cumprod(ref), v)
            }, .(group, ri)]
    }
    

    或者使用melt会更快:

    mDT <- melt(trt[, rn := .I], measure.vars=patterns("^V"))
    mDT[, pv := nafill(value, "locf"), group]
    mDT[, nv := fifelse(is.na(value), pv * cumprod(ref), value),
        .(group, variable, rleid(is.na(value)))]
    dcast(mDT, rn + group + reflev + ref ~ variable, value.var="nv")
    

    样本数据:

    library(data.table)
    set.seed(0L)
    nc <- 30L
    nr <- 3e3L
    trt <- data.table(group = rep(1:(nr/5L), each=5L), 
        reflev = 1+runif(nr)/10,
        as.data.table(matrix(sample(c(NA,10,20,30), nc*nr, TRUE), ncol=nc)))
    trt[ , ref:= round(reflev/shift(reflev), 2), by = group]
    

    【讨论】:

    • 谢谢,明白,非常巧妙的解决方案!任何想法如何将上述内容推广到 cols 中的多个列?由于分组中的 val1/val2 我遇到了麻烦...。在这个方向上尝试了一些东西trt[, (paste0("out", cols)) := lapply(.SD, function(x)fifelse(is.na(x), prevval1 * cumprod(ref), x)), .(group, rleid(is.na(val1))), .SDcols = cols]
    • 您好,您的数据集有多大?你有多少 val 列?
    • 不是很大(2000-3000 行),但有 30 列
    • @Djpengo 我为此添加了 2 种方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 2016-02-07
    • 1970-01-01
    • 2019-05-06
    • 2021-05-12
    • 2019-03-23
    相关资源
    最近更新 更多