我有两个大型数据集,一个大约50万条记录,另一个大约70K。这些数据集具有地址。我希望匹配较小数据集中的任何地址是否存在于较大的数据集中。正如您可以想象的那样,地址可以用不同的方式和不同的情况写入,所以看到应该匹配的时候没有匹配,而不应该匹配的时候有匹配,这是相当恼人的。我做了一些研究,找出了可以使用的软件包stringdist。然而,我被困住了,我觉得我没有充分利用它的能力,关于这一点的一些建议会有所帮助。
下面是一个示例虚拟数据,以及我为解释这种情况而创建的代码
Address1 <- c("786, GALI NO 5, XYZ","rambo, 45, strret 4, atlast, pqr","23/4, 23RD FLOOR, STREET 2, ABC-E, PQR","45-B, GALI NO5, XYZ","HECTIC, 99 STREET, PQR")
df1 <- data.table(Address1)
Address2 <- c("abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR")
df2 <- data.table(Address2)
df1[, key_match := gsub("[^[:alnum:]]", "", Address1)]
df2[, key_match := gsub("[^[:alnum:]]", "", Address2)]
fn_match = function(str, strVec, n){
strVec[amatch(str, strVec, method = "dl", maxDist=n,useBytes = T)]
}
df1[!is.na(key_match)
, address_match :=
fn_match(key_match, df2$key_match,3)
]如果您看到输出,它会给出df1中address_match下的匹配项。如果我在我的主数据上应用相同的代码,代码仍然在过去30小时内运行。虽然我已经转换成了data.table。不知道怎么才能加快速度。
我正在做进一步的阅读,偶然发现了stringdist。这似乎更有帮助,我可以根据地址和空格划分地址,并检查每个地址列表中是否存在每个单词,并根据最大匹配创建匹配摘要。然而,我不太擅长循环。如何为每个单词遍历较小文件中的每个地址,并签入较大文件中的各个地址,并创建匹配矩阵?帮帮忙!!
发布于 2017-03-01 22:06:23
我有一个不需要data.table的解决方案,但如果set很大,可以使用package:parallel运行
rbind.pages(
parallel::mclapply(Address1, function(i){
data.frame(
src = i,
match = Address2[which.min(adist(i, Address2))]
)
}, mc.cores = parallel::detectCores() - 2)) %>%
select(`src (Address1)`= 1, `match (Address2)` = 2)然后给出输出解决方案:
src (Address1) match (Address2)
1 786, GALI NO 5, XYZ 786, GALI NO 4 XYZ
2 rambo, 45, strret 4, atlast, pqr del, 546, strret2, towards east, pqr
3 23/4, 23RD FLOOR, STREET 2, ABC-E, PQR 23/4, STREET 2, PQR
4 45-B, GALI NO5, XYZ 45B, GALI NO 5, XYZ
5 HECTIC, 99 STREET, PQR 23/4, STREET 2, PQR编辑:
我意识到,如果没有看到距离计算,这可能没有多大帮助,因此我将数据复制到更大的随机集中,然后修改函数以显示字符串距离计算和处理时间
rand_addy_one <- rep(Address1, 1000)[sample(1:1000, 1000)]
rand_addy_two <- rep(Address2, 3000)[sample(1:3000, 3000)]
system.time({
test_one <<- rbind.pages(parallel::mclapply(rand_addy_one, function(i) {
calc <- as.data.frame(drop(attr(adist(i, rand_addy_two, counts = TRUE), "counts")))
calc$totals <- (rowSums(calc))
calc %>% mutate(src = i, target = rand_addy_two) %>%
filter(totals == min(totals))
}, mc.cores = parallel::detectCores() - 2)) %>%
select(`source Address1` = src, `target Address2(matched)` = target,
insertions = ins, deletions = del, substitutions = sub,
total_approx_dist = totals)
})
user system elapsed
24.940 1.480 3.384
> nrow(test_one)
[1] 600000现在反转并将较大的集合应用于较小的集合:
system.time({
test_two <<- rbind.pages(parallel::mclapply(rand_addy_two, function(i) {
calc <- as.data.frame(drop(attr(adist(i, rand_addy_one, counts = TRUE), "counts")))
calc$totals <- (rowSums(calc))
calc %>% mutate(src = i, target = rand_addy_one) %>%
filter(totals == min(totals))
}, mc.cores = parallel::detectCores() - 2)) %>%
select(`source Address2` = src, `target Address1(matched)` = target,
insertions = ins, deletions = del, substitutions = sub,
total_approx_dist = totals)
})
user system elapsed
27.512 1.280 4.077
nrow(test_two)
[1] 720000https://stackoverflow.com/questions/42486172
复制相似问题