如果数据列的内容满足条件,我想提取它们。我需要一种方法来使用(或在列组合中以其他方式使用(。我对 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