二つの表の動詞

データ分析では、1つの表のデータだけを扱うことは稀です。 実際には、分析に必要な多くの表があり、それらを組み合わせるための柔軟なツールが必要となります。 dplyr には、同時に2つの表を扱う3種類の動詞があります。

(ここでは、行がオブザベーション、列が変数であるTidy dataを想定しています。このフレームワークに慣れていない方は、まずそれを読むことをお勧めします)。

すべての2表式の動詞は同様に動作します。最初の2つの引数は xy で、結合する表を指定します。出力は常に x と同じ型の新しい表になります。

変異結合

変異結合は、複数の表の変数を組み合わせることができます。 例えば、nycflights13 のデータを見てみましょう。 ある表には、航空会社の略語を含むフライト情報があり、別の表には、略語とフルネームの間のマッピングがあります。 結合を使用して、フライトデータに航空会社名を追加することができます。

library("nycflights13")
# Drop unimportant variables so it's easier to understand the join results.
flights2 <- flights %>% select(year:day, hour, origin, dest, tailnum, carrier)

flights2 %>% 
  left_join(airlines)
#> Joining, by = "carrier"
#> # A tibble: 336,776 x 9
#>    year month   day  hour origin dest  tailnum carrier name                  
#>   <int> <int> <int> <dbl> <chr>  <chr> <chr>   <chr>   <chr>                 
#> 1  2013     1     1     5 EWR    IAH   N14228  UA      United Air Lines Inc. 
#> 2  2013     1     1     5 LGA    IAH   N24211  UA      United Air Lines Inc. 
#> 3  2013     1     1     5 JFK    MIA   N619AA  AA      American Airlines Inc.
#> 4  2013     1     1     5 JFK    BQN   N804JB  B6      JetBlue Airways       
#> 5  2013     1     1     6 LGA    ATL   N668DN  DL      Delta Air Lines Inc.  
#> # … with 336,771 more rows

表のマッチング方法の制御

xy と同様に、それぞれの変異結合は引数 by を取り、2つの表のオブザベーションをマッチさせるためにどの変数を使うかをコントロールします。 これを指定するにはいくつかの方法がありますが、以下に nycflights13 の様々な表を使って説明します。

結合の種類

変異結合には4つのタイプがあり、マッチしなかった場合の動作が異なります。簡単な例を挙げてそれぞれを説明します。

df1 <- tibble(x = c(1, 2), y = 2:1)
df2 <- tibble(x = c(3, 1), a = 10, b = "a")

左結合、右結合、完全結合を総称して 外側結合 と呼びます。 外側結合で行が一致しない場合、新しい変数には欠落した値が入力されます。

観測値

変異結合は主に新しい変数の追加に使用されますが、新しい観測値を生成することもできます。 一致するものが一意でない場合、結合は一致する観測値のすべての可能な組み合わせ(デカルト積)を追加します。

df1 <- tibble(x = c(1, 1, 2), y = 1:3)
df2 <- tibble(x = c(1, 1, 2), z = c("a", "b", "a"))

df1 %>% left_join(df2)
#> Joining, by = "x"
#> # A tibble: 5 x 3
#>       x     y z    
#>   <dbl> <int> <chr>
#> 1     1     1 a    
#> 2     1     1 b    
#> 3     1     2 a    
#> 4     1     2 b    
#> 5     2     3 a

フィルタリング結合

フィルタリング結合は変異結合と同じ方法で観測値をマッチさせますが、変数ではなく観測値に影響を与えます。 2つのタイプがあります。

これらは結合のミスマッチを診断するために最も有用です。 例えば、nycflights13 データセットの中には、planes 表の中に一致する tail 番号を持たない多くのフライトがあります。

library("nycflights13")
flights %>% 
  anti_join(planes, by = "tailnum") %>% 
  count(tailnum, sort = TRUE)
#> # A tibble: 722 x 2
#>   tailnum     n
#>   <chr>   <int>
#> 1 <NA>     2512
#> 2 N725MQ    575
#> 3 N722MQ    513
#> 4 N723MQ    507
#> 5 N713MQ    483
#> # … with 717 more rows

もし、結合がどの観測値にマッチするか心配ならば、semi_join() または anti_join() から始めてください。 semi_join()anti_join() は、重複することはなく、観測値を削除するだけです。

df1 <- tibble(x = c(1, 1, 3, 4), y = 1:4)
df2 <- tibble(x = c(1, 1, 2), z = c("a", "b", "a"))

# Four rows to start with:
df1 %>% nrow()
#> [1] 4
# And we get four rows after the join
df1 %>% inner_join(df2, by = "x") %>% nrow()
#> [1] 4
# But only two rows actually match
df1 %>% semi_join(df2, by = "x") %>% nrow()
#> [1] 2

集合演算

2つの表の動詞の最後のタイプは集合演算です。 これらは xy の入力が同じ変数を持つことを想定しており、観測値を集合のように扱います。

この単純なデータを考えると

(df1 <- tibble(x = 1:2, y = c(1L, 1L)))
#> # A tibble: 2 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     1
(df2 <- tibble(x = 1:2, y = 1:2))
#> # A tibble: 2 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     2

4つの可能性があります。:

intersect(df1, df2)
#> # A tibble: 1 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
# Note that we get 3 rows, not 4
union(df1, df2)
#> # A tibble: 3 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     1
#> 3     2     2
setdiff(df1, df2)
#> # A tibble: 1 x 2
#>       x     y
#>   <int> <int>
#> 1     2     1
setdiff(df2, df1)
#> # A tibble: 1 x 2
#>       x     y
#>   <int> <int>
#> 1     2     2

複数表対応の動詞

dplyr は、3つ以上の表を扱うための関数を提供していません。その代わりに、Advanced Rで説明されているように、 purrr::reduce() または Reduce() を使用して、2つの表の動詞を反復的に組み合わせて、必要な数の表を処理します。