【问题标题】:Understanding constraints in agrep fuzzy matching in R了解 R 中 agrep 模糊匹配中的约束
【发布时间】:2021-08-21 23:53:07
【问题描述】:

这看起来很简单,但由于某种原因,我不明白agrep 模糊匹配涉及替换的行为。当指定all=2 时,两次替换会产生预期的匹配,但在指定substitutions=2 时不会。这是为什么呢?

# Finds a match as expected
agrep("abcdeX", "abcdef", value = T,
      max.distance = list(sub=1, ins=0, del=0))
#> [1] "abcdef"


# Doesn't find a match as expected
agrep("abcdXX", "abcdef", value = T,
      max.distance = list(sub=1, ins=0, del=0))
#> character(0)


# Finds a match as expected
agrep("abcdXX", "abcdef", value = T,
      max.distance = list(all=2))
#> [1] "abcdef"
      

# Doesn't find a match UNEXPECTEDLY
agrep("abcdXX", "abcdef", value = T,
      max.distance = list(sub=2, ins=0, del=0))
#> character(0)

由reprex package (v2.0.0) 于 2021 年 6 月 3 日创建

【问题讨论】:

    标签: r fuzzy-search agrep


    【解决方案1】:

    all 是始终适用的上限,无论其他max.distance 控件(cost 除外)如何。默认为 10%。

    # one characters can change
    agrep(pattern = "abcdXX", x = "abcdef", value = TRUE,
         max.distance = list(sub = 2, ins = 0, del = 0, all = 0.1))
    # character(0)
    
    # two characters can change
    agrep(pattern = "abcdXX", x = "abcdef", value = TRUE,
         max.distance = list(sub = 2, ins = 0, del = 0, all = 0.2))
    # [1] "abcdef"
    
    # one character can change
    agrep(pattern = "abcdXX", x = "abcdef", value = TRUE,
        max.distance = list(sub = 1, ins = 1, del = 0, all = 0.1))
    # character(0)
    
    # two characters can change
    agrep(pattern = "abcdXX", x = "abcdef", value = TRUE,
        max.distance = list(sub = 1, ins = 1, del = 0, all = 0.2))
    # [1] "abcdef"
    

    设置all 的小数模式在 1 处切换到整数模式有一点问题。

    # 8 insertions allowed
    agrep(pattern = "abcdXXef", x = "abcdef", value = TRUE,
        max.distance = list(sub = 0, ins = 2, del = 0, all = 1 - 1e-9))
    # [1] "abcdef"
    
    # 1 insertion allowed
    agrep(pattern = "abcdXXef", x = "abcdef", value = TRUE,
        max.distance = list(sub = 0, ins = 2, del = 0, all = 1))
    # character(0)
    

    当您通过将 all 设置为小于 1 来抑制 all 时,将应用距离模式的限制。

    # two substitutions allowed
    agrep(pattern = "abcdXX", 
        x = c("abcdef", "abcXdef", "abcefg"), value = TRUE,
        max.distance = list(sub = 2, ins = 0, del = 0, all = 1 - 1e-9))
    # [1] "abcdef"
    

    设置成本的目的是让您在变异空间中以不同的速率在不同的方向上移动。这将取决于您的用例。例如,某些语言方言可能更可能添加字母。您可能会选择让删除花费两次插入。默认情况下,当costs = NULL,即costs = c(ins = 1, del = 1, sub = 1)时,所有的权重相同。

    编辑:关于您关于为什么某些模式匹配而其他模式不匹配的评论,10% 是指模式中的字符数,四舍五入。

    agrep(pattern = "01234567XX89", x = "0123456789", value = TRUE, 
        max.distance = list(sub = 0, ins = 2, del = 0))
    # [1] "0123456789"
    agrep(pattern = "01234567XX", x = "0123456789", value = TRUE, 
        max.distance = list(sub = 2, ins = 0, del = 0))
    # character(0)
    num_mutations <- nchar(c("01234567XX89", "01234567XX")) * 0.1
    num_mutations
    # [1] 1.2 1.0
    ceiling(num_mutations)
    [1] 2 1
    

    第二个模式只有 10 个字符,所以只允许替换一个。

    【讨论】:

    • 感谢您的回复。这是否意味着 max.distance 参数是无用的,只要它们的约束比 all 参数控制的更宽松?我阅读了 10 次函数帮助,但我无法理解 cost 在 max.distance 中实际控制的内容。在这种方法中,我怎样才能只允许 2 个替换而不允许其他任何替换?
    • 通过一些实验,我注意到cost 控制了允许多少“错误”。那正确吗?例如,如果我设置sub=2 和cost=2,我的示例就可以工作。但如果其中任何一个设置为1,它就不起作用。直觉上,如果cost 是在没有手动指定的情况下默认添加约束,那对我来说会更有意义。也许我错过了什么
    • 感谢您更新答案。这个例子现在更有意义了。你能帮我理解我应该如何考虑为未来定义规则吗?似乎ins 和all 都控制了可以允许的插入次数。我正在考虑设置all=1-1e-9 以将此参数保持在分数模式,同时确定我可以使用sub 和ins 等参数允许多少不匹配/插入。这是一个可靠的方法吗?
    • 很抱歉用 cmets 轰炸你,但我仍然对 all 如何影响其他参数感到困惑。我发现以下令人困惑:这有效:agrep("01234567XX89", "0123456789", value = T, max.distance = list(sub=0, ins=2, del=0)) 这无效:agrep("01234567XX", "0123456789", value = T, max.distance = list(sub=2, ins=0, del=0)) 我想不通为什么。如果all 是默认为0.1 的通用上限,则两个示例都应该找不到匹配项
    猜你喜欢
    • 2018-05-31
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 2019-09-21
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多