r语言 - 根据条件选择数据表列,在 by 内



如果数据列的内容满足条件,我想提取它们。我需要一种方法来使用(或在列组合中以其他方式使用(。我对 data.table 不是很有经验,并且已经尽力了。SDcol 以及我能想到的其他什么。

示例:我经常有数据集,其中包含多个主题在多个时间点的观察结果。它们还包含主体内不变的协变量。

dt1 <- data.table(
id=c(1,1,2,2,3,3),
time=c(1,2,1,2,1,2),
meas=c(452,23,555,33,322,32),
age=c(30,30,54,54,20,20),
bw=c(75,75,81,81,69,70)
)

如何(有效地(选择在id内没有变化的列(在本例中为id和age(?我想要一个会返回的函数调用

id age
1:  1  30
2:  2  54
3:  3  20

以及如何选择在 ID 内变化的列(因此删除年龄(?函数调用应返回:

id time meas bw
1:  1    1  452 75
2:  1    2   23 75
3:  2    1  555 81
4:  2    2   33 81
5:  3    1  322 69
6:  3    2   32 70

当然,如果您知道解决上述特定示例的函数,我会感兴趣,但我对通常如何做到这一点更加好奇。包含两个以上值的列在 by= 中的 id 和时间的任意组合中> 1000。(id,时间(,或者其他什么...

谢谢!

如何(有效地(选择在 id 内没有变化的列(在本例中为 id 和年龄(?

也许像这样:

f <- function(DT, byChar) {
cols <- Reduce(intersect, DT[, .(.(names(.SD)[sapply(.SD, uniqueN)==1])), byChar]$V1)
unique(DT[, c(byChar, cols), with=FALSE])
}
f(dt1, "id")

输出:

id age
1:  1  30
2:  2  54
3:  3  20

以及如何选择在 ID 内变化的列(因此删除年龄(?

同样地

f2 <- function(DT, byChar, k) {
cols <- Reduce(intersect, DT[, .(.(names(.SD)[sapply(.SD, uniqueN)>k])), byChar]$V1)
unique(DT[, c(byChar, cols), with=FALSE])
}
f2(dt1, "id", 1)

输出:

id time meas
1:  1    1  452
2:  1    2   23
3:  2    1  555
4:  2    2   33
5:  3    1  322
6:  3    2   32

数据:

library(data.table)
dt1 <- data.table(
id=c(1,1,2,2,3,3),
time=c(1,2,1,2,1,2),
meas=c(452,23,555,33,322,32),
age=c(30,30,54,54,20,20),
bw=c(75,75,81,81,69,70)
)

这也可能是一个选项:

按 ID 计算每列的唯一值(使用data.table::uniqueN
(检查哪些列中唯一值的总和(按组(等于唯一 ID 的数量(使用colSums(仅保留(或删除(
所需的列

library(data.table)
ids <- uniqueN(dt1$id)
#no variation
dt1[, c( TRUE, colSums( dt1[, lapply( .SD, uniqueN ), by = id ][,-1]) == ids ), with = FALSE]
id age
1:  1  30
2:  1  30
3:  2  54
4:  2  54
5:  3  20
6:  3  20
#variation
dt1[, c( TRUE, !colSums( dt1[, lapply( .SD, uniqueN ), by = id ][,-1]) == ids ), with = FALSE]
id time meas bw
1:  1    1  452 75
2:  1    2   23 75
3:  2    1  555 81
4:  2    2   33 81
5:  3    1  322 69
6:  3    2   32 70

根据chinsoon12的建议,我设法把一些东西放在一起。我需要四个步骤,我不确定它的效率如何,但至少它可以完成这项工作。回顾一下,这是数据集:

dt1
id time meas age bw
1:  1    1  452  30 75
2:  1    2   23  30 75
3:  2    1  555  54 81
4:  2    2   33  54 81
5:  3    1  322  20 69
6:  3    2   32  20 70

我把它放在一起以获得在"id"(仅限年龄(内常量的列:

cols.id <- "id"
dt2 <- dt1[, .SD[, lapply(.SD, function(x)uniqueN(x)==1)], by=cols.id]
ifkeep <- dt2[,sapply(.SD,all),.SDcols=!(cols.id)]
keep <- c(cols.id,setdiff(colnames(dt2),cols.id)[ifkeep])
unique(dt1[,keep,with=F])
id age
1:  1  30
2:  2  54
3:  3  20

要获取在"id"的任何值内变化的列(年龄被删除(:

cols.id <- "id"
## differenct from above: ==1 -> >1
dt2 <- dt1[, .SD[, lapply(.SD, function(x)uniqueN(x)>1)], by=cols.id]
## difference from above: all -> any
ifkeep <- dt2[,sapply(.SD,any),.SDcols=!(cols.id)]
keep <- c(cols.id,setdiff(colnames(dt2),cols.id)[ifkeep])
unique(dt1[,keep,with=F])
id time meas bw
1:  1    1  452 75
2:  1    2   23 75
3:  2    1  555 81
4:  2    2   33 81
5:  3    1  322 69
6:  3    2   32 70

最新更新