【问题标题】:Finding all matches in a vector in a data.table在 data.table 中的向量中查找所有匹配项
【发布时间】:2013-01-02 08:53:51
【问题描述】:

这个问题是 this previous question 的后续问题。

我有一个 id 向量,sampleIDs。 我还有一个 data.table,rec_data_table,按出价键并包含一列, A_IDs.list 其中每个元素都是 aID 的集合(向量)。

我想创建第二个 data.table 包含 sampleIDs 和其中
对于每个aID,都有一个对应的所有bID的向量
该 aID 出现在 A_IDs.list 列中。

例子:

> rec_data_table
   bid counts names_list A_IDs.list
1: 301     21        C,E       3,NA
2: 302     21          E         NA
3: 303      5      H,E,G     8,NA,7
4: 304     10        H,D        8,4
5: 305      3          E         NA
6: 306      5          G          7
7: 307      6        B,C        2,3

> sampleIDs
[1] 3 4 8

AB.dt <- data.table(aID=sampleIDs, key="aID")

# unkown step
AB.dt[ , bIDs := ????  ]

# desired result:
> AB.dt
    aid     bIDs
1:    3  301,307
2:    4      304
3:    8  303,304



我在AB.dt[] 调用中尝试了几行不同的行。 我能得到的最接近的是

rec_data_table[sapply(A_IDs.list, function(lst) aID %in% lst), bID]

对于给定的aID,这将为我提供所需的结果,我可以申请
sampleIDs 上创建向量列表并构建所需的结果。

但是,我怀疑必须有一个更“适合 data.table”的方法来完成此操作。任何建议表示赞赏。



#--------------------------------------------------#
#           SAMPLE DATA                            #

library(data.table)
set.seed(101)

  rows <- size <- 7
  varyingLengths <- c(sample(1:3, rows, TRUE))
  A <-  lapply(varyingLengths, function(n) sample(LETTERS[1:8], n))
  counts <- round(abs(rnorm(size)*12))   
rec_data_table <- data.table(bID=300+(1:size), counts=counts, names_list=A, key="bID")

A_ids.DT <- data.table(name=LETTERS[c(1:4,6:8,10:11)], id=c(1:4,6:8,10:11), key="name")
rec_data_table[, A_IDs.list := sapply(names_list, function(n) c(A_ids.DT[n, id]$id))]
sampleIDs <- c(3, 4, 8)

【问题讨论】:

  • 您的示例数据不起作用,因为我们没有定义 rowssize
  • 感谢@Justin 指出这一点。我已经着手修复了示例数据。

标签: r data.table


【解决方案1】:

我认为这会提供您想要的输出:

myfun <- function(ids) {
  any(ids %in% sampleIDs)
}

rec_data_table[sapply(A_IDs.list, myfun),]

#    bID counts names_list A_IDs.list
# 1: 301     21        C,E       3,NA
# 2: 303      5      H,E,G     8,NA,7
# 3: 304     10        H,D        8,4
# 4: 307      6        B,C        2,3

rec_data_table[sapply(A_IDs.list, myfun), list(bID, A_IDs.list)]

#   bID A_IDs.list
# 1: 301       3,NA
# 2: 303     8,NA,7
# 3: 304        8,4
# 4: 307        2,3

您可以在A_IDs.list 列上使用unlist 来获取长data.table:

unique(na.omit(rec_data_table[sapply(A_IDs.list, myfun), list(bID, unlist(A_IDs.list))]))

#    bID V2
# 1: 301  3
# 2: 304  8
# 3: 301  7
# 4: 303  8
# 5: 304  4
# 6: 307  2

我建议使用“长”数据而不是上面的嵌套列表构造,因为它通常会导致更简单的代码。

【讨论】:

    【解决方案2】:
    bIDs <- lapply(sampleIDs, function(x){rec_data_table$bID[sapply(rec_data_table$A_IDs.list, function(y){x %in% y})]})
    AB.dt <- data.table(aID=sampleIDs, bIDs=bIDs)
    

    也许有更快的方法,但这个方法有效。 :)

    【讨论】:

      【解决方案3】:

      在我对上一个问题的回答中将tmp加入A_ids.DT之后,您可以通过在tmp中查找sampleIDs来获得所需的输出:

      # ... from previous answer
      # tmp <- A_ids.DT[tmp]
      
      AB.dt <- setkey(tmp, id)[J(sampleIDs)][, list(bIDs = list(bID)),
                                             by = list(aid = id)]
      
      # setkey(tmp, orig.order)
      # previous answer continues ...
      

      请注意,这两个问题中bID 列的大小写不同。当然,这是假设您没有在示例数据中执行倒数第二行。由于data.table 的二分搜索的奇迹,当有很多记录时,这应该比基于%in% 的方法更快。

      【讨论】:

      • 再次感谢您对此问题和上一个问题的意见
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 2021-10-17
      • 2012-08-04
      • 1970-01-01
      • 2023-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多