我有以下几行代码:
DT[flag==T, temp:=haz_1.5]
DT[, temp:= na.locf(temp, na.rm = FALSE), "pid"]
DT[agedays==61, haz_1.5_1:=temp]
我需要将其转换为一个函数,以便它可以处理一系列变量,而不仅仅是一个变量。最近,我学习了如何通过遍历列和创建一组新列的条件使用lapply创建函数。但是,我不确定在通过列列表以及在这些列上向前传递变量的所有值时该怎么做。
例如,我可以编写以下代码:
columns<-c("haz_1.5", "waz_1.5")
new_cols <- paste(columns, "1", sep = "_")
x=61
maled_anthro[(flag==TRUE)&(agedays==x), (new_cols) := lapply(.SD, function(y) na.locf(y, na.rm=F)), .SDcols = columns]
但是我错过了na.locf步骤,因此在构建函数之前没有得到与原始代码行相同的输出。我如何将使用na.locf的代码行合并到该函数中,以将方式转发值(DT [,temp:= na.locf(temp,na.rm = FALSE),“ pid”])所有数据都包装到单个函数中?可以用相同的方式来愉快地工作吗?
与我正在使用的数据表类似的虚拟数据:
DT <- data.table(pid = c(1,1,2,3,3,4,4,5,5,5),
flag = c(T,T,F,T,T,F,T,T,T,T),
agedays = c(1,61,61,51,61,23,61,1,32,61),
haz_1.5 = c(1,1,1,2,NA,1,3,2,3,4),
waz_1.5 = c(1,NA,NA,NA,NA,2,2,3,4,4))
答案 0 :(得分:2)
OP的代码可以转换成匿名函数,该匿名函数将应用于所选的columns
:
library(data.table)
columns <- c("haz_1.5", "waz_1.5")
new_cols <- paste0(columns, "_1")
x <- 61
DT[, (new_cols) := lapply(.SD, function(v) {
temp <- fifelse(flag, v, NA_real_)
temp <- nafill(temp, "locf")
fifelse(agedays == x, temp, NA_real_)
}), .SDcols = columns, by = pid][]
pid flag agedays haz_1.5 waz_1.5 haz_1.5_1 waz_1.5_1 1: 1 TRUE 1 1 1 NA NA 2: 1 TRUE 61 1 NA 1 1 3: 2 FALSE 61 1 NA NA NA 4: 3 TRUE 51 2 NA NA NA 5: 3 TRUE 61 NA NA 2 NA 6: 4 FALSE 23 1 2 NA NA 7: 4 TRUE 61 3 2 3 2 8: 5 TRUE 1 2 3 NA NA 9: 5 TRUE 32 3 4 NA NA 10: 5 TRUE 61 4 4 4 4
这与我们手动为两列重复OP的代码时得到的结果相同(请注意,在按引用分配的部分之前,需要清除temp
列)
DT[(flag), temp := haz_1.5]
DT[, temp := zoo::na.locf(temp, na.rm = FALSE), by = pid]
DT[agedays == 61, haz_1.5_1 := temp]
DT[, temp := NULL]
DT[(flag), temp := waz_1.5]
DT[, temp := zoo::na.locf(temp, na.rm = FALSE), by = pid]
DT[agedays == 61, waz_1.5_1 := temp]
DT[, temp := NULL][]
pid flag agedays haz_1.5 waz_1.5 haz_1.5_1 waz_1.5_1 1: 1 TRUE 1 1 1 NA NA 2: 1 TRUE 61 1 NA 1 1 3: 2 FALSE 61 1 NA NA NA 4: 3 TRUE 51 2 NA NA NA 5: 3 TRUE 61 NA NA 2 NA 6: 4 FALSE 23 1 2 NA NA 7: 4 TRUE 61 3 2 3 2 8: 5 TRUE 1 2 3 NA NA 9: 5 TRUE 32 3 4 NA NA 10: 5 TRUE 61 4 4 4 4
pid
中的每个项目调用匿名函数。在OP的代码中,第一个和最后一个分配在未分组的(完整的)向量上工作(也许效率更高)。但是,这些分配的结果与pid
无关,并且结果相同。zoo::na.locf()
函数而不是nafill()
(data.table v1.12.4的新增功能,于CRAN 03 Oct 2019)DT[(flag), ...]
等同于DT[flag == TRUE, ...]
fifelse()
代替子集按引用分配,则no
参数必须为NA
才能兼容。因此,DT[, temp := fifelse(flag, haz_1.5, NA_real_)][]
等效于DT[(flag), temp := haz_1.5][]