从数据场%2中的数据帧%1查找紧密匹配 [英] finding close match from data frame 1 in data fame 2
本文介绍了从数据场%2中的数据帧%1查找紧密匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
shift_1 <- c(1,1,0,2)
length_1 <- c(100,120,5,70)
level_1<- c(1,3,5,4)
age_1 <- c(4.5,3.2,3,2.5)
df_1 <- data.frame(shift_1,level_1,age_1,length_1)
shift_1 level_1 age_1 length_1
1 1 1 4.5 100
2 1 3 3.2 120
3 0 5 3.0 5
4 2 4 2.5 70
和i对于此数据框的每一行,我希望在数据框2中找到最接近的匹配项,如下所示:
shift_2 <- c(1,1,2,1,0)
length_2 <- c(100,200,40,180,10)
level_2<- c(3,4,4,3,5)
age_2 <- c(2.5,5.5,2.2,3.1,5)
df_2 <- data.frame(shift_2,level_2,age_2,length_2)
shift_2 level_2 age_2 length_2
1 1 3 2.5 100
2 1 4 5.5 200
3 2 4 2.2 40
4 1 3 3.1 180
5 0 5 5.0 10
基于这些标准: Shift必须完全匹配。级别必须完全匹配。年龄将被接受,但有20%的差异。
如果找到匹配项:我们希望添加匹配行的索引号和匹配信息,否则将放入NA。所以预期的结果是这样的:
shift_r level_r age_r length_r index shift_match level_match age_match length_match
1 1 1 4.5 100 NA NA NA NA NA
2 1 3 3.2 120 4 1 3 3.1 180
3 0 5 3.0 5 NA NA NA NA NA
4 2 4 2.5 70 3 2 4 2.2 40
您能告诉我应该如何处理这件事吗?是否有库可以简化此任务?
推荐答案
您需要一个非等项(&QOOT;NON-QUI&QOOT;)或范围(&QOOT;RANGE&QOOT;JOIN)。这在R的fuzzyjoin
和data.table
包中实现,因为SQL也支持它,所以也可以使用sqldf
。
dplyr
本身不支持此功能。由于SQL支持此操作,因此如果您的数据位于数据库中,则dbplyr
将允许它使用其sql_on
,但不是本机使用。
首先,我们需要添加20%的容差:
df_1$age_1_start <- df_1$age_1 * 0.8
df_1$age_1_end <- df_1$age_1 * 1.2
df_1
# shift_1 level_1 age_1 length_1 age_1_start age_1_end
# 1 1 1 4.5 100 3.60 5.40
# 2 1 3 3.2 120 2.56 3.84
# 3 0 5 3.0 5 2.40 3.60
# 4 2 4 2.5 70 2.00 3.00
模糊联接
fuzzyjoin::fuzzy_left_join(
df_1, df_2,
by = c("shift_1" = "shift_2", "level_1" = "level_2",
"age_1_start" = "age_2", "age_1_end" = "age_2"),
match_fun = list(`==`, `==`, `<=`, `>=`))
# shift_1 level_1 age_1 length_1 age_1_start age_1_end shift_2 level_2 age_2 length_2
# 1 1 1 4.5 100 3.60 5.40 NA NA NA NA
# 2 1 3 3.2 120 2.56 3.84 1 3 3.1 180
# 3 0 5 3.0 5 2.40 3.60 NA NA NA NA
# 4 2 4 2.5 70 2.00 3.00 2 4 2.2 40
data.table
library(data.table)
DT_1 <- as.data.table(df_1) # must include age_1_start and age_1_end from above
DT_2 <- as.data.table(df_2)
DT_2[DT_1, on = .(shift_2 == shift_1, level_2 == level_1, age_2 >= age_1_start, age_2 <= age_1_end)]
# shift_2 level_2 age_2 length_2 age_2.1 age_1 length_1
# 1: 1 1 3.60 NA 5.40 4.5 100
# 2: 1 3 2.56 180 3.84 3.2 120
# 3: 0 5 2.40 NA 3.60 3.0 5
# 4: 2 4 2.00 40 3.00 2.5 70
此程序包倾向于根据右侧的名称重命名左侧(DT_1
)联接,这可能会令人沮丧。为此,您需要在之后进行一些清理。
sqldf
sqldf::sqldf(
"select t1.*, t2.*
from df_1 t1
left join df_2 t2 on t1.shift_1 = t2.shift_2 and t1.level_1 = t2.level_2
and t1.age_1_start <= t2.age_2 and t1.age_1_end >= t2.age_2")
# shift_1 level_1 age_1 length_1 age_1_start age_1_end shift_2 level_2 age_2 length_2
# 1 1 1 4.5 100 3.60 5.40 NA NA NA NA
# 2 1 3 3.2 120 2.56 3.84 1 3 3.1 180
# 3 0 5 3.0 5 2.40 3.60 NA NA NA NA
# 4 2 4 2.5 70 2.00 3.00 2 4 2.2 40
如果您了解SQL,那么最后一个可能是最直观、最容易理解的。不过请记住,对于较大的帧,它会将整个帧复制到内存存储的SQLite实例中……它不是免费的&q;。
fuzzyjoin
实现为您提供了强大的功能,它的论点似乎(在我看来)很容易理解。结果的命名与我预期的一样。但是,它是三个实现中最慢的(使用此数据)。(只有当您的实际数据非常大时,才应考虑此问题。)
如果您还不知道data.table
,尽管它的速度很快,但对于不知情的人来说,它的R方言可能有点晦涩难懂。我相信它和fuzzyjoin
一样强大,不过我还没有测试所有的角盒,看看其中一个是否支持另一个不支持的东西。
bench::mark(
fuzzyjoin = fuzzyjoin::fuzzy_left_join(
df_1, df_2,
by = c("shift_1" = "shift_2", "level_1" = "level_2",
"age_1_start" = "age_2", "age_1_end" = "age_2"),
match_fun = list(`==`, `==`, `<=`, `>=`)),
data.table = DT_2[DT_1, on = .(shift_2 == shift_1, level_2 == level_1, age_2 >= age_1_start, age_2 <= age_1_end)],
sqldf = sqldf::sqldf(
"select t1.*, t2.*
from df_1 t1
left join df_2 t2 on t1.shift_1 = t2.shift_2 and t1.level_1 = t2.level_2
and t1.age_1_start <= t2.age_2 and t1.age_1_end >= t2.age_2"),
check = FALSE
)
# # A tibble: 3 x 13
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result memory time gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list> <list> <list> <list>
# 1 fuzzyjoin 134.12ms 143.24ms 6.98 107KB 6.98 2 2 286ms <NULL> <Rprofmem[,3~ <bch:tm ~ <tibble ~
# 2 data.table 2.14ms 2.63ms 335. 114KB 2.06 163 1 487ms <NULL> <Rprofmem[,3~ <bch:tm ~ <tibble ~
# 3 sqldf 21.14ms 22.72ms 42.9 184KB 4.52 19 2 442ms <NULL> <Rprofmem[,3~ <bch:tm ~ <tibble ~
这篇关于从数据场%2中的数据帧%1查找紧密匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文