R:将函数应用于 data.table 1 中的单个值,并将向量中的结果单个值与 data.table 2 中的单个值进行比较

问题描述 投票:0回答:1

我知道如何将函数应用于 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)

非常感谢任何帮助。

vector merge data.table lookup fault-tolerance
1个回答
0
投票

首先,我假设您的一些数字在

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 不存在。

© www.soinside.com 2019 - 2024. All rights reserved.