如何在作为参数传递给函数时访问datatable的变量?

时间:2017-04-05 20:34:56

标签: r data.table

我是R的新手,我在google上搜索了以下问题的解决方案。

我有

DT = data.table(y=c("a",NA,NA), y_1=c(NA,3,6), y_2=c(1,NA,3), y_3=c(1,1,1)). 

我想创建一个传递数据表的函数和需要更改的列。

fun <- function(dt, var)

{

dt[,(var) := ifelse(!(is.na(get(var))), get(paste0(var,"1")),
                    ifelse(!(is.na(get(paste0(var,"1")), get(paste0(var,"2")...))]
return(dt)
}

我想将y变量NA中的值替换为y_1中的值,如果它们不是NULL,或者替换为{{1} }} 等等。像这样我想创建一个可以接受不同变量但具有相同结尾的函数。

更新:Uwe,感谢您指出上一个问题。我发现它很有用。但是,我的要求略有不同。我需要对其他变量进行相同的更新,其中值为NA。例如,我需要为(x,x_1,x_2,x_3 ...),(z,z_1,z_2,z_3 ..)以及除y之外的一些其他变量执行此操作。有没有办法使用lapply或函数来做到这一点。

提前致谢。

1 个答案:

答案 0 :(得分:1)

OP正在寻找locf方法的变体(最后一次观察结果),例如实现为zoo::na.locf()。虽然na.locf()通常应用于data.frame的向量或列,但OP正在查找应用于data.table的每一行但仅限于列的特定子集的变体。因此,该函数被命名为na.locl()(最后一次观察 left )。

此外,data.table将在适当的位置更新,例如,无需复制。列以特定方式命名,例如xx_1x_2x_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
除第1行外,

yxzzzNA。在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

yxzzz中的缺失值已替换为右侧的下一个非NA值(如果在列的子集中可用) 。因此,第4行全部为NA,因为在每个列子集中都没有非NA(连续三个否定)。