0Pricing
R Academy · レッスン

dplyrでの複数テーブル結合

inner_join、left_join、right_join、full_join、anti_joinを使いこなします。

「dplyrでの複数テーブル結合」はCoddyKit上の無料R Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはR Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 R Academyコースには全4レッスンが含まれています。

テーブルを結合する理由

実際のデータが1つのテーブルだけに収まっていることは、ほとんどありません。リレーショナルデータベースでは、重複を避けるために情報を複数のテーブルに分けて保存します。結合を使うと、共通するキーに基づいてテーブルを組み合わせることができます。dplyrには、すっきりと読みやすい構文で利用できるSQL形式の結合関数が用意されています。

library(dplyr)

# Two related tables
orders <- data.frame(
  order_id = 1:4,
  customer_id = c(1, 2, 1, 3),
  amount = c(250, 180, 320, 90)
)

customers <- data.frame(
  customer_id = 1:3,
  name = c('Alice','Bob','Carol'),
  city = c('NYC','LA','Chicago')
)

print(orders)
print(customers)

inner_join() — 一致する行のみ

inner_join(x, y, by='key')は、キーが両方のテーブルに存在する行だけを返します。もう一方のテーブルに一致する行がない行は削除されます。最も一般的な結合の種類です。

library(dplyr)

orders <- data.frame(
  order_id = 1:4,
  customer_id = c(1, 2, 1, 99),
  amount = c(250, 180, 320, 90)
)

customers <- data.frame(
  customer_id = c(1, 2, 3),
  name = c('Alice','Bob','Carol')
)

# customer_id = 99 in orders has no match => dropped
# customer_id = 3 in customers has no match => dropped
inner_join(orders, customers, by = 'customer_id')

left_join() — 左側のすべての行を保持

left_join(x, y, by='key')は、xのすべての行を保持し、yから一致するデータを追加します。yに一致する行がないxの行では、yの列にNAが入ります。結果は左側のテーブルを基準に作られます。

library(dplyr)

orders <- data.frame(
  order_id = 1:4,
  customer_id = c(1, 2, 1, 99),
  amount = c(250, 180, 320, 90)
)

customers <- data.frame(
  customer_id = c(1, 2, 3),
  name = c('Alice','Bob','Carol')
)

# Order with customer_id=99 is kept, name = NA
left_join(orders, customers, by = 'customer_id')

right_join() — 右側のすべての行を保持

right_join(x, y, by='key')は、yのすべての行を保持します。xに一致する行がないyの行では、xの列にNAが入ります。left_join()の反対の動作です。テーブルの順序を入れ替えればよいため、こちらはあまり使われません。

library(dplyr)

orders <- data.frame(
  order_id = c(1, 2),
  customer_id = c(1, 2),
  amount = c(250, 180)
)

customers <- data.frame(
  customer_id = c(1, 2, 3),
  name = c('Alice','Bob','Carol')
)

# Carol (customer_id=3) has no orders => NA for order columns
right_join(orders, customers, by = 'customer_id')

full_join() — すべての行を保持

full_join(x, y, by='key')は、両方のテーブルのすべての行を保持します。どちらか一方にしか存在しない行では、もう一方のテーブルの列にNAが入ります。データを1件も失えない場合に使用します。

library(dplyr)

q1 <- data.frame(product = c('A','B','C'), q1_sales = c(100, 200, 150))
q2 <- data.frame(product = c('A','C','D'), q2_sales = c(120, 160, 90))

# D appears only in q2, B only in q1 => both kept
full_join(q1, q2, by = 'product')

anti_join() — 一致しない行を見つける

anti_join(x, y, by='key')は、yに一致する行がないxの行を返します。yの列は含まれません。孤立レコード、一致しない注文、参照テーブルに存在しない項目などを見つけるのに最適です。

library(dplyr)

all_employees <- data.frame(
  id = 1:5,
  name = c('Alice','Bob','Carol','Dave','Eve')
)

trained <- data.frame(id = c(1, 3, 5))

# Who has NOT completed training?
anti_join(all_employees, trained, by = 'id')

semi_join() — 一致する行で絞り込む

semi_join(x, y, by='key')は、yに一致する行があるxの行を返しますが、yの列は追加しません。inner_join()に似ていますが、xの列だけを返すため、フィルタリングのステップとして便利です。

library(dplyr)

products <- data.frame(
  id = 1:5,
  name = c('Widget','Gadget','Donut','Gizmo','Sprocket'),
  price = c(9.99, 24.99, 1.99, 14.99, 4.99)
)

ordered_products <- data.frame(id = c(1, 3, 5))

# Products that appear in at least one order
semi_join(products, ordered_products, by = 'id')

異なる列名で結合する

xとyでキー列の名前が異なる場合は、by = c('x_col' = 'y_col')構文を使用します。これにより、左側のテーブルの列名を右側のテーブルの対応する列名に割り当てます。

library(dplyr)

orders <- data.frame(
  order_id = 1:3,
  user_id = c(10, 20, 10),
  amount = c(100, 200, 150)
)

users <- data.frame(
  id = c(10, 20, 30),
  username = c('alice','bob','carol')
)

# orders.user_id matches users.id
left_join(orders, users, by = c('user_id' = 'id'))

複数のキーで結合する

byにベクトルを渡すと、複数の列を使って結合できます。行を結合するには、指定したすべての列が一致している必要があります。1つの列だけでは一意にならない複合キーを扱う場合に便利です。

library(dplyr)

actual <- data.frame(
  year = c(2023, 2023, 2024, 2024),
  quarter = c('Q1','Q2','Q1','Q2'),
  sales = c(100, 120, 130, 150)
)

target <- data.frame(
  year = c(2023, 2023, 2024, 2024),
  quarter = c('Q1','Q2','Q1','Q2'),
  target = c(110, 115, 125, 145)
)

inner_join(actual, target, by = c('year', 'quarter'))

複数の結合を連結する

パイプ演算子を使うと、1つのパイプライン内で複数の結合を連結できます。複数のルックアップテーブルから、1ステップずつ情報を追加して非正規化ビューを構築できます。

library(dplyr)

orders <- data.frame(order_id=1:3, cust_id=c(1,2,1), prod_id=c(10,10,20))
customers <- data.frame(cust_id=1:2, name=c('Alice','Bob'))
products <- data.frame(prod_id=c(10,20), product=c('Widget','Gadget'))

orders %>%
  left_join(customers, by = 'cust_id') %>%
  left_join(products, by = 'prod_id')

重複する列の処理

両方のテーブルに同じ名前の列がある場合(結合キーを除く)、dplyrは.xと.yのサフィックスを付けます。suffix引数を使ってこれらを変更し、必要に応じて列を選択または名前変更できます。

library(dplyr)

current <- data.frame(id=1:3, value=c(10,20,30), date=Sys.Date())
historic <- data.frame(id=1:3, value=c(8,22,28), date=Sys.Date()-365)

# Both have 'value' and 'date' columns
result <- inner_join(current, historic, by='id',
                     suffix=c('_current','_historic'))
print(names(result))

理解度チェック

右側のテーブルに一致する行がない、左側のテーブルの行だけを返すdplyrの結合はどれですか?

まとめ:dplyrの結合

dplyrで複数のテーブルを結合する際の重要ポイント:

  • inner_join() — 両方のテーブルで一致する行のみ
  • left_join() — 左側のすべての行。一致する右側の行がない場合はNA
  • right_join() — 右側のすべての行。一致する左側の行がない場合はNA
  • full_join() — 両方のテーブルのすべての行。一致しない場合はNA
  • anti_join() — yに一致しないxの行(フィルタリング用)
  • semi_join() — yに一致するxの行(フィルタリング用)
  • 列名が異なる場合はby = c('x_col' = 'y_col')を使用します
  • 複合キーにはベクトルを使用します:by = c('year', 'quarter')
library(dplyr)

# Chain of joins: the typical real-world pattern
orders <- data.frame(oid=1:3, cid=c(1,2,1), pid=c(10,20,10))
customers <- data.frame(cid=1:2, name=c('Alice','Bob'))
products <- data.frame(pid=c(10,20), name=c('Widget','Gadget'), price=c(9.99,19.99))

orders %>%
  inner_join(customers, by='cid') %>%
  inner_join(products, by='pid', suffix=c('','_product')) %>%
  select(oid, name, name_product, price)

よくある質問

「dplyrでの複数テーブル結合」レッスンは無料ですか?

はい。「dplyrでの複数テーブル結合」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、R Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 R Academyコースには全4レッスンが含まれています。

「dplyrでの複数テーブル結合」で何を学びますか?

inner_join、left_join、right_join、full_join、anti_joinを使いこなします。 ブラウザで直接実行するハンズオンコードでR Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

R Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのR Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「dplyrでの複数テーブル結合」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このR Academyレッスンでコードを書いて実行できますか?

はい。すべてのR Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. グループ別集計とgroup_by()
  2. ウィンドウ関数:lag、lead、cumsum
  3. dplyrでの複数テーブル結合
  4. Tidy評価:{{ }}と.data
← R Academyに戻る