【问题标题】:Find rows with the longest matching string查找具有最长匹配字符串的行
【发布时间】:2020-08-11 01:16:02
【问题描述】:

我有一个由组组成的数据框,其中对应的动物为字符串:

data = data.frame(group = c(1,2,3,4), animal = c("cat, dog, horse, mouse", "cat, dog, horse", "cat, dog,", "cat, dog, frog, cow"))

我想返回最长字符串匹配的组。在此示例中,第 1 组和第 2 组将匹配,因为 4 只动物中有 3 只相同。此外,第 2 组和第 3 组将匹配为 3 只动物中的 2 只匹配。但是,没有与第 4 组匹配的组,因为 4 只动物中只有 2 只匹配。

我想返回一个显示匹配组的数据框:

group_a group_b
   1       2
   2       3

我不确定这是否可能。我研究了如何匹配部分字符串,但努力寻找类似的例子来适应。有什么想法吗?

谢谢。

【问题讨论】:

  • 你能解释一下关于 group_a 和 group_b 如何以不同方式形成的分组吗?看起来可能,但需要澄清一下。
  • 不完全确定您的意思。但想法是,当两个组具有最长的匹配字符串时,它将返回两个匹配组的编号。这有帮助吗?
  • 明白!您想创建尽可能多的匹配组吗?在第 4 组中,猫、狗与其他三个组匹配,为什么不能选择其中一个?你想匹配一半以上的动物吗?
  • 是的,尽可能多的匹配组,但理想情况下,我希望它们只在缺少一只动物时匹配。 IE。 4 种中有 3 种,或 9 种中有 8 种(我的数据集多达 9 种动物)。
  • 你想实际匹配子字符串吗?还是您的用例本质上是关于匹配单词的?

标签: r string matching longest-substring


【解决方案1】:

鉴于您对想要匹配单词的评论,这里是文本方法的开始,可能会有所帮助。基本上,我们想拆分每个单词并计算每个语句中的出现次数。

library(tidytext)
library(dplyr)
library(tidyr)

dtm <- data %>%
  unnest_tokens("word", "animal", token = "regex", pattern = ",") %>% 
  mutate(word = str_trim(word)) %>%
  count(group, word) %>% 
  pivot_wider(names_from = "word", values_from = "n", values_fill = list(n = 0)) 

您所知道的是一个文档术语矩阵。我们现在已将您的问题从匹配一个正则表达式更改为查找匹配最多的向量。

# A tibble: 4 x 7
  group   cat   dog horse mouse   cow  frog
  <dbl> <int> <int> <int> <int> <int> <int>
1     1     1     1     1     1     0     0
2     2     1     1     1     0     0     0
3     3     1     1     0     0     0     0
4     4     1     1     0     0     1     1

一个简单的方法是提取矩阵部分并乘以。

mat <- as.matrix(select(dtm, -group))
matches <- (mat %*% t(mat))

这将为您提供每个组匹配的矩阵。例如,第 1 行第 2 列显示了第 1 组和第 2 组之间的三个单词匹配项(猫、狗和马)。

matches
     [,1] [,2] [,3] [,4]
[1,]    4    3    2    2
[2,]    3    3    2    2
[3,]    2    2    2    2
[4,]    2    2    2    4

然后你可以从那里玩东西。例如,拉出行和列 ID,然后拉出矩阵的上三角部分可以给你一个总结。我认为从这里开始,这只是您要如何过滤表格的问题。

data.frame(row = c(row(matches)),
           col = c(col(matches)),
           value = c(matches),
           upper = c(upper.tri(matches))) %>% 
  filter(upper == TRUE)

  row col value upper
1   1   2     3  TRUE
2   1   3     2  TRUE
3   2   3     2  TRUE
4   1   4     2  TRUE
5   2   4     2  TRUE
6   3   4     2  TRUE

【讨论】:

    【解决方案2】:

    这是你要找的吗?

    lst <- regmatches(data$animal,gregexpr("\\w+",data$animal))
    
    u <- lapply(seq_along(lst)[-length(lst)], 
                function(p) subset(data.frame(group_a = p,
                                              group_b = seq_along(lst)[-(1:p)],
                                              longestmatch = sapply(seq_along(lst)[-(1:p)], 
                                                                    function(q) length(intersect(lst[[p]],lst[[q]])))),
                                   longestmatch == max(longestmatch)))
    
    res <- do.call(rbind,c(make.row.names = FALSE,u))
    

    这样

    > res
      group_a group_b longestmatch
    1       1       2            3
    2       2       3            2
    3       2       4            2
    4       3       4            2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-26
      • 2017-07-13
      • 1970-01-01
      • 2016-06-14
      • 1970-01-01
      • 2016-07-01
      • 1970-01-01
      • 2016-01-16
      相关资源
      最近更新 更多