我有data.table
个测量值,每列都有一个较低的检测限,(可能还有检测上限)
set.seed(1)
dt <- data.table(id=1:5, A=rnorm(5), B=rnorm(5, mean=2), C=rnorm(5,mean=-1))
setkey(dt, id)
# "randomly" disperse upper an lower limits to measurement columns
dt[3,A := -5]
dt[2,B := -3]
dt[5,B := 7]
dt[1,C := -10]
dt
id A B C
1: 1 -0.6264538 1.179532 -10.0000000
2: 2 0.1836433 -3.000000 -0.6101568
3: 3 -5.0000000 2.738325 -1.6212406
4: 4 1.5952808 2.575781 -3.2146999
5: 5 0.3295078 7.000000 0.1249309
我想在NA
的每一列中过滤(设置为dt
)输出值,这些值与另一个data.table
中列出的测量下限和上限完全匹配:
limits <- data.table(measurement=LETTERS[1:3], lower=c(-5,-3,-10),
upper=c(NA, 7, NA))
setkey(limits, measurement)
limits
measurement lower upper
1: A -5 NA
2: B -3 7
3: C -10 NA
我的预期输出是:
dt
id A B C
1: 1 -0.6264538 1.179532 NA
2: 2 0.1836433 NA -0.6101568
3: 3 NA 2.738325 -1.6212406
4: 4 1.5952808 2.575781 -3.2146999
5: 5 0.3295078 NA 0.1249309
我无法为此构建一个很好的解决方案,所以目前我正在使用一个笨拙的for循环来完成工作:
for (i in 1:nrow(dt)) {
for (j in 2:ncol(dt)) {
if (is.na(dt[i, j, with=F])) {
next
} else if (dt[i, j, with=F] == limits[names(dt)[j]][, lower]) {
dt[i, j := NA_real_, with=F]
} else if (is.na(limits[names(dt)[j]][, upper])) {
next
} else if (dt[i, j, with=F] == limits[names(dt)[j]][, upper]) {
dt[i, j := NA_real_, with=F]
} else {
next
}
}
}
但必须有更好更好的东西吗?我对apply
limits
的每一行data.table
dt
的每一栏{{1}}进行了游戏,但没有取得任何成功。
答案 0 :(得分:6)
首先,我按照以下方式转置您的limiits
data.table:
require(reshape2)
require(data.table)
limits = dcast.data.table(melt(limits, id=1), variable ~ measurement)
# variable A B C
# 1: lower -5 -3 -10
# 2: upper NA 7 NA
然后,您可以匹配i
的相应列,并使用NA
将这些匹配替换为set
,如下所示:
for (i in 2:ncol(dt)) {
set(dt, i=which(dt[[i]] %in% limits[[i]]), j=i, value=NA_real_)
}
# id A B C
# 1: 1 -0.6264538 1.179532 NA
# 2: 2 0.1836433 NA -0.6101568
# 3: 3 NA 2.738325 -1.6212406
# 4: 4 1.5952808 2.575781 -3.2146999
# 5: 5 0.3295078 NA 0.1249309
答案 1 :(得分:2)
这是另一种选择:
dt[, 2:length(dt) := lapply(
2:length(dt),
function(x) ifelse(.SD[[x]] %in% limits[x - 1, c(lower, upper)], NA, .SD[[x]])
) ]
由于limits
中的行与dt
中的列的顺序相同,因此您只需遍历列:
id A B C
1: 1 -0.6264538 1.179532 NA
2: 2 0.1836433 NA -0.6101568
3: 3 NA 2.738325 -1.6212406
4: 4 1.5952808 2.575781 -3.2146999
5: 5 0.3295078 NA 0.1249309