"fuzzy" inner_join 在 dplyr 中保留完全匹配和不完全匹配的两行
"fuzzy" inner_join in dplyr to keep both rows that do AND not exactly match
我正在处理两个我想加入的数据集,而不是基于它们之间的 精确 匹配,而是近似匹配。我的问题与此类似 OP.
以下是我的两个数据框的示例。
df1
是这个:
x
4.8
12
4
3.5
12.5
18
df2
是这个:
x y
4.8 6.6
12 1
4.5 1
3.5 0.5
13 1.8
15 2
我目前正在使用 inner_join(df1, df2, by=c("x")
将两者连接在一起。
这给了我:
x y
4.8 6.6
12 1
3.5 0.5
但是,我真正想做的是根据这些条件加入两个 df
:
- 首先加入任何完全匹配(与
inner_join()
目前的工作方式完全一样)
- 但是,如果没有完全匹配,则加入任何匹配 ± 0.5
我试图获得的输出类型如下所示:
x y
4.8 6.6
12 1
4 1 #the y value is from x=4.5 in df1
4 0.5 #the y value is from x=3.5 in df1
3.5 0.5
12.5 1 #the y value is from x=12 in df1
12.5 1.8 #the y value is from x=13 in df1
我通常在 dplyr
工作,因此 dplyr
解决方案将不胜感激。但是,我也愿意接受其他建议,因为我不知道 dplyr
是否足够灵活以进行“模糊”连接。
(我知道 fuzzyjoin
包,但它似乎并没有完全理解我在这里尝试做的事情)
一个可能的解决方案,没有join
:
library(tidyverse)
df1 %>%
rename(x1 = x) %>%
crossing(df2) %>%
mutate(diff = abs(x1-x)) %>%
filter(diff <= 0.5) %>%
group_by(x1) %>%
mutate(aux = any(diff == 0)) %>%
filter(aux*(diff == 0) | !aux) %>%
select(-diff, -aux) %>%
ungroup
#> # A tibble: 7 × 3
#> x1 x y
#> <dbl> <dbl> <dbl>
#> 1 3.5 3.5 0.5
#> 2 4 3.5 0.5
#> 3 4 4.5 1
#> 4 4.8 4.8 6.6
#> 5 12 12 1
#> 6 12.5 12 1
#> 7 12.5 13 1.8
您可以使用{powerjoin}
library(powerjoin)
power_left_join(
df1, df2,
by = ~ .x$x == .y$x | ! .x$x %in% .y$x & .x$x <= .y$x +.5 & .x$x >= .y$x -.5,
keep = "left")
#> x y
#> 1 4.8 6.6
#> 2 12.0 1.0
#> 3 4.0 1.0
#> 4 4.0 0.5
#> 5 3.5 0.5
#> 6 12.5 1.0
#> 7 12.5 1.8
由 reprex package (v2.0.1)
于 2022-04-14 创建
我正在处理两个我想加入的数据集,而不是基于它们之间的 精确 匹配,而是近似匹配。我的问题与此类似 OP.
以下是我的两个数据框的示例。
df1
是这个:
x
4.8
12
4
3.5
12.5
18
df2
是这个:
x y
4.8 6.6
12 1
4.5 1
3.5 0.5
13 1.8
15 2
我目前正在使用 inner_join(df1, df2, by=c("x")
将两者连接在一起。
这给了我:
x y
4.8 6.6
12 1
3.5 0.5
但是,我真正想做的是根据这些条件加入两个 df
:
- 首先加入任何完全匹配(与
inner_join()
目前的工作方式完全一样) - 但是,如果没有完全匹配,则加入任何匹配 ± 0.5
我试图获得的输出类型如下所示:
x y
4.8 6.6
12 1
4 1 #the y value is from x=4.5 in df1
4 0.5 #the y value is from x=3.5 in df1
3.5 0.5
12.5 1 #the y value is from x=12 in df1
12.5 1.8 #the y value is from x=13 in df1
我通常在 dplyr
工作,因此 dplyr
解决方案将不胜感激。但是,我也愿意接受其他建议,因为我不知道 dplyr
是否足够灵活以进行“模糊”连接。
(我知道 fuzzyjoin
包,但它似乎并没有完全理解我在这里尝试做的事情)
一个可能的解决方案,没有join
:
library(tidyverse)
df1 %>%
rename(x1 = x) %>%
crossing(df2) %>%
mutate(diff = abs(x1-x)) %>%
filter(diff <= 0.5) %>%
group_by(x1) %>%
mutate(aux = any(diff == 0)) %>%
filter(aux*(diff == 0) | !aux) %>%
select(-diff, -aux) %>%
ungroup
#> # A tibble: 7 × 3
#> x1 x y
#> <dbl> <dbl> <dbl>
#> 1 3.5 3.5 0.5
#> 2 4 3.5 0.5
#> 3 4 4.5 1
#> 4 4.8 4.8 6.6
#> 5 12 12 1
#> 6 12.5 12 1
#> 7 12.5 13 1.8
您可以使用{powerjoin}
library(powerjoin)
power_left_join(
df1, df2,
by = ~ .x$x == .y$x | ! .x$x %in% .y$x & .x$x <= .y$x +.5 & .x$x >= .y$x -.5,
keep = "left")
#> x y
#> 1 4.8 6.6
#> 2 12.0 1.0
#> 3 4.0 1.0
#> 4 4.0 0.5
#> 5 3.5 0.5
#> 6 12.5 1.0
#> 7 12.5 1.8
由 reprex package (v2.0.1)
于 2022-04-14 创建