【问题标题】:R find matches for more than 2 vectorsR查找超过2个向量的匹配项
【发布时间】:2019-02-17 09:42:09
【问题描述】:

我正在处理一组 5 个 excel 列 A,B,C,D,E 的单词 "Aaa","Aab"...,我想在所有列中找到完全匹配的内容(在 R 中)。

A   B   C   D   E  
Aaa Aaa Baa Aaa Ass
Aab Ccc Aaa Baa Aaa
Ccc Abc Ccc Ccc Ccc
... ... ... ... ... 

我为每一列创建一个向量。
为此,我尝试了带有ifgrep 函数的for 循环。

<pre>
    for(i in A_vector) {
          if(grep("i", B_vector))
              if(grep("i", C_vector))
                  if(grep("i", D_vector))
                      if(grep("i", E_vector))
                          print(i)
      }
<code>

(但我只获得了第一个向量A_vector中的单词)。
最后,我希望有一个包含 5 列中匹配的单词 "Aaa", "Bbb"... 的向量。我不需要向量中每个匹配项的位置,只需要所有向量共有的单词。

 Result
    [1] "Aaa"
    [2] "Ccc"
    [n]  ...

提前谢谢你!

【问题讨论】:

  • Hiho J L Carballo,欢迎来到 stackoverflow。我认为您可以通过一些直接的比较来存档。索引 = 其中(数据$A == 数据$B & 数据$A == 数据$C % 数据$A == 数据$D $ 数据$A == 数据$E)。这为您提供了所有列中包含相同字符串的每一行的索引。因此,使用 data[index] 您可以获得所有具有相同字符串的行。使用 data$A[index] 你会得到一个向量,其中所有字符串在所有列上都相等。
  • grep 非常适合使用正则表达式匹配模式。对于精确匹配,请使用 ==%in%,具体取决于您是否需要逐元素匹配。但是,对于寻找“共同元素”intersect 可能是一个更好的选择。如果您的输入是名为dd 的数据框,我认为您正在寻找Reduce(inntersect, dd)

标签: r excel matching grepl


【解决方案1】:

您要求在每个列表之间找到共同的元素,而不仅仅是一般的重复元素。下面的重复项是Aaa, Ccc, Ddd, and Xxx,但唯一重复的元素是Xxxintersect() 将通过一些双重 lapply 函数来完成此任务。

A = list("Aaa", "Aaa", "Ccc", "Ccc")
B = list("Ddd", "Ddd", "Ddd", "Eee")
C = list("Fff", "Ggg", "Hhh", "Iii", "Jjj")
D = list("Kkk", "Lll", "Mmm", "Nnn", "Xxx")
E = list("Ppp", "Qqq", "Rrr", "Xxx")
Mylist <- list(A, B, C, D, E)

dupes <- unlist(lapply(Mylist, function(x) lapply(Mylist, function(y) intersect(x,y))))

unique(dupes[duplicated(dupes)])

[1] "Xxx"

要查看交叉点在哪里,这将告诉您第 4 个列表与第 5 个列表有 1 个共同元素:

sapply(seq_len(length(Mylist)), function(x) sapply(seq_len(length(Mylist)), function(y) length(intersect(unlist(Mylist[x]), unlist(Mylist[y])))))

     [,1] [,2] [,3] [,4] [,5]
[1,]    2    0    0    0    0
[2,]    0    2    0    0    0
[3,]    0    0    5    0    0
[4,]    0    0    0    5    1
[5,]    0    0    0    1    4

【讨论】:

    【解决方案2】:

    这是根据您的解释编辑的答案,您希望找到至少两列之间的所有匹配项:

     Mylist <-list(A=c("Aaa","Aab","Ccc","Ddd"), B=c("Aaa","Ccc","Abc","Abd"), C=c("Baa","Aaa","Ccc","Abb","Ddd"), D=c("Aaa","Baa","Ccc","CBB","Baa"),E=c("Ass","Aaa","Ccc","Gef"))
     CharVec <-unlist(Mylist)
     unique(CharVec[duplicated(CharVec)])
    

    【讨论】:

    • 我正在处理 5 个变量,每个变量的长度为 150 到 650 个单词。单词在同一个变量中不重复。使用Reduce(intersect, dd)Reduce(df, intersect) 我得到一个错误“参数“init”丢失,没有默认值”。然后我也尝试调用.init 作为第一个变量,但没有成功。
    • 命令和函数是针对具体情况的。您正在尝试 Reduce 而不是 reduce。您还需要library(purrr)。 @shirin 这会在所有列之间找到匹配项。 OP 正在寻找至少 2 列之间的匹配项。
    • @JLCarballo 我在您发表评论后编辑了我的答案,请看看是否是您需要的
    • 谢谢@shirin!这样我就可以很好地获得所有匹配项。我还用 excel 进行了检查,所有列都不匹配,但有些列在 2 或 3 之间。
    • @JLCarballo 这不符合您的要求。这会取消对所有列的分组并找到任何重复项。例如Mylist &lt;-list(A=c("Aaa","Aaa","Ccc","Ccc"), B=c("Ddd","Ddd","Ddd","Eee"), C=c("Fff","Ggg","Hhh","Iii","Jjj")),此解决方案将返回Aaa, Ccc, and Ddd,它们不会跨列重复。
    【解决方案3】:

    您可以使用 data.table 尝试一些东西,虽然有点复杂:

    library(data.table)
    
    setDT(data)
    
    data[, unlist(lapply(.SD, intersect, y = unique(A))), A][, .N, A][N == {ncol(dt) - 1}, A]
    

    【讨论】:

    • 我不确定这是否能满足 OP 的要求。
    猜你喜欢
    • 1970-01-01
    • 2023-01-01
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2020-02-13
    • 2017-12-14
    相关资源
    最近更新 更多