将参数传递给 R fuzzyjoin::fuzzy_join 中的多个 match_fun 函数
Passing arguments into multiple match_fun functions in R fuzzyjoin::fuzzy_join
我正在回答这些 questions 并得到了一个合适的解决方案,但是我在使用 fuzzy_join
将参数传递到我从 fuzzyjoin::stringdist_join
中提取的 match_fun 时遇到了问题。在这种情况下,我混合使用了多个 match_fun,包括这个自定义的 match_fun_stringdist
以及 ==
和 <=
用于精确匹配和标准匹配。
我收到的错误消息是:
# Error in mf(rep(u_x, n_y), rep(u_y, each = n_x), ...): object 'ignore_case' not found
# Data:
library(data.table, quietly = TRUE)
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")
AREACODE <- c('10','10','14','20','30')
Year1 <- c(2001:2005)
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","abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR")
Year2 <- c(2001:2010)
AREA_CODE <- c('10','10','10','20','30','40','50','61','64', '99')
data1 <- data.table(Address1, Year1, AREACODE)
data2 <- data.table(Address2, Year2, AREA_CODE)
data2[, unique_id := sprintf("%06d", 1:nrow(data2))]
# Solution:
library(fuzzyjoin, quietly = TRUE); library(dplyr, quietly = TRUE)
# First, need to define match_fun_stringdist
# Code from stringdist_join from https://github.com/dgrtwo/fuzzyjoin/blob/master/R/stringdist_join.R
match_fun_stringdist <- function(v1, v2, ...) {
if (ignore_case) {
v1 <- stringr::str_to_lower(v1)
v2 <- stringr::str_to_lower(v2)
}
dists <- stringdist::stringdist(v1, v2, method = method, ...)
ret <- dplyr::data_frame(include = (dists <= max_dist))
if (!is.null(distance_col)) {
ret[[distance_col]] <- dists
}
ret
}
# Call fuzzy_join
fuzzy_join(data1, data2,
by = list(x = c("Address1", "AREACODE", "Year1"), y = c("Address2", "AREA_CODE", "Year2")),
match_fun = list(match_fun_stringdist, `==`, `<=`),
mode = "left",
ignore_case = FALSE,
method = "dl",
max_dist = 99,
distance_col = "dist"
) %>%
group_by(Address1, Year1, AREACODE) %>%
top_n(1, -Address1.dist) %>%
top_n(1, Year2) %>%
select(unique_id, Address1.dist, everything())
#> Error in mf(rep(u_x, n_y), rep(u_y, each = n_x), ...): object 'ignore_case' not found
我认为这个错误是因为传递给每个 match_fun 的参数搞砸了,即不能传递像 ignore_case
这样的额外参数,最初只用于 string_distmatch_fun,变成match_fun的>=
解决方案是定义我自己的 match_fun,并为参数设置固定参数。请参阅下面我用固定参数定义自己的 match_fun_stringdist 的地方。我也在另一个 question/answer 中实现了它。
# First, need to define match_fun_stringdist
# Code from stringdist_join from https://github.com/dgrtwo/fuzzyjoin
match_fun_stringdist <- function(v1, v2) {
# Can't pass these parameters in from fuzzy_join because of multiple incompatible match_funs, so I set them here.
ignore_case = FALSE
method = "dl"
max_dist = 99
distance_col = "dist"
if (ignore_case) {
v1 <- stringr::str_to_lower(v1)
v2 <- stringr::str_to_lower(v2)
}
# shortcut for Levenshtein-like methods: if the difference in
# string length is greater than the maximum string distance, the
# edit distance must be at least that large
# length is much faster to compute than string distance
if (method %in% c("osa", "lv", "dl")) {
length_diff <- abs(stringr::str_length(v1) - stringr::str_length(v2))
include <- length_diff <= max_dist
dists <- rep(NA, length(v1))
dists[include] <- stringdist::stringdist(v1[include], v2[include], method = method)
} else {
# have to compute them all
dists <- stringdist::stringdist(v1, v2, method = method)
}
ret <- dplyr::data_frame(include = (dists <= max_dist))
if (!is.null(distance_col)) {
ret[[distance_col]] <- dists
}
ret
}
并调用 fuzzy_join
fuzzy_join(data1, data2,
by = list(x = c("Address1", "AREACODE", "Year1"), y = c("Address2", "AREA_CODE", "Year2")),
match_fun = list(match_fun_stringdist, `==`, `<=`),
mode = "left")
我正在回答这些 fuzzy_join
将参数传递到我从 fuzzyjoin::stringdist_join
中提取的 match_fun 时遇到了问题。在这种情况下,我混合使用了多个 match_fun,包括这个自定义的 match_fun_stringdist
以及 ==
和 <=
用于精确匹配和标准匹配。
我收到的错误消息是:
# Error in mf(rep(u_x, n_y), rep(u_y, each = n_x), ...): object 'ignore_case' not found
# Data:
library(data.table, quietly = TRUE)
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")
AREACODE <- c('10','10','14','20','30')
Year1 <- c(2001:2005)
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","abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR")
Year2 <- c(2001:2010)
AREA_CODE <- c('10','10','10','20','30','40','50','61','64', '99')
data1 <- data.table(Address1, Year1, AREACODE)
data2 <- data.table(Address2, Year2, AREA_CODE)
data2[, unique_id := sprintf("%06d", 1:nrow(data2))]
# Solution:
library(fuzzyjoin, quietly = TRUE); library(dplyr, quietly = TRUE)
# First, need to define match_fun_stringdist
# Code from stringdist_join from https://github.com/dgrtwo/fuzzyjoin/blob/master/R/stringdist_join.R
match_fun_stringdist <- function(v1, v2, ...) {
if (ignore_case) {
v1 <- stringr::str_to_lower(v1)
v2 <- stringr::str_to_lower(v2)
}
dists <- stringdist::stringdist(v1, v2, method = method, ...)
ret <- dplyr::data_frame(include = (dists <= max_dist))
if (!is.null(distance_col)) {
ret[[distance_col]] <- dists
}
ret
}
# Call fuzzy_join
fuzzy_join(data1, data2,
by = list(x = c("Address1", "AREACODE", "Year1"), y = c("Address2", "AREA_CODE", "Year2")),
match_fun = list(match_fun_stringdist, `==`, `<=`),
mode = "left",
ignore_case = FALSE,
method = "dl",
max_dist = 99,
distance_col = "dist"
) %>%
group_by(Address1, Year1, AREACODE) %>%
top_n(1, -Address1.dist) %>%
top_n(1, Year2) %>%
select(unique_id, Address1.dist, everything())
#> Error in mf(rep(u_x, n_y), rep(u_y, each = n_x), ...): object 'ignore_case' not found
我认为这个错误是因为传递给每个 match_fun 的参数搞砸了,即不能传递像 ignore_case
这样的额外参数,最初只用于 string_distmatch_fun,变成match_fun的>=
解决方案是定义我自己的 match_fun,并为参数设置固定参数。请参阅下面我用固定参数定义自己的 match_fun_stringdist 的地方。我也在另一个 question/answer 中实现了它。
# First, need to define match_fun_stringdist
# Code from stringdist_join from https://github.com/dgrtwo/fuzzyjoin
match_fun_stringdist <- function(v1, v2) {
# Can't pass these parameters in from fuzzy_join because of multiple incompatible match_funs, so I set them here.
ignore_case = FALSE
method = "dl"
max_dist = 99
distance_col = "dist"
if (ignore_case) {
v1 <- stringr::str_to_lower(v1)
v2 <- stringr::str_to_lower(v2)
}
# shortcut for Levenshtein-like methods: if the difference in
# string length is greater than the maximum string distance, the
# edit distance must be at least that large
# length is much faster to compute than string distance
if (method %in% c("osa", "lv", "dl")) {
length_diff <- abs(stringr::str_length(v1) - stringr::str_length(v2))
include <- length_diff <= max_dist
dists <- rep(NA, length(v1))
dists[include] <- stringdist::stringdist(v1[include], v2[include], method = method)
} else {
# have to compute them all
dists <- stringdist::stringdist(v1, v2, method = method)
}
ret <- dplyr::data_frame(include = (dists <= max_dist))
if (!is.null(distance_col)) {
ret[[distance_col]] <- dists
}
ret
}
并调用 fuzzy_join
fuzzy_join(data1, data2,
by = list(x = c("Address1", "AREACODE", "Year1"), y = c("Address2", "AREA_CODE", "Year2")),
match_fun = list(match_fun_stringdist, `==`, `<=`),
mode = "left")