data.table 按组填充其他行的缺失值

LeG*_*sII 4 row r na data.table

# have
> aDT <- data.table(colA = c(1,1,1,1,2,2,2,2,3,3,3,3), colB = c(4,NA,NA,1,4,3,NA,NA,4,NA,2,NA))
> aDT
    colA colB
 1:    1    4
 2:    1   NA
 3:    1   NA
 4:    1    1
 5:    2    4
 6:    2    3
 7:    2   NA
 8:    2   NA
 9:    3    4
10:    3   NA
11:    3    2
12:    3   NA
# want
> bDT <- data.table(colA = c(1,1,1,1,2,2,2,2,3,3,3,3), colB = c(4,1,1,1,4,3,3,3,4,2,2,2))
> bDT
    colA colB
 1:    1    4
 2:    1    1
 3:    1    1
 4:    1    1
 5:    2    4
 6:    2    3
 7:    2    3
 8:    2    3
 9:    3    4
10:    3    2
11:    3    2
12:    3    2
Run Code Online (Sandbox Code Playgroud)

想根据以下算法填充缺失值:在每个组内('colA'),

  1. 使用下面一行的值,如果它仍然是 NA,则继续直到该组中的最后一行
  2. 如果下面行中的所有 NA,请查看上面的行(一次向上 1 行)
  3. 如果所有 NA,则 NA

由于数据集相当大,算法效率是考虑的一部分。不确定是否已经有任何此类操作的包。怎么做?

tyl*_*uRp 7

随着data.tablezoo

library(data.table)
library(zoo)

# Last observation carried forward from last row of group
dt <- dt[, colB := na.locf0(colB, fromLast = TRUE), by = colA]

# Last observation carried forward for first row of group
dt[, colB := na.locf(colB), by = colA][]
Run Code Online (Sandbox Code Playgroud)

或者在单个链中:

dt[, colB := na.locf0(colB, fromLast = TRUE), by = colA][
   , colB := na.locf(colB), by = colA][]
Run Code Online (Sandbox Code Playgroud)

两者都返回:

    colA colB
 1:    1    4
 2:    1    1
 3:    1    1
 4:    1    1
 5:    2    4
 6:    2    3
 7:    2    3
 8:    2    3
 9:    3    4
10:    3    2
11:    3    2
12:    3    2
Run Code Online (Sandbox Code Playgroud)

数据:

text <- "colA colB
    1    4
    1   NA
    1   NA
    1    1
    2    4
    2    3
    2   NA
    2   NA
    3    4
    3   NA
    3    2
    3   NA"

dt <- fread(input = text, stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)