【问题标题】:How do I match table entries to a second table's list entries in R?如何将表条目与 R 中的第二个表的列表条目匹配?
【发布时间】:2015-06-04 18:53:48
【问题描述】:

我有两张表,table1 有一列字符串。我想在另一个表 table2 中找到每个字符串的匹配项,但在相应的 table2 列中,每个单元格包含每个行条目的列表。

到目前为止,我已经弄清楚了如何使用 grepl 来匹配特定条目:

grepl(table1$label[i],table2$labels[[j]][k])

对于某些 i、j 和 k。 i 和 j 是固定的,因为它们分别是表 1 和表 2 中的行数,但 k 是一些正值,所以我有这样的东西:

for (i in 1:nrow(table1)){
  for (j in 1:nrow(table2){
    for(k ?){
    grepl(table1$label[i],table2$labels[[j]][k])
    }
  }
}

我不太确定要为 k 循环放什么。

一旦我确定了包含 table1 字符串的 table2 行,我想做的是报告来自不同 table2 列的相应值并将这些值附加到 table1 中的相应字符串行,所以我'我猜我需要更多的 for 循环...有没有任何快捷方式可以解决诸如此类的多个引用问题?

一些示例数据(注意 table2 列表中也有缺失值,但我假设在匹配这些时会被忽略,其他条目是字符类):

表 1

    label 
1   Tom     
2   Gemma     
3   Graham     

表 2(更新)

     item      labels 
1    Apple     Tom, ,John, ,Terry,     
2    Orange    Bryan, ,Graham,  
3    Pear      Finn, ,Gemma, ,Graham, 

输出

表 1

    label   item
1   Tom     Apple
2   Gemma   Pear  
3   Graham  Orange, Pear

从使用dput 我得到

Table1 <- structure(list(label = c("Tom", "Gemma", "Graham")), .Names = "label", 
class = "data.frame", row.names = c(NA, 
-3L))


Table2 <- structure(list(item = c("Apple", "Orange", "Pear"), labels = list(
    structure(c("Tom", "", "John", "", "Terry", ""), .Dim = c(6L, 
    1L)), structure(c("Bryan", "", "Graham", ""), .Dim = c(4L, 
    1L)), structure(c("Finn", "", "Gemma", "", "Graham", ""), .Dim = c(6L, 
    1L)))), .Names = c("item", "labels"), row.names = c(NA, -3L
), class = "data.frame")

附录:关于我最初使用grepl,Table2中的一些标签与Table1中的标签只有部分匹配,但名称在Table1中是唯一的,所以我想申请匹配Table1标签,例如 Graham (Table1) 到 Graham (Table2) 和 Graham Green (Table2) 例如

表 2(版本 2)

     item      labels 
1    Apple     Tom, ,John, ,Terry,     
2    Orange    Bryan, ,Graham,  
3    Pear      Finn, ,Gemma, ,Graham Green, 

输出 Table1 将是相同的。

【问题讨论】:

  • 如果您想要有效的解决方案,请提供示例数据集和所需的输出。
  • 对于包含列表的数据(如您的“表 2”),我们可能需要数据本身来了解其格式。考虑dput 或显示用于制作表格的代码。
  • 谢谢@Frank,我没用过dput,很有用!

标签: r loops for-loop grepl


【解决方案1】:

这是使用data.table 包的尝试

library(data.table)
res <- setDT(Table2)[, list(label = unlist(labels)), by = item]
setkey(res, label)[Table1, toString(unique(item)), by = .EACHI]
#     label         item
# 1:    Tom        Apple
# 2:  Gemma         Pear
# 3: Graham Orange, Pear

我基本上在这里所做的是将每个项目的labels 拆分为Table2。然后我聚合了每个标签的唯一项目,同时执行二进制左连接回到Table1


编辑为您的新Table2,您可以将代码修改为

res <- setDT(Table2)[, list(label = unlist(labels)), by = item]
Table1["item"] <- sapply(Table1$label, function(x) toString(unique(res[grepl(x, label), item])))
Table1
#    label         item
# 1    Tom        Apple
# 2  Gemma         Pear
# 3 Graham Orange, Pear

【讨论】:

  • 谢谢大卫,我试过你的代码,但我无法让它工作,也许是数据输入 - 我已经在我的问题中提供了表格的dput 来澄清。
  • 嗨,大卫,如果我在表 1 和表 2 中的标签包含像 Tom Jones 这样的全名或像 Gemma Austen-Davenport 这样的连字符名称,而不仅仅是 Tom 例如或是否还有其他特殊字符,如/
  • 我不这么认为。你试过了吗?
  • 它适用于我提出的示例。我会在一个更大的例子上再试一次,看看。谢谢。
  • 谢谢大卫,这段代码运行良好,谢谢 - 是的,我可以删除新的。
【解决方案2】:

这是一个在后端使用 data.tableqdapTools 方法。您的数据类型有点模棱两可。 dput 在这里会很有帮助。

我认为您的数据基于 NA 评论

Table1 <- read.table(text="   label 
1   Tom     
2   Gemma     
3   Graham", header=TRUE)


key <- list(
    Apple  = c('Tom', NA, 'John', NA, 'Terry'),
    Orange =  c('Bryan', 'Graham'),
    Pear =  c('Finn', 'Gemma', NA, 'Graham')
)

现在查找值:

library(qdapTools)
Table1[["item"]] <- lapply(Table1[[1]], lookup, key)

##    label         item
## 1    Tom        Apple
## 2  Gemma         Pear
## 3 Graham Orange, Pear

如果你有data.frame,那么试试:

key2 <- data.frame(x = names(key))
key2[["item"]] <- key

Table1[["item2"]] <- lapply(Table1[[1]], lookup, setNames(as.list(key2[[2]]), key2[[1]]))

如果该列确实是折叠/粘贴的向量:

key2 <- data.frame(x = names(key))
key2[["item"]] <- lapply(key, paste, collapse=", ")
Table1[["item2"]] <- lapply(Table1[[1]], lookup, setNames(strsplit(as.character(key2[[2]]), "\\s*,\\s*"), key2[[1]]))

【讨论】:

  • 感谢 Tyler,我提供了上面表格的 dput 以澄清,我认为您的 table1 格式与我的略有不同,但我会使用您的代码。很抱歉没有提供更清晰的数据,我以后会使用dput提供数据输入。
猜你喜欢
  • 1970-01-01
  • 2016-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 2017-10-13
相关资源
最近更新 更多