【问题标题】:fuzzy and exact match of two databases两个数据库的模糊匹配和精确匹配
【发布时间】:2021-01-26 23:12:22
【问题描述】:

我有两个数据库。第一个有大约 70k 行和 3 列。第二个有 790k 行 2 列。两个数据库都有一个公共变量grantee_name。我想根据grantee_name 将第一个数据库的每一行与第二个数据库的一个或多个行进行匹配。请注意,merge 将不起作用,因为 grantee_name 不完全匹配。有不同的拼写等。所以,我正在使用fuzzyjoin 包并尝试以下操作:

library("haven"); library("fuzzyjoin"); library("dplyr")
forfuzzy<-read_dta("/path/forfuzzy.dta")
filings <- read_dta ("/path/filings.dta")
> head(forfuzzy)
# A tibble: 6 x 3
  grantee_name                 grantee_city grantee_state
  <chr>                        <chr>        <chr>        
1 (ICS)2 MAINE CHAPTER         CLEARWATER   FL           
2 (SUFFOLK COUNTY) VANDERBILT~ CENTERPORT   NY           
3 1 VOICE TREKKING A FUND OF ~ WESTMINSTER  MD           
4 10 CAN                       NEWBERRY     FL           
5 10 THOUSAND WINDOWS          LIVERMORE    CA           
6 100 BLACK MEN IN CHICAGO INC CHICAGO      IL   
... 7 - 70000 rows to go

> head(filings)
# A tibble: 6 x 2
  grantee_name                       ein 
  <chr>                             <dbl>               
1 ICS-2 MAINE CHAPTER              123456             
2 SUFFOLK COUNTY VANDERBILT        654321            
3 VOICE TREKKING A FUND OF VOICES  789456            
4 10 CAN                           654987               
5 10 THOUSAND MUSKETEERS INC       789123               
6 100 BLACK MEN IN HOUSTON INC     987321      

rows 7-790000 omitted for brevity

上面的例子很清楚,可以提供一些好的匹配和一些不太好的匹配。请注意,例如,10 THOUSAND WINDOWS 将与 10 THOUSAND MUSKETEERS INC 匹配得最好,但这并不意味着它是一个很好的匹配。 filings 数据中的某处会有更好的匹配(上面未显示)。在这个阶段这无关紧要。

所以,我尝试了以下方法:

df<-as.data.frame(stringdist_inner_join(forfuzzy, filings, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance"))

对 R 来说是全新的。这会导致错误: cannot allocate vector of size 375GB(当然是大数据库)。来自forfuzzy 的 100 行样本始终有效。因此,我想到了一次迭代 100 行的列表。

我尝试了以下方法:

n=100
lst = split(forfuzzy, cumsum((1:nrow(forfuzzy)-1)%%n==0))

df<-as.data.frame(lapply(lst, function(df_)
{
(stringdist_inner_join(df_, filings, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance", nthread = getOption("sd_num_thread")))
}
)%>% bind_rows)

我也尝试过使用mclapply 而不是lapply 进行上述操作。即使我尝试了设置 3 个 CPU 的高性能集群,每个 CPU 有 480G 内存并使用 mclapply 和选项 mc.cores=3,也会发生同样的错误。也许foreach 命令会有所帮助,但我不知道如何实现它。

有人建议我使用 purrrrepurrrsive 包,所以我尝试以下方法:

purrr::map(lst, ~stringdist_inner_join(., filings, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance", nthread = getOption("sd_num_thread")))

by=grantee_name 语句中出现新手错误之后,这似乎有效。但是,它需要很长时间,我不确定它是否会起作用。 forfuzzy 中的 100 行示例列表,n=10(因此 10 个列表,每个列表 10 行)已经运行了 50 分钟,仍然没有结果。

【问题讨论】:

    标签: r purrr parallel.foreach fuzzyjoin furrr


    【解决方案1】:

    我之前没有使用过foreach,但也许变量x已经是zz1的各个行?

    你试过了吗:

    stringdist_inner_join(x, zz2, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance")

    ?

    【讨论】:

    • 谢谢 Arthur 我试过了。错误消息Error in as.data.frame(x) : object 'x' not found
    • 我可以使用 lapply 或 mclapply 吗?如果是这样,我将如何更改上述内容?抱歉:这里是 R 新手。
    • 看起来你想返回(as.data.frame(整个数据框,而不是单个"x"))
    • mclapply 可以提供帮助,但我不熟悉它。
    • 查看我使用地图的其他答案(基本上是 lapply)
    【解决方案2】:

    如果您将 uniquegrantees 数据框拆分(使用 base::splitdplyr::group_split)为数据框列表,则可以在列表中调用 purrr::map。 (map 几乎是lapply

    purrr::map(list_of_dfs, ~stringdist_inner_join(., filings, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance"))

    您的结果将是一个数据框列表,每个数据框都与文件模糊连接。然后您可以调用bind_rows(或者您可以调用map_dfr)再次在同一数据框中获取所有结果。

    R - Splitting a large dataframe into several smaller dateframes, performing fuzzyjoin on each one and outputting to a single dataframe

    【讨论】:

    • 很难判断你的错误来自哪里。请创建一个可重现的示例并编辑您的问题。您可以使用 head() 和 dput() 提供数据样本
    • 尽量减少数据(匹配一行,列表中有 2 个数据框),看看会发生什么
    • 无法让它更快地工作。在 HPC 系统上,我收到错误“尚不支持大型向量...”。也就是说,除非速度很慢,否则它可以工作。非常感谢。
    • 您也可以尝试调整 max_dist 和 p 参数以将结果限制为“良好匹配”或使用 method="jw"。此页面解释了可能的不同方法:rdocumentation.org/packages/stringdist/versions/0.9.4.6/topics/…
    • 确实支持亚瑟,但我需要更高的代表才能让它发挥作用。该代码在 Windows 上运行(但非常挑剔),但不在 HPC 集群上。 stackoverflow.com/questions/64549055/…
    猜你喜欢
    • 2018-06-09
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多