R将unique()与逻辑条件相结合以对data.table进行子集化

时间:2015-11-03 16:43:08

标签: r conditional data.table unique subset

我正在使用带有R 3.2.1的data.table 1.9.6。

我有一个带有一个名为pid的密钥的data.table。有多个具有相同pid的记录,其完整程度,样本的日期和执行的测试类型不同。我需要将这个data.table与pid上的另一个data.table合并,但是第二个表只有一个每个pid的唯一记录。

在合并之前,我需要对第一个data.table进行子集化,这样它每个pid只包含一个唯一的记录。我可以用unique()来做这个,但是这会给我按顺序给每个pid的第一个记录,这不一定是我想要的那个。对于每个pid,我正在寻找包含特定测试类型(x)的行,具有该pid的最早样本日期,如果有多个具有最早的样本日期,那么那些具有最完整字段的行作为决胜局。

只需按样品日期(从最小到最大)排序,然后没有。完整字段(最大到最小)然后应用unique()让我成为一部分,但有效地引用test=="x"条件是我陷入困境的地方。

如何有效地对data.table进行重复数据删除并明确选择要保留的行,以满足某些逻辑条件(可以评估给定pid的所有行)?

以下是一些示例数据:

pid <- c("a1", "b1", "c1", "a1", "c1", "c1", "c1")
sampledate <- c("2014-11-19", "2014-11-01", "2014-11-05", "2014-11-17", "2014-11-05", "2014-11-05", "2014-11-05")
age <- c(10,43,2,10,2,NA,2)
sex <- c("female","female","male","female","male",NA,"male")
test <- c("x", "x", "e", "x", "d", "y", "x")

dt <- data.table(cbind(pid,sampledate,age,sex,test))
dt[, sampledate := as.Date(sampledate)]
dt[, completefields := rowSums(!is.na(dt))]

以下是使用setorder的唯一子集:

setkey(dt, pid)
setorder(dt, pid, sampledate, -completefields, na.last=TRUE)
dts=unique(dt)

 > dts
   pid sampledate age    sex test completefields
1:  a1 2014-11-17  10 female    x              5
2:  b1 2014-11-01  43 female    x              5
3:  c1 2014-11-05   2   male    e              5   

在上面的输出中,对于pid“c1”,选择了测试“e”的记录,而我只对测试“x”的记录感兴趣。在订单列表中包括测试对我没有帮助,因为选项是d,e,x和y,其中我想要的值,“x”分别落在第三个(如果是有序的升序)或第二个(如果是有序的降序)的位置。

如果我将逻辑测试的结果添加到我的数据集中,我可以按顺序包含“testisx”列并得到我想要的内容:

dt[, testisx := test=="x"]

setkey(dt, pid)
setorder(dt, pid, sampledate, -testisx, -completefields, na.last=TRUE)
dts=unique(dt)

 > dts
   pid sampledate age    sex test completefields testisx
1:  a1 2014-11-17  10 female    x              5    TRUE
2:  b1 2014-11-01  43 female    x              5    TRUE
3:  c1 2014-11-05   2   male    x              5    TRUE

这适用于小型数据集,但为更大的数据集创建额外的列将在计算上非常昂贵。

有没有办法为每个符合上述条件的pid选择一行而不创建额外的列?我不必使用unique();我可以构建一个forloop但在此之前我想检查是否有更简单的方法。

0 个答案:

没有答案