【问题标题】:Fuzzy Address matching R模糊地址匹配 R
【发布时间】:2022-01-06 15:52:40
【问题描述】:

是的,以前有人问过这个问题,但我找不到可以为这个问题提供简单、清晰答案的线程。

我有下面的示例数据 - 我有两列,col1 是当前地址,col2 是我被告知比当前地址“更好”的地址。我需要看看第二列比第一列“好”多少。大多数情况下,第二个更好,因为它包含第一个缺少的辅助信息,例如公寓号码。

test <- as.data.frame(matrix(c(
"742 Evergreen Terrace" , "742 Evergreen Terrace Apt 3" , 
"31 Spooner Street #42" , "31 Spooner Street", 
"129 W 81st Street" , "129 W 81st Street Apt 5A" , 
"245 E 73rd Street", "245 E 73rd Street Apt 6") , ncol=2, byrow=TRUE, 
dimnames=list(NULL, c("old_addr" , "new_addr"))) ,stringsAsFactors=FALSE)

我在这里找到了一个接近我想要的答案: Fuzzy match row in one column with same row in next column

我需要创建第三列,它是一个简单的 1/0 变量,如果是近似匹配,则 == 1,否则为 0。我需要能够为近似匹配指定阈值。

对于我的第一个示例 - 742 Evergreen Terrace 与 742 Evergreen Terrace Apt 3,长度相差六。我需要能够指定六、八或其他的长度差。

我查看了 agrep,但我需要比较同一行中的两列数据,但它不允许这样做。我也尝试过 lapply,但它的结果让我认为它正在循环遍历整个列中的所有数据,我需要逐行比较。还有我不明白的最大距离,下面的 ifelse 和最大值为 1(如果我正确理解为 1 == 可以有一个编辑或更改单位),它应该会抛出错误,但它只会在一个案例。

agrep(test$old_addr, test$new_addr, max.distance = 0.1, ignore.case = TRUE)

test$fuzz_match <- lapply(test$old_addr , agrep , x = 
test$new_addr , max.distance = 1 , ignore.case = TRUE)

感谢您的帮助,谢谢!

【问题讨论】:

  • 您可以先将所有同义词转换为通用形式。例如,St. 变成 Street。 Av 和 Ave 成为大道。所有AptApartment# 都可能映射到 Apt。或者,如果您只需要建筑地址,您可能会决定放弃它们。取决于你的目标
  • 这是计划的一部分,是的,但与此同时我需要一些东西。不过建议不错,谢谢,
  • 没有简单干净答案的线程,因为不存在这样的答案。一般来说,两种方法效果最好:首先规范化你的字符串。例如全部大写,去掉标点符号,更改 Apt.和strt。到“公寓”和“街道等”(如上所述)。接下来,使用近似匹配策略,例如使用stringdist::amatchfuzzyjoin 包。

标签: r lapply fuzzy-comparison


【解决方案1】:

您可以计算每对之间的Levenshtein distance。那么你需要决定的是距离必须有多大才能使两者不是同一个地址。

test$lev_dist <- mapply(adist, test$old_addr, test$new_addr)

test$same_addr <- test$lev_dist < 5

test
#                old_addr                    new_addr lev_dist same_addr
# 1 742 Evergreen Terrace 742 Evergreen Terrace Apt 3        6     FALSE
# 2 31 Spooner Street #42           31 Spooner Street        4      TRUE
# 3     129 W 81st Street    129 W 81st Street Apt 5A        7     FALSE
# 4     245 E 73rd Street     245 E 73rd Street Apt 6        6     FALSE

您可以以类似的方式将agrep()mapply() 一起使用。

test$agrep_match <- mapply(agrep, test$old_addr, test$new_addr)
test$agrep_match <- lengths(test$agrep_match) == 1
test
#                old_addr                    new_addr agrep_match
# 1 742 Evergreen Terrace 742 Evergreen Terrace Apt 3        TRUE
# 2 31 Spooner Street #42           31 Spooner Street       FALSE
# 3     129 W 81st Street    129 W 81st Street Apt 5A        TRUE
# 4     245 E 73rd Street     245 E 73rd Street Apt 6        TRUE

agrep() 也是基于 Levenshtein 距离,但有许多不同的选项可用于调整阈值,我相信您已经找到了。


除了 Levenshtein 之外,还有其他差异度量可能更适合此应用程序。包stringdist 有许多其他可用的字符串距离指标。

【讨论】:

  • 太棒了。干净,简单,轻松。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 2016-07-07
  • 2018-04-26
  • 2020-11-01
  • 1970-01-01
  • 2022-01-08
相关资源
最近更新 更多