有条件地匹配两个大型数据集的多列中的元素

Posted

技术标签:

【中文标题】有条件地匹配两个大型数据集的多列中的元素【英文标题】:Conditionally matching elements in multiple columns of two large datasets with each other 【发布时间】:2014-04-01 06:49:40 【问题描述】:

我有两个非常大的产品需求和退货数据集(每个数据集大约有 400 万个条目,但长度不等)。第一个数据集给出 [1] 需求日期,[2] 客户 ID 和 [3] 产品 ID。第二个数据集给出 [1] 退货日期,[2] 客户 ID 和 [3] 产品 ID。

现在我想将给定客户和产品的所有需求与相同客户和产品的回报相匹配。成对的产品类型和客户并不是唯一的,因为客户可以多次要求一个产品。因此,我想匹配数据集中最早回报的产品需求。也可能发生某些产品没有退回,或者退回了一些没有被要求的产品(因为客户退回了在数据集中的起始数据之前要求的项目)。

为此,我编写了以下代码:

transactionNumber = 1:nrow(demandSet)  #transaction numbers for the demandSet
matchedNumber = rep(0, nrow(demandSet)) #vector of which values in the returnSet correspond to the transactions in the demandSet

for (transaction in transactionNumber)
indices <- which(returnSet[,2]==demandSet[transaction,2]&returnSet[,3]==demandSet[transaction,3]) 
if (length(indices)>0)
    matchedNumber[transaction] <- indices[which.min(returnSet[indices,][,1])] #Select the index of the transaction with the minimum date
 
 

但是,这需要大约一天的时间来计算。有人有更好的建议吗?请注意,match two columns with two other columns 的建议在这里不起作用,因为 match() 会溢出内存。

作为一个工作示例考虑

demandDates = c(1,1,1,5,6,6,8,8)
demandCustIds = c(1,1,1,2,3,3,1,1)
demandProdIds = c(1,2,3,4,1,5,2,6)
demandSet = data.frame(demandDates,demandCustIds,demandProdIds)

returnDates = c(1,1,4,4,4)
returnCustIds = c(4,4,1,1,1)
returnProdIds = c(5,7,1,2,3)
returnSet = data.frame(returnDates,returnCustIds,returnProdIds)

(这实际上不能完全正确地工作,因为事务 7 与返回 4 不正确匹配,但是为了这个问题,让我们假设这是我想要的......我可以稍后解决这个问题)

【问题讨论】:

你看过data.table吗? 以前没听说过,现在去研究一下! 如果你更喜欢 SQL 风格,也可以查看sqldf。 @asb Data.table 导致稍微提速,但是上面代码的等效实现还是很慢。 我猜你足够小心使用setkey 并使用 A[B] 语法? 【参考方案1】:
require(data.table)

DD<-data.table(demandSet,key="demandCustIds,demandProdIds")
DR<-data.table(returnSet,key="returnCustIds,returnProdIds")
DD[DR,mult="first"]   

   demandCustIds demandProdIds demandDates returnDates
1:             1             1           1           4
2:             1             2           1           4
3:             1             3           1           4
4:             4             5          NA           1
5:             4             7          NA           1

【讨论】:

哇,太棒了!您还可以在这里添加额外的条件吗? IE。将需求与具有较大日期而不是数据集中第一个日期的“第一个”回报相匹配? 确定——试试DD[DR][returnDates&gt;demandDates,mult="first"] DD[DR][returnDates&gt;demandDates,.SD[1],by=c("demandCustIds","demandProdIds")] 最后一个问题:如果两个数据集中的日期都有列名“日期”怎么办? DD[DR][DR[,Date]&gt;DD[,Date],mult="first"] 给出的结果与 DD[DR][returnDates&gt;demandDates,mult="first"] 不同 你会发现在结果data.table中,合并后,第二个Date列将别名为Date.1,所以你可以直接使用Date.1>Date

以上是关于有条件地匹配两个大型数据集的多列中的元素的主要内容,如果未能解决你的问题,请参考以下文章

带有大型数据集的 SQL 插入

从大型数据集的数据框有效地创建矩阵

如何有效地找到两个列表中匹配元素的索引

基于条件的 2 个大型数据集上的模糊模糊字符串匹配 - python

在 Pandas 中加入两个大型数据集的最佳方法

具有大型数据集的 SQL Server 中的数据透视表