簡體   English   中英

使用 OR 條件為要匹配的列連接數據框

[英]Join dataframes using an OR condition for columns to match by

假設我們有兩個要加入的數據框。 為簡單起見,假設兩者具有相同的行數,並且一個數據幀中的每一行必須在另一個數據幀中具有唯一的對應行。 這是此設置的 MWE:

library(dplyr)
df1 <- tibble(id1 = 1:3, x = c("b", "a", "b"), y = c(55, 50, 58), z = c(65, 60, 69))
df2 <- tibble(id2 = 11:13, x = c("a", "b", "b"), y = c(50, 55, 59), z = c(61, 66, 69))

# # A tibble: 3 x 4
#     id1 x         y     z
#   <int> <chr> <dbl> <dbl>
# 1     1 b        55    65
# 2     2 a        50    60
# 3     3 b        58    69
# # A tibble: 3 x 4
#     id2 x         y     z
#   <int> <chr> <dbl> <dbl>
# 1    11 a        50    61
# 2    12 b        55    66
# 3    13 b        59    69

目標是將df1中的唯一 ID 與df2唯一但不同的 ID 鏈接起來。 我可以通過利用xyz列中的組合信息足以唯一地標識行這一事實來做到這一點。 下面詳細解釋的問題是,如果我們能夠通過諸如c("x", "y" OR "z")類的內容進行連接,連接將在此設置中正常工作。

  • x列開始,我們有足夠的信息將id1 == 2id2==11 ,因為它們共享相同的唯一值(即"a" )。 但是,對於其余的對,僅列x是不夠的。
  • 在連接中使用列y允許我們將id1 == 1id2==12鏈接起來。 但是,列y (除了x )將(正確地)不匹配id1 == 3id2==13 ,因為它們具有不同的y值。
  • 在連接中使用列z允許我將id1 == 3id2==13鏈接起來,但現在我們遇到了與以前相同的問題,現在將id1 == 1id2==12鏈接起來:它們的z值不同。 此外,如果我們通過z加入,那么我們會破壞id1 == 2id2==11的鏈接(盡管這個例子在沒有這個額外的怪癖的情況下仍然可以工作)。

因此,問題是,除了在x嚴格匹配之外,是否有一種好的和/或簡潔的方式在yz列上使用OR條件連接這兩個數據幀。 就像是

full_join(df1, df2, by = c("x", "y" OR "z"))

到目前為止,我的嘗試涉及一系列連接和其他操作,但讀取起來非常麻煩(這使它容易出錯),而且對於足夠大的數據來說可能太慢了。 我願意對此方法進行更正,或者被告知這是唯一的方法(盡管我真的希望不是)。

left_join(df1, df2, by = c("x", "y"), suffix = c("1", "2")) %>% 
  left_join(df2, by = c("x", "z1" = "z"), suffix = c("1", "2")) %>% 
  rowwise() %>% 
  mutate(id2 = sum(id21, id22, na.rm = T)) %>% 
  select(id1, id2)

# # A tibble: 3 x 2
# # Rowwise: 
#     id1   id2
#   <int> <int>
# 1     1    12
# 2     2    11
# 3     3    13

您可以使用tidyr將兩個 data.frames 轉換為長格式。

library(tidyr)
library(dplyr)

df2_2 <- df2 %>% 
  pivot_longer(c(y, z))

df1_1 <- df1 %>% 
  pivot_longer(c(y, z))

接下來,您inner_join都是由你轉動data.frames的x和新value列,並把它們放回寬格式。 所以

df1_1  %>% 
  inner_join(df2_2, by=c("x", "value")) %>% 
  pivot_wider(names_from="name.x") %>% 
  select(-name.y)

返回

# A tibble: 3 x 5
    id1 x       id2     y     z
  <int> <chr> <int> <dbl> <dbl>
1     1 b        12    55    NA
2     2 a        11    50    NA
3     3 b        13    NA    69

要么

df1_1  %>% 
  inner_join(df2_2, by=c("x", "value")) %>% 
  pivot_wider(names_from="name.x") %>% 
  select(id1, id2)

給你你想要的輸出

# A tibble: 3 x 2
    id1   id2
  <int> <int>
1     1    12
2     2    11
3     3    13

如果yz是相同類型,這可以正常工作。 如果它們的類型不同(例如一個是字符,另一個是雙pivot_longer ),則必須將它們轉換為通用格式,以便pivot_longer起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM