2017-04-05 70 views
1

我是R的新手,我已经在谷歌搜索解决以下问题。如何在作为参数传递给函数时访问数据表变量?

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或者与y_2等替代值。像这样,我想创建一个可以接受不同变量但具有相同结尾的函数。

更新:Uwe,感谢您指出上一个问题。我发现它非常有用。但是,我的要求稍有不同。对于其他变量以及值为NA的情况,我需要同样的更新。例如,我需要为(x,x_1,x_2,x_3 ...),(z,z_1,z_2,z_3 ..)和除y以外的其他变量执行此操作。有没有办法使用lapply或功能来做到这一点。

在此先感谢。

+1

你错过了你的问题中的一个重要部分,你如何使用你定义的'DT'来调用你的'fun'函数。 – vincentmajor

+0

我想传递数据表和我想用其替换其NA值的变量。Like fun(DT,“y”) – Lufy

+0

这里是同样的问题(忽略grep列名的希望):http:// stackoverflow.com/q/37776942/亚历克西斯的答案可能在这两个方面更有效率,fwiw。 – Frank

回答

1

该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 

yx,和zzzNA除了第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 

xy,缺失的值,和zzz已经由取代下一个非NA值在列的子集内可用。因此,第4行全部为NA,因为不是非NA(这是一行中的三个否定)在每个列子集中都可用。

+0

谢谢Uwe。我用你以前的帖子来完成我的工作。但我用样本测试数据测试了这个新功能,并且它工作正常。我将使用这个函数并更新我的代码。非常感谢你。 – Lufy

相关问题