两个数据库的模糊和精确匹配
fuzzy and exact match of two databases
我有两个数据库。第一个有大约 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,每个 480G 内存并使用 mclapply
和选项 mc.cores=3
,也会发生同样的错误。也许 foreach
命令会有所帮助,但我不知道如何实现它。
有人建议我使用 purrr
和 repurrrsive
包,所以我尝试以下操作:
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 分钟,但仍然没有结果。
我以前没有用过 foreach,但也许变量 x 已经是 zz1 的各个行了?
你试过了吗:
stringdist_inner_join(x, zz2, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance")
?
如果您将 uniquegrantees 数据框拆分(使用 base::split
或 dplyr::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
)以再次在同一数据框中获取所有结果。
见
我有两个数据库。第一个有大约 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,每个 480G 内存并使用 mclapply
和选项 mc.cores=3
,也会发生同样的错误。也许 foreach
命令会有所帮助,但我不知道如何实现它。
有人建议我使用 purrr
和 repurrrsive
包,所以我尝试以下操作:
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 分钟,但仍然没有结果。
我以前没有用过 foreach,但也许变量 x 已经是 zz1 的各个行了?
你试过了吗:
stringdist_inner_join(x, zz2, by="grantee_name", method="jw", p=0.1, max_dist=0.1, distance_col="distance")
?
如果您将 uniquegrantees 数据框拆分(使用 base::split
或 dplyr::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
)以再次在同一数据框中获取所有结果。
见