我知道如何将函数应用于 data.table 中的列,接收单个值并在同一 data.table 中进行比较。但是,由于我是新手,我不知道如何将函数的结果与另一个 data.table 进行比较。这种情况的特殊之处在于函数的结果是一个向量。我不善言辞,所以这里是一个例子。
示例数据。我在 data.table 中有值,dt1:
## dt1
id <- c("p1","p2","p3","p3","p3",
"p4","p4","p4","p4","p4",
"p4","MJF2_157","MJF2_157","MJF3_30","MJF3_30",
"MJF3_30","MJF3_30","MJF3_30","MJF3_30")
mass_Da <- c(45659.18,45589.87,45589.19,45610.22,45802.85,
45660.37,45634.28,45611.12,45589.83,45569.70,
20838.62,20952.07,20951.89,23539.60,46860.72,
46839.05,47851.63,46909.48,47555.12)
dt1 <- data.table(id,mass_Da)
这是我想应用于“质量”列中每一行的函数,结果是每个质量的向量:
ld <- function(m,n=5:60){
ldx <- (m+1.0078*n)/n
return(ldx[ldx>1000 & ldx<2000])
}
生成的向量应与另一个 data.table dt2 中 id 的值进行比较。如果在向量中也找到了 Masstal 列中的值,则向量中的相应质量应显示在 dt2 中。如果未找到匹配项,则应输出“否”。如果有多个,则每个向量应与同一 ID 内的每个质量进行比较。请注意,dt1 中的列长度与 dt2 中的列长度永远不会相同:
### dt2
id <- c("p1","p2","p3","p3","p3",
"p4","p4","p4","MJF2_157","MJF2_157",
"MJF3_157","MJF3_30","MJF3_30","MJF3_30","MJF3_30",
"MJF3_61","MJF3_61","MJF3_61","MJF3_61","MJF3_61")
length(id)
masstal <- c(1689.770,1341.931,1086.698,1304.001,1433.335,
1425.521,1989.758,1173.885,1384.406,1065.691,
1073.079,1742.961,1384.798,1090.666,1447.482,
1057.163,1173.785,1304.204,1557.331,1149.469)
length(masstal)
dt2 <- data.table(id,masstal)
最后,匹配的公差应为+-0.5。如果成功的话,理想的 dt 应该是这样的:
dt2$confirmed_mass <- c("no",45489.87,45489.19,45489.19,"no",
"X","no","no","no","no",
"no","no","no",46860.72,"no",
"NA","NA","NA","NA","NA")
但是,如果公差接受两个或多个质量(此处标记为“X”)的质量,仍然存在问题。
我尝试过合并 dt:s 但这似乎是一条弯路...而且我仍然陷入困境,无法弄清楚如何与向量进行比较。
dt_merge <- merge.data.table(dt1,dt2, by=.EACHI, allow.cartesian=TRUE)
非常感谢任何帮助。
首先,我假设您的一些数字在
confirmed_mass
列中存在拼写错误,有些数字在您提供的任何数据中都不存在。
试试这个:
dt1long <- dt1[, list(lapply(mass_Da, ld)), by = dt1
][, c(lapply(.SD, function(z) rep(z, times = lengths(V1))),
list(V1 = unlist(V1))),
.SDcols = c("id", "mass_Da")]
dt1long
# id mass_Da V1
# <char> <num> <num>
# 1: p1 45659.18 1986.190
# 2: p1 45659.18 1903.474
# 3: p1 45659.18 1827.375
# 4: p1 45659.18 1757.130
# 5: p1 45659.18 1692.089
# 6: p1 45659.18 1631.693
# 7: p1 45659.18 1575.462
# 8: p1 45659.18 1522.980
# 9: p1 45659.18 1473.885
# 10: p1 45659.18 1427.857
# ---
# 380: MJF3_30 47555.12 1252.458
# 381: MJF3_30 47555.12 1220.370
# 382: MJF3_30 47555.12 1189.886
# 383: MJF3_30 47555.12 1160.889
# 384: MJF3_30 47555.12 1133.273
# 385: MJF3_30 47555.12 1106.941
# 386: MJF3_30 47555.12 1081.806
# 387: MJF3_30 47555.12 1057.788
# 388: MJF3_30 47555.12 1034.815
# 389: MJF3_30 47555.12 1012.819
也就是说,
dt1
的每一行都会分解为 ld
函数产生的新值。然后我们将其连接到 dt2
上并找到具有容差的匹配项。由于我推断 dt2
没有保证唯一的键(使用浮点对此并不安全),因此我将使用 rn
添加一个键,用于重新聚合回原始数据。
tol <- 0.5
dt2[, c("rn", "masstal1", "masstal2") := .(.I, masstal - tol, masstal + tol)]
dt1long[dt2, on = .(id, V1 >= masstal1, V1 <= masstal2)
][, .(mass = na.omit(mass_Da)[1]), by = .(rn, id, masstal, confirmed_mass)
][, massfound := fifelse(id %in% dt1$id, !is.na(mass), NA)]
# rn id masstal confirmed_mass mass massfound
# <int> <char> <num> <char> <num> <lgcl>
# 1: 1 p1 1689.770 no NA FALSE
# 2: 2 p2 1341.931 45489.87 45589.87 TRUE
# 3: 3 p3 1086.698 45489.19 45589.19 TRUE
# 4: 4 p3 1304.001 45489.19 45589.19 TRUE
# 5: 5 p3 1433.335 no NA FALSE
# 6: 6 p4 1425.521 X 45589.83 TRUE
# 7: 7 p4 1989.758 no NA FALSE
# 8: 8 p4 1173.885 no NA FALSE
# 9: 9 MJF2_157 1384.406 no NA FALSE
# 10: 10 MJF2_157 1065.691 no NA FALSE
# 11: 11 MJF3_157 1073.079 no NA NA
# 12: 12 MJF3_30 1742.961 no NA FALSE
# 13: 13 MJF3_30 1384.798 no NA FALSE
# 14: 14 MJF3_30 1090.666 46860.72 46860.72 TRUE
# 15: 15 MJF3_30 1447.482 no NA FALSE
# 16: 16 MJF3_61 1057.163 NA NA NA
# 17: 17 MJF3_61 1173.785 NA NA NA
# 18: 18 MJF3_61 1304.204 NA NA NA
# 19: 19 MJF3_61 1557.331 NA NA NA
# 20: 20 MJF3_61 1149.469 NA NA NA
# rn id masstal confirmed_mass mass massfound
备注:
我保留了您的
confirmed_mass
列(并将其用作聚合的“键”)只是为了与您的数据进行并排比较;我认为它实际上并不是原始 dt2
的一部分,因此应该将其从 by=
向量中删除。
我还保留了
rn
只是为了展示它在做什么...在与 dt1long
连接后可以安全地将其删除。
根据评论,我将结果分成两列,这样我们就不会合并数字和非数字。如果您确实需要它们,请随意重新组合它们。我为第二列选择了一个逻辑,因为您的意图似乎是三元的:找到、未找到或 id 不存在。