该OP正在寻找locf
方法的变体(最后一次观察结转),例如实施为zoo::na.locf()
。虽然na.locf()
通常应用于data.frame的向量或列,但OP正在寻找应用于data.table
的每一行但限于特定列子集的变体。所以,该函数被命名为na.locl()
(最后一次观测进行了左)。
另外,data.table
将在适当的位置更新,例如不需要复制。列以特定方式命名,例如,x
,x_1
,x_2
,x_3
等。因此,x
对于列的子集是基类名称的种类。
以下函数将在给定data.table
的列的特定子集的每一行中查找第一个非NA
列,并将此值复制到列x
。
该实现基于this solution。它包括一些可信的检查。
na.locl <- function(var, dt) {
checkmate::assert_data_table(dt)
checkmate::assert_string(var)
checkmate::assert_choice(var, names(dt))
ans_val = rep_len(NA_real_, nrow(dt))
selected_cols <- unlist(lapply(
var, function(x) stringr::str_subset(names(dt), paste0("^", x, "(_\\d*)?$"))))
for(col in selected_cols) {
i = is.na(ans_val) & (!is.na(dt[[col]]))
ans_val[i] = dt[[col]][i]
}
set(DT, , var, ans_val)
return(invisible(NULL))
}
另外,OP已要求对其他变量重复此操作。这可以使用lapply()
和na.locl()
函数完成。为了演示这一点,需要样本数据。
library(data.table)
DT0 <- data.table(y=c("a",NA,NA,NA), y_1=c(NA,3,NA,NA), y_2=c(1,NA,3,NA), y_3=c(1,1,1,NA))
DT <- cbind(DT0, setnames(copy(DT0), stringr::str_replace(names(DT0), "^y", "x")))
DT <- cbind(DT, setnames(copy(DT0), stringr::str_replace(names(DT0), "^y", "zzz")))
DT
# y y_1 y_2 y_3 x x_1 x_2 x_3 zzz zzz_1 zzz_2 zzz_3
#1: a NA 1 1 a NA 1 1 a NA 1 1
#2: NA 3 NA 1 NA 3 NA 1 NA 3 NA 1
#3: NA NA 3 1 NA NA 3 1 NA NA 3 1
#4: NA NA NA NA NA NA NA NA NA NA NA NA
y
,x
,和zzz
是NA
除了第1行上施加的DT功能后,
dummy <- lapply(c("x", "y", "zzz"), na.locl, dt = DT)
DT
# y y_1 y_2 y_3 x x_1 x_2 x_3 zzz zzz_1 zzz_2 zzz_3
#1: a NA 1 1 a NA 1 1 a NA 1 1
#2: 3 3 NA 1 3 3 NA 1 3 3 NA 1
#3: 3 NA 3 1 3 NA 3 1 3 NA 3 1
#4: NA NA NA NA NA NA NA NA NA NA NA NA
在x
列y
,缺失的值,和zzz
已经由取代下一个非NA
值在列的子集内可用。因此,第4行全部为NA
,因为不是非NA
(这是一行中的三个否定)在每个列子集中都可用。
你错过了你的问题中的一个重要部分,你如何使用你定义的'DT'来调用你的'fun'函数。 – vincentmajor
我想传递数据表和我想用其替换其NA值的变量。Like fun(DT,“y”) – Lufy
这里是同样的问题(忽略grep列名的希望):http:// stackoverflow.com/q/37776942/亚历克西斯的答案可能在这两个方面更有效率,fwiw。 – Frank