我正在使用带有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但在此之前我想检查是否有更简单的方法。