繁体   English   中英

R data.table按列值子集

[英]R data.table subsetting by column value

我想知道在data.table ,根据某些列值的出现选择行的最有效或最干净的方法是什么? 例如,在一个7列的数据表中,每个值都是1或0,我希望所有的行都精确地有2个值1和5个值0(1表示“存在”而0表示“不存在”)。

到目前为止,这是我在做的,假设下面的data.table (更大,这只是其中的一个示例)

                                    name D2A1.var D2B3.var D3A1.var D4A3.var D5B3.var H2A3.var H4A4.var MA_ancestor.var
Chrom_1;10000034;G;A Chrom_1;10000034;G;A        1        1        1        1        1        1        1               1
Chrom_1;10000035;G;A Chrom_1;10000035;G;A        1        1        1        1        1        1        1               1
Chrom_1;10000042;C;A Chrom_1;10000042;C;A        1        1        1        1        1        1        1               1
Chrom_1;10000051;A;G Chrom_1;10000051;A;G        1        1        1        1        1        1        1               1
Chrom_1;10000070;G;A Chrom_1;10000070;G;A        1        1        1        1        1        1        1               1
Chrom_1;10000084;C;T Chrom_1;10000084;C;T        1        1        1        1        1        1        1               1
Chrom_6;9997224;AT;A               Chrom_6;9997224;AT;A        0        0        0        0        0        1        0               1
Chrom_6;9998654;GTGTGTGTT;G Chrom_6;9998654;GTGTGTGTT;G        0        0        0        0        0        0        0               1
Chrom_6;9999553;TTTC;T           Chrom_6;9999553;TTTC;T        0        0        0        0        0        0        0               1

如果我要所有行中有7 1的行,并且假设D2A1.var和D3A1.var中只有1,则执行以下操作

ALL = DT[DT$MA_ancestor.var == 1 & DT$D2A1.var == 1 &DT$D2B3.var == 1 & DT$D3A1.var == 1 & DT$D4A3.var == 1 &DT$D5B3.var == 1 & DT$H2A3.var == 1 & DT$H4A4.var == 1,]
TWO = DT[DT$MA_ancestor.var == 0 & DT$D2A1.var == 1 &DT$D2B3.var == 0 & DT$D3A1.var == 1 & DT$D4A3.var == 0 &DT$D5B3.var == 0 & DT$H2A3.var == 0 & DT$H4A4.var == 0,]
DFlist=list(TWO, ALL)
DFlong = rbindlist(DFlist, use.names = TRUE, idcol = FALSE)

这将返回预期结果并且足够快。 但是,在具有多个条件的情况下,需要进行大量的键入和大量的data.table创建。 是否有更快,更清洁和更紧凑的方式来实现这一目标?

我们可以通过指定感兴趣的列来使用.SDcols 遍历Data.table的子集( .SD ),创建逻辑vector list ,并使用& Reduce.SD为单个逻辑vector

ALL <- DT[, Reduce(`&`, lapply(.SD, `==`, 1), .SDcols = nm1]
TWO <- DT[, Reduce(`&`, lapply(.SD, `==`, 0), .SDcols = nm1]

哪里

nm1 <- names(DT)[-1] #or change the names accordingly

是否有更快,更清洁和更紧凑的方式来实现这一目标?

像您一样进行单独的查询和重新绑定可能是最简单的。

您可以使用replace和join语法简化每个查询:

# make a list of columns initially set to value 0
vec0 = lapply(DT[, .SD, .SDcols=D2A1.var:MA_ancestor.var], function(x) 0)

# helper function for semi join
subit = function(x, d = DT) d[x, on=names(x), nomatch=0]

rbind(
  subit(replace(vec0, names(vec0), 1)),
  subit(replace(vec0, c("D2A1.var", "D3A1.var"), 1))
)

(此代码未经测试,因为OP的数据不易复制。)

您可能可以进一步简化...

subitall = function(..., d = DT, v0 = vec0) 
  rbindlist(lapply(..., function(x) subit( replace(v0, names(v0), 1), d = d )))

subitall( names(vec0), c("D2A1.var", "D3A1.var") )

关于功能subit的子集/半连接,你可以修改它的基础上的答案,满足您的需求进行有data.table半联接


编辑:哦,对了,按照@chinsoon的回答,您也可以先rbind:

subit(rbindlist(list(
  replace(vec0, names(vec0), 1),
  replace(vec0, c("D2A1.var", "D3A1.var"), 1)      
)))

这意味着只加入一次,这更简单。

使用setkey另一个选项:

setkeyv(DT, names(DT))

#create desired filtering conditions as lists
cond1 <- setNames(as.list(rep(1, ncol(DT))), names(DT))
cond2 <- list(MA_ancestor.var=0, D2A1.var=1, D2B3.var=0, D3A1.var=1, D4A3.var=0, D5B3.var=0, H2A3.var=0, H4A4.var=0)

#get list of conditions so that one does not have to type it one by one
scond <- grep("^cond", ls(), value=TRUE)
DT[rbindlist(mget(scond, envir=.GlobalEnv), use.names=TRUE)]

如果您担心使用cond开头的虚假变量,则可以使用list2env将它们分配给环境,然后将list2env传递给mget

数据:

DT <- fread("D2A1.var D2B3.var D3A1.var D4A3.var D5B3.var H2A3.var H4A4.var MA_ancestor.var
1        1        1        1        1        1        1               1
1        1        1        1        1        1        1               1
1        1        1        1        1        1        1               1
1        1        1        1        1        1        1               1
1        1        1        1        1        1        1               1
1        1        1        1        1        1        1               1
0        0        0        0        0        1        0               1
0        0        0        0        0        0        0               1
0        0        0        0        0        0        0               1")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM