【问题标题】:Weighting a String Distance Metric based on regular expressions基于正则表达式对字符串距离度量进行加权
【发布时间】:2017-07-27 11:23:29
【问题描述】:

是否可以对字符串距离度量进行加权,例如 Damerau-Levenshtein 距离,其中权重根据字符类型而变化?

我希望创建地址的模糊匹配,并且需要对数字和字母进行不同的加权,以便地址如下:

“5 James Street”“5 Jmaes Street”被认为相同

“5 James Street”“6 James Street”被认为是不同的

我考虑在应用字符串距离之前将地址拆分为数字和字母,但是这会错过 "5a""5b" 处的单位。数据集中的顺序也不一致,因此一个条目可能是“James Street 5”

我目前正在使用 R 和 stringdist 包,但不限于这些。

谢谢!

【问题讨论】:

  • 您是否考虑过为此项目尝试地理编码 API?
  • @AndrewBrēza 谢谢你的建议。我确实考虑过这一点,但仍想匹配一个可能写得不恰当且 API 无法获取的地址。例如 "5#Jam#es Str$eet" 仍然匹配,抱歉这里没有更具体!
  • Google Maps API 应该仍然能够识别拼写错误的地名。当我在 Google 地图中搜索 5#Jam#es Str$eet 时,正确的位置会出现在结果中。

标签: r


【解决方案1】:

这是一个想法。它涉及一些手动处理,但它可能是一个很好的起点。首先,我们使用adist()(或stringdist(),最适合您的数据的method)计算地址之间的近似字符串距离,而不关注街道编号。

m <- adist(v) 
rownames(m) <- v

> m
#                     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#5 James Street          0    2    3    1    4   17   17
#5 Jmaes Street          2    0    4    3    6   17   17
#5#Jam#es Str$eet        3    4    0    4    6   17   17
#6 James Street          1    3    4    0    4   17   17
#James Street 5          4    6    6    4    0   16   17
#10a Cold Winter Road   17   17   17   17   16    0    1
#10b Cold Winter Road   17   17   17   17   17    1    0

在这种情况下,我们可以清楚地识别这两个集群,但我们也可以使用hclust() 来可视化树状图。

cl <- hclust(as.dist(m))
plot(cl)
rect.hclust(cl, 2) 

然后,我们将每条街道标记为其对应的相似性集群,遍历它们并检查匹配的街道编号。

library(dplyr)
res <- data.frame(cluster = cutree(cl, 2)) %>%
  tibble::rownames_to_column("address") %>%
  mutate(
    # Extract all components of the address
    lst = stringi::stri_extract_all_words(address),
    # Identify the component containing the street number and return it
    num = purrr::map_chr(lst, .f = ~ grep("\\d+", .x, value = TRUE))) %>% 
  # For each cluster, tag matching street numbers
  mutate(group = group_indices_(., .dots = c("cluster", "num")))

这给出了:

#               address cluster                     lst num group
#1       5 James Street       1        5, James, Street   5     1
#2       5 Jmaes Street       1        5, Jmaes, Street   5     1
#3     5#Jam#es Str$eet       1    5, Jam, es, Str, eet   5     1
#4       6 James Street       1        6, James, Street   6     2
#5       James Street 5       1        James, Street, 5   5     1
#6 10a Cold Winter Road       2 10a, Cold, Winter, Road 10a     3
#7 10b Cold Winter Road       2 10b, Cold, Winter, Road 10b     4

然后您可以使用distinct() pull() 基于group 的唯一地址:

> distinct(res, group, .keep_all = TRUE) %>% pull(address)
#[1] "5 James Street"       "6 James Street"       "10a Cold Winter Road"
#    "10b Cold Winter Road"

数据

v <- c("5 James Street", "5 Jmaes Street", "5#Jam#es Str$eet", "6 James Street",
       "James Street 5", "10a Cold Winter Road", "10b Cold Winter Road")

【讨论】:

  • 这是一个很好的建议,史蒂文。它是一个很好的使用基础。我认为 adist 会错过一些匹配,但我可以使用一些字符串 dist 指标来捕获它们!谢谢!
猜你喜欢
  • 2010-10-16
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
相关资源
最近更新 更多