假设我们有一个缺少值的数据表(参见下面的示例).
library(data.table)
mat <- matrix(rnorm(50), ncol = 5)
mat[c(1,3,5,9,10,11,14,37,38)] <- NA
DT <- as.data.table(mat)
Run Code Online (Sandbox Code Playgroud)
总的来说,我们在示例中有5个唯一的缺失数据模式(请参阅参考资料unique(!is.na(DT))).
现在进一步假设我们想要找到这些模式并根据它们的出现频率来识别它们(从1表示的最频繁模式开始).
DTna <- as.data.table(!is.na(DT))
DTna <- DTna[, n := .N, by = names(x = DTna)]
DTna <- DTna[, id := 1:nrow(x = DTna)]
DTna <- DTna[order(n, decreasing = TRUE)]
DTna <- DTna[, m := .GRP, by = eval(names(x = DT))]
Run Code Online (Sandbox Code Playgroud)
最后,具有特定模式的观察应该根据预先规范进行子集化(这里例如对于最频繁的模式为1).
pattern <- 1
i <- DTna[m == pattern, id]
DT[i]
Run Code Online (Sandbox Code Playgroud)
总之,我需要找到共享相同缺失数据模式的观察结果,然后根据预先指定(例如最常见的模式)对它们进行子集化.请注意,我需要子集DT而不是DTna.
题
到目前为止,上面的代码按预期工作,但使用data.table是否有更优雅的方式?
我会在DT中添加一个分组列来加入和过滤:
DT[, nag := do.call(paste0, lapply(.SD, function(x) +is.na(x)))]
nagDT = DT[, .N, by=nag][order(-N), nagid := .I][, setorder(.SD, nagid)]
# nag N nagid
# 1: 10000 4 1
# 2: 00000 2 2
# 3: 00010 2 3
# 4: 11000 1 4
# 5: 01000 1 5
# subsetting
my_id = 1L
DT[nagDT[nagid == my_id, nag], on=.(nag), nomatch=0]
Run Code Online (Sandbox Code Playgroud)
这使
V1 V2 V3 V4 V5 nag
1: NA 1.3306093 -2.1030978 0.06115726 -0.2527502 10000
2: NA 0.2852518 -0.1894425 0.86698633 -0.2099998 10000
3: NA -0.1325032 -0.5201166 -0.94392417 0.6515976 10000
4: NA 0.3199076 -1.0152518 -1.61417902 -0.6458374 10000
Run Code Online (Sandbox Code Playgroud)
如果要在结果中省略新列:
DT[nagDT[nagid == my_id, nag], on=.(nag), nomatch=0, !"nag"]
Run Code Online (Sandbox Code Playgroud)
并且还省略了空白列:
DT[nagDT[nagid == my_id, nag], on=.(nag), nomatch=0, !"nag"][,
Filter(function(x) !anyNA(x), .SD)]
Run Code Online (Sandbox Code Playgroud)