2017-07-11 304 views
2

我需要在R中執行順序合併,我的意思是讓我們說我有兩個數據集:訂單和交付。如何在R中基於多個列在兩個相同的數據集中進行順序合併

我想匹配這些訂單和交付在一起,但我首先想要基於地址列合併,然後對於不匹配的行,我想合併基於郵政編碼,然後對於這些行不匹配,我想基於經度和緯度進行合併,然後對於那些不匹配的行,我想合併其他屬性等等。

我可以很容易做到基於一個屬性,像這樣的合併:

merge1 <- merge(orders, deliveries, by.x = c("order_date", "address"), 
by.y = c("date", "delivery_address"), sort = FALSE) 

但現在我要投其所好未通過假設有兩個不同的郵政編碼merge1匹配的行兩列中的名稱(一個數據集中的「郵政編碼」和另一箇中的「郵政編碼」)。

我試着在訂單上做一個左連接,然後找到對於merge1的deliveries數據集中的某個列返回NA的行,然後嘗試使用該子集進行另一次合併,但一直未能成功完成。

merge1 <- merge(orders, deliveries, by.x = c("order_date", "address"), 
    by.y = c("date", "delivery_address"), all.x = TRUE, sort = FALSE) 

    merge2 <- merge(merge1[is.na(merge1$delivery_address),], deliveries, by.x = c("order_date", "zipcode"), 
by.y = c("date", "postcode"), all.x = TRUE, sort = FALSE) 

我知道這是完全錯誤的,因爲它只返回NA值,它重複列,但這是我的思路。

基本上,只需要一種方法來在兩個數據集之間進行R的順序合併,首先是一列,然後是另一列,依此類推。儘管我不想要左連接,但只有匹配行被返回的內連接,但是,我可以執行左連接,然後在所有合併後,只選擇沒有NA的行。所以我的最終結果應該是所有與交付相匹配的訂單,但只有那些相應匹配的訂單。

編輯:

人們問一些示例數據,所以這裏是一些:

orders <- data.frame(order = c(1,2,3,4,5,6,7,8,9,10), 
         address = c(1111, 1112, 1314, 1113, 1114, 1618, 1917, 1118, 1945, 2000), 
         zipcode = c(001, 002, 001, 999, 999, 006, 007, 007, 999, 010)) 

deliveries <- data.frame(length = c(4, 5, 9, 11, 13, 15, 93, 17, 4, 8, 12), 
         delivery_address = c(1111, 1112, 0111, 1113, 1114, 0000, 1618, 0001, 0002, 0405, 1121), 
         postcode = c(001, 912, 001, 910, 913, 006, 080, 007, 074, 088, 010)) 


merge1 <- merge(orders, deliveries, by.x = "address", by.y = "delivery_address", sort = FALSE) 

所以merge1正確給了我與交付是有相同的地址,現在怎麼匹配了訂單添加到merge1數據集並添加那些未與deliveryies數據集匹配的行,以便我可以通過郵編匹配它們,因爲仍然有一些訂單和郵遞可以通過郵政編碼匹配。

+2

請出示基於該 – akrun

+0

增加了一些示例數據 – Ic3MaN911

+0

你能顯示出與貼出的例子您想要的結果的小重複的例子,和預期的輸出? – Parfait

回答

1

這適用於您的數據。例如:

# functions used here use dplyr to process data 
library("dplyr") 

# using forward pipe syntax for readability of this example 
# though this isn't necessary for functions to work 
library("magrittr") 

# merge by exact matches between address and delivery_address 
# add column of delivery_address for binding later so dataframes match 
merge1 <- orders %>% 
    inner_join(y = deliveries, 
      by = c("address" = "delivery_address")) %>% 
    mutate(delivery_address = address) 

# extract unmerged columns from orders then merge exact matches by 
# zipcode to postcode. 
# add postcode column for binding 
merge2 <- orders %>% 
    anti_join(y = deliveries, 
      by = c("address" = "delivery_address")) %>% 
    inner_join(y = deliveries, 
      by = c("zipcode" = "postcode")) %>% 
    mutate(postcode = zipcode) 

# bind two sets of results together. 
results <- bind_rows(merge1, merge2) 
results 

我強烈建議RStudio cheat sheets on data transformation這樣的工作的

+0

謝謝,但這不會執行順序合併,它只是使用完全連接進行合併。順序連接/合併的目的在於,我的標準從嚴格到寬鬆,從只有合併到第一次沒有合併的行的行才放鬆。因此,即使在這個例子中,長度(這是我想要在這個例子中匹配的最重要的列)與第3階段不匹配,即使它應該有9的長度。那是因爲它沒有按順序執行它,它一次完成了所有的連接。 merge1之後,order 1已經合併 – Ic3MaN911

+0

因此order 3是唯一一個zipcode 1,它在交付時與長度9匹配。不知道這是否有意義 – Ic3MaN911

+0

好的,我明白了 - (它很難遵循這個長問題) - 它應該很容易,我會立即編輯 –

0

考慮所有的合併和行結合每個,然後刪除重複與unique()

merge1 <- unique(rbind(transform(merge(orders, deliveries, by.x = "address", by.y = "delivery_address", sort = FALSE), 
           delivery_address = address), 
         transform(merge(orders, deliveries, by.x = "zipcode", by.y = "postcode", sort = FALSE), 
           postcode = zipcode))) 

# address order zipcode length postcode delivery_address 
# 1  1111  1  1  4  1    1111 
# 2  1112  2  2  5  912    1112 
# 3  1113  4  999  11  910    1113 
# 4  1114  5  999  13  913    1114 
# 5  1618  6  6  93  80    1618 
# 6  1314  3  1  9  1    111 
# 7  1314  3  1  4  1    1111 
# 8  1111  1  1  9  1    111 
# 10 1618  6  6  15  6    0 
# 11 1917  7  7  17  7    1 
# 12 1118  8  7  17  7    1 
# 13 2000 10  10  12  10    1121 

對於跨多列的可普遍解決方案,我們使用Map()do.call() er定義的函數,seqmerge,其中您將xvaryvar擴展到合併列的配對。確保兩者長度相同。

seqmerge <- function(xvar, yvar) { 
    df <- merge(orders, deliveries, by.x = xvar, by.y = yvar, sort = FALSE) 
    df[[yvar]] = df[[xvar]] 
    return(df) 
} 

xvars <- c("address", "zipcode")    # ADD MORE AS NEEDED 
yvars <- c("delivery_address", "postcode")  # ADD MORE AS NEEDED 

merge2 <- unique(do.call(rbind, Map(seqmerge, xvars, yvars, USE.NAMES=FALSE))) 

all.equal(merge1, merge2) 
# [1] TRUE 

identical(merge1, merge2) 
# [1] TRUE 
+0

這種方法不恰當地匹配訂單和交付。由於這會導致相同訂單與多次交付相匹配的行,因爲多個條件都是成功的。出於同樣的原因,導致同樣的交付被映射到多個訂單。當我用我的數據集做這件事情時,結果有800萬行,但實際上,最多隻有9000或10000。我想要一個順序合併,因爲與不同的列合併會導致多個匹配,所以我從一個嚴格的合併開始,然後變得更加放鬆 – Ic3MaN911

相關問題