gpt4 book ai didi

r - 模糊与精确匹配相结合

转载 作者:行者123 更新时间:2023-12-04 12:12:12 25 4
gpt4 key购买 nike

我有两个包含地址的表(街道,城市,邮政编码和两个包含这些值的串联值的字段),我想对Zipcode进行模糊匹配,但仅适用于StrCity值完全相同的情况。我首先从字典中仅选择与StrCity匹配的地址,然后再进行模糊匹配,但是存在两个问题:

1)如果与邮政编码匹配,则不会考虑街道和城市
2)如果与地址(包含邮政编码,街道和城市的所有地址)匹配,它还会返回可能的值,其中在同一邮政编码上,存在另一条距离足够近的街道。

可能我需要同时进行两种不同的匹配(一种模糊和一种精确)的方法,但是我不确定如何实现它,同时又不影响计算机性能。

这是TableAd的数据示例:

StrCity              ID      Zipcode Street       City     Address
BiałowiejskaWarszawa 5148676 01-459 Białowiejska Warszawa 01-459BiałowiejskaWarszawa
BukowińskaWarszawa 6423687 02-730 Bukowińska Warszawa 02-730BukowińskaWarszawa
KanałowaWarszawa 6425093 03-536 Kanałowa Warszawa 03-536KanałowaWarszawa

和字典示例:
Zipcode Street   City     Address                StrCity
02-882 Agaty Warszawa 02-882AgatyWarszawa AgatyWarszawa
03-663 Kanałowa Warszawa 03-663KanałowaWarszawa KanałowaWarszawa
03-536 Kołowa Warszawa 03-536KołowaWarszawa KołowaWarszawa

这是我当前的代码:
TableMatch <- merge(TableAd, TableDict, by="StrCity")
TableMatch <- TableMatch[, -grep("y", colnames(TableMatch))]
names(TableMatch)[names(TableMatch)=="Zipcode.x"] <- "Zipcode"
names(TableMatch)[names(TableMatch)=="Address.x"] <- "Address"

ResultTable <- TableMatch %>%
stringdist_left_join(TableDict, by="Address", distance_col="dist", method="lv", max_dist=5, ignore_case = TRUE) %>%
select(ID, Zipcode.x, Address.x, Address.y, dist) %>%
group_by(Address.x) %>%
# select best fit record
top_n(-1, dist)

我在上面提供的示例中专门发现了问题-该脚本验证了字典中存在strCityKanałowaWarszawa,但是更改邮政编码时的组合地址字符串的Levenshtein距离与将街道更改为Kołowa时的组合地址字符串的Levenshtein距离相同,该邮政编码与被检查的人。
在这里,它会返回两个更改,但是如果邮政编码之间只有2位或1位数字的差异,那么在更改邮政编码的同时,它可能会错误地建议更换街道。

注意:我正在使用 purrrdplyrfuzzyjoin软件包。

最佳答案

这是使用更灵活的常规fuzzyjoin函数使其工作的一种方法:

数据

TableAd <- read.table(h=T,strin=F,text="StrCity ID Zipcode Street City Address
BiałowiejskaWarszawa 5148676 01-459 Białowiejska Warszawa 01-459BiałowiejskaWarszawa
BukowińskaWarszawa 6423687 02-730 Bukowińska Warszawa 02-730BukowińskaWarszawa
KanałowaWarszawa 6425093 03-536 Kanałowa Warszawa 03-536KanałowaWarszawa")

TableDict <- read.table(h=T,strin=F,text="Zipcode Street City StrCity
02-882 Agaty Warszawa 02-882AgatyWarszawa AgatyWarszawa
03-663 Kanałowa Warszawa 03-663KanałowaWarszawa KanałowaWarszawa
03-536 Kołowa Warszawa 03-536KołowaWarszawa KołowaWarszawa")

解决方案
library(fuzzyjoin)
library(stringdist)
res <- fuzzy_left_join(
TableAd,
TableDict,
by=c("StrCity","Zipcode"),
list(`==`, function(x,y) stringdist(tolower(x), tolower(y), method="lv") <= 5)
)
res %>%
select(StrCity = StrCity.x, everything(), - StrCity.y)

# StrCity ID Zipcode.x Street.x City.x Address.x Zipcode.y Street.y City.y Address.y
# 1 BialowiejskaWarszawa 5148676 01-459 Bialowiejska Warszawa 01-459BialowiejskaWarszawa <NA> <NA> <NA> <NA>
# 2 BukowinskaWarszawa 6423687 02-730 Bukowinska Warszawa 02-730BukowinskaWarszawa <NA> <NA> <NA> <NA>
# 3 KanalowaWarszawa 6425093 03-536 Kanalowa Warszawa 03-536KanalowaWarszawa 03-663 Kanalowa Warszawa 03-663KanalowaWarszawa

上述解决方案的问题在于,它内部产生笛卡尔积,如果您有大量数据,则可能会出现问题。由于您要加入串联字符串,因此影响减小了,但是感觉像是可以更好地避免的黑客攻击。

解决此问题的一种方法是将模糊联接应用于由完全匹配确定的子集对,我们在下面定义了一个函数来实现,并结合了增强的样本数据。

数据
TableAd2 <- read.table(h=T,strin=F,text="ID Zipcode Street City
5148676 01-459 Białowiejska Warszawa
6423687 02-730 Bukowińska Warszawa
6423687 99-999 Agaty Warszawa
6423687 02-883 Agaty Warszawa
6425093 03-536 Kanałowa Warszawa")

TableDict2 <- read.table(h=T,strin=F,text="Zipcode Street City
02-882 Agaty Warszawa
03-663 Kanałowa Warszawa
03-536 Kołowa Warszawa
02-730 Bukowińska Warszawa")

应该匹配
  • Bukowińska,因为其邮政编码与
  • 完全匹配
  • Kanałowa应该匹配,因为其邮政编码中只有3个数字不同
  • Agaty只应匹配1个项目,因为5个字符不同,我们最多允许输入3个

  • 函数
    fuzzy_inner_join2 <- function(x,y,by, match_fun, ...){
    match_fun_equal_lgl <- sapply(match_fun, identical, `==`)
    # columns to use for exact join equivalent
    by_exact = by[match_fun_equal_lgl]
    # columns to use for fuzzy join on relevant subsets of data (for efficiency)
    by_fuzzy = by[!match_fun_equal_lgl]
    # update match_fun
    match_fun <- match_fun[!match_fun_equal_lgl]
    # trim inputs of irrelevant data
    x <- dplyr::semi_join(x,y,by= by_exact)
    y <- dplyr::semi_join(y,x,by= by_exact)
    # make lists so we have pairs of data frames to fuzzy join together
    x_list <- dplyr::group_split(dplyr::group_by_at(x, by_exact))
    y_list <- dplyr::group_split(dplyr::group_by_at(y, by_exact), keep = FALSE)
    # apply fuzzy join on pairs and bind the results
    map2_dfr(x_list,y_list, fuzzyjoin::fuzzy_inner_join, match_fun = match_fun,
    by = by_fuzzy, ...)
    }

    解决方案
    fuzzy_inner_join2(
    TableAd2,
    TableDict2,
    by=c("City","Street","Zipcode"),
    match_fun = list(
    `==`, `==`,
    function(x,y) stringdist(tolower(x), tolower(y), method="lv") <= 3)
    )

    # # A tibble: 3 x 5
    # ID Zipcode.x Street City Zipcode.y
    # <int> <chr> <chr> <chr> <chr>
    # 1 6423687 02-883 Agaty Warszawa 02-882
    # 2 6423687 02-730 Bukowinska Warszawa 02-730
    # 3 6425093 03-536 Kanalowa Warszawa 03-663

    关于r - 模糊与精确匹配相结合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48008903/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com