我有两个 Dataframe ,对于 Dataframe 1中的每个特定行,我试图根据定义的重要标准(偏移、年龄、级别)从 Dataframe 2中找到最接近的匹配。举个例子,假设我有 Dataframe 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
对于该 Dataframe 的每一行,我想在 Dataframe 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
你能建议我该如何处理这件事吗?有没有什么库可以让这个任务更容易完成?
1条答案
按热度按时间woobm2wo1#
您需要一个“非等”或“范围”联接。这在R的
fuzzyjoin
和data.table
包中实现。由于SQL也支持它,因此也可以使用sqldf
。遗憾的是,
dplyr
本机不支持此功能。由于SQL支持此操作,因此如果您的数据位于数据库中,则dbplyr
将允许它使用其sql_on
,但不是原生的。dplyr
及其最近添加的join_by
。首先,我们需要添加20%的公差:
模糊连接
data.table
这个包倾向于根据右边的名称重命名左边的(
DT_1
)连接,这可能会让人感到沮丧。为此,您需要在之后进行一些清理。sqldf
dplyr
如果您了解SQL,那么最后一个可能是最直观和最容易吸收的。但是请记住,对于较大的帧,它会将整个帧复制到内存存储SQLite示例中。这不是“免费的”。
fuzzyjoin
实现给了您很大的权力,它的参数似乎(对我来说)很容易遵循。结果正如我所期望的那样命名。然而,它是三种实现中最慢的(使用此数据)。(只有当您的真实的数据“非常”大时,才应该关注这一点。)如果你还不知道
data.table
,尽管它的速度极快,但它的R方言对不知情的人来说可能有点模糊。我相信它和fuzzyjoin
一样强大,尽管我还没有测试所有的极端情况,看看一个是否支持另一个不支持的东西。