[英]Match data from two different data frames in R like Excel VLOOKUP
[英]R: Match values in two data frames like vlookup but for multiple criteria without Key [large data]
我有兩個來自兩個單獨來源的大型數據框(500k行),沒有密鑰。 與其能夠使用鍵進行合並,不如通過匹配其他列來合並兩個數據框。 如年齡和數量。 這不是兩個數據幀之間的完美匹配,因此某些值將不匹配,我稍后將簡單地刪除這些值。
數據可能看起來像這樣。
因此,在上面的示例中,我希望能夠創建一個與鍵1和鍵2匹配的表。在上圖中,我們看到XXX1和YYY3是匹配項。 所以從這里我想創建一個像這樣的數據框:
[鍵1] [鍵2]
XXX1 YYY3
XXX2不適用
XXX3不適用
我知道如何在Excel中執行此操作,但是由於大量數據,它只會崩潰。 我想專注於R,但是對於它的價值,這是我在Excel中構建它的方式(其思想是我們首先執行VLOOKUP,然后使用INDEX作為VLOOKUP來獲得第二個匹配項,如果第一個匹配的話)不符合這兩個條件):
=IF(P2=0;IFNA(VLOOKUP(L2;B:C;2;FALSE);VLOOKUP(L2;G:H;2;FALSE));IF(O2=Q2;INDEX($A$2:$A$378300;SMALL(IF($L2=$B$2:$B378300;ROW($B$2:$B$378300)-ROW($B$2)+1);2));0))
這是R中的方法:
for (i in 1:nrow(df)) {
for (j in 1:nrow(df)) {
if (df_1$pc_age[i] == df_2$pp_age[j] && (df_1$amount[i] %in% c(df_2$amount1[j], df_2$amount2[j], df_2$amount3[j]))) {
df_1$Key1[i] = df_2$Key2[j]
} else (df_1$Key1[i] = N/A)
}}
問題是這需要很長的路要走。 有沒有更有效的方法來盡可能更好地映射此數據?
謝謝!
在兩個數據框中創建虛擬列,例如(我可以為df1展示):
for(i in 1:nrow(df1)){
df1$key1 <- paste0("X_",i)
}
同樣,對於Y1 .... Yn中的df2,然后使用“合並”列年齡和金額對兩個數據框進行合並。 將Key1和key2連接到合並數據框中的新列中。 您將直接獲得所需的數據框。
以下代碼可以為您工作嗎?
# create random data
set.seed(123)
df1 <- data.frame(
key_1=as.factor(paste("xxx",1:100,sep="_")),
age = sample(1:100,100,replace=TRUE),
amount = sample(1:200,100))
df2 <- data.frame(
key_1=paste("yyy",1:500,sep="_"),
age = sample(1:100,500,replace=TRUE),
amount_1 = sample(1:200,500,replace=TRUE),
amount_2 = sample(1:200,500,replace=TRUE),
amount_3 = sample(1:200,500,replace=TRUE))
# ensure at least three fit rows
df2[10,2:3] <- df1[1,2:3]
df2[20,c(2,4)] <- df1[2,2:3]
df2[30,c(2,5)] <- df1[3,2:3]
# define comparrison with df2
comp2df2 <- function(x){
ageComp <- df2$age == as.numeric(x[2])
if(!any(ageComp)){
return(NaN)
}
amountComp <- apply(df2,1,function(a) as.numeric(x[3]) %in% as.numeric(a[3:5]))
if(!any(amountComp)){
return(NaN)
}
matchIdx <- ageComp & amountComp
if(sum(matchIdx) > 1){
warning("multible match detected first match is taken\n")
}
return(which(matchIdx)[1])
}
# run match
matchIdx <- apply(df1,1,comp2df2)
# merge
df_new <- cbind(df1[!is.na(matchIdx),],df2[matchIdx[!is.na(matchIdx)],])
沒時間對真正的大數據進行測試,但是我想這應該比您的兩個for循環要快。...要進一步加快處理速度,您可以刪除
if(sum(matchIdx) > 1){
warning("multible match detected first match is taken\n")
}
如果您不擔心一行會與其他幾行相匹配,則可以使用這些行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.