Rにおけるdplyrチュートリアル:データのマージと結合(例付き)

⚡ スマートサマリー

dplyr パッケージは、left_join()、right_join()、inner_join()、full_join() の 4 つの関数を使用して、R のデータフレームをマージおよび結合します。その関連パッケージである tidyr は、gather()、spread()、separate()、unite() を使用して、結合された結果を整形します。

  • 🔗 結合の変更: left_join() は元のテーブルのすべての行を保持し、right_join() は宛先テーブルのすべての行を保持します。
  • 🎯 マッチコントロール: inner_join() は一致しない行を削除しますが、full_join() は両方の側を保持し、欠落部分を NA で埋めます。
  • 🗝️ 複合キー: 単一の列が行を一意に識別しない場合は、常に = c(“ID”, “year”) を渡します。
  • 🔄 レシャping: gather() は幅の広いテーブルを長くし、spread() はそれを元に戻します。ping 列ごとに1つの変数。
  • ✂️ 分裂と統合: separate() は区切り文字で列を分割し、unite() は分割された列を再び1つに連結します。
  • ⚠️ バージョンノート: pivot_longer()、pivot_wider()、separate_wider_delim() は、以前の tidyr resha に取って代わります。ping 機能します。

R言語におけるdplyr:データの結合と結合

データ分析入門

参加または再共有する前にping 動詞が意味を成すので、データ操作がどこに当てはまるのかが分かりやすくなります。 データ分析 3つの部分に分けられます。

  • 抽出プロセス: まず、多くのソースからデータを収集し、それらを組み合わせる必要があります。
  • エージェント型AIで研究開発を変革: このステップにはデータ操作が含まれます。 すべてのデータソースを統合したら、データのクリーンアップを開始できます。
  • 視覚化する: 最後の手段は、データを可視化して異常をチェックすることです。

下の図は、3つの段階がどのように繋がっているかを示しています。

3段階のデータ分析プロセスで、trac変換、変形、視覚化
データ分析プロセス

データサイエンティストが直面する最も大きな課題の一つは、データ操作です。データは常に希望通りの形式で入手できるとは限りません。データサイエンティストは、少なくとも時間の半分をデータのクリーニングと操作に費やす必要があります。これは、この仕事において最も重要な業務の一つです。データ操作プロセスが完全かつ正確で厳密でなければ、モデルは正しく機能しません。

R dplyr

Rには、データ変換を扱うdplyrというパッケージがあります。これは、filter()、select()、arrange()、mutate()、summarise()といった少数のコア関数と、結合関数群を中心に構成されています。データが適切な形式に整えば、ggplot2で可視化できます。

dplyr パッケージを使用して操作する方法を学びます データフレームRがまだインストールされていない場合は、次の手順に従ってください。 RとRStudioのセットアップ手順次に、install.packages(“dplyr”)を実行します。

dplyrでデータをマージする

dplyr は、データセットを結合する優れた便利な方法を提供します。 入力データのソースが多数ある場合、ある時点でそれらを組み合わせる必要があります。 dplyr を使用した結合では、元のデータセットの右側に変数が追加されます。

dplyr が参加します

dplyrで2つのデータセットを結合する際に使用される重要な結合の種類を4つ紹介します。これら4つはすべて同じ引数(2つのテーブルとキー)を取り、一致しない行のうちどれを残すかという点だけが異なります。

演算 DevOps Tools Engineer試験のObjective Arguments 複数のキー
left_join() XNUMX つのデータセットを結合します。 元のテーブルからのすべての観測値を保持します x、y、by = “ID” x、y、by = c(“ID”, “ID2”)
right_join() XNUMX つのデータセットを結合します。 宛先テーブルからのすべての観測値を保持します x、y、by = “ID” x、y、by = c(“ID”, “ID2”)
inner_join() 2つのデータセットをマージします。一致しない行はすべて除外します。 x、y、by = “ID” x、y、by = c(“ID”, “ID2”)
full_join() 2つのデータセットをマージします。すべての観測値を保持します。 x、y、by = “ID” x、y、by = c(“ID”, “ID2”)

これら 4 つの動詞は、LEFT、RIGHT、INNER、FULL OUTER 結合にマッピングされます。 SQL. Base R は、all、all.x、all.y 引数を通じて同じ結果を得ます。 マージ().

簡単な例を通して、すべての結合タイプについて学習します。

まず、2 つのデータセットを作成します。表 1 には ID と y という 2 つの変数が含まれていますが、表 2 には ID と z が含まれています。それぞれの状況で、 キーペア 変数。 私たちの場合、ID は私たちのものです key 変数。この関数は両方のテーブルで同一の値を探し、返された値をテーブル1の右側にバインドします。下の図は、2つのテーブルを並べて表示したものです。

dplyrによるマージ前にIDキー列を共有する2つのサンプルテーブル

library(dplyr)
df_primary <- tribble(
  ~ID, ~y,
   "A", 5,
   "B", 5,
   "C", 8,
   "D", 0,
  "F", 9)
df_secondary <- tribble(
  ~ID, ~z,
   "A", 30,
   "B", 21,
   "C", 22,
   "D", 25,
   "E", 29)

dplyr left_join()

2 つのデータセットを結合する最も一般的な方法は、left_join() 関数を使用することです。下の図は、キー ペアが行 A、B、C、D と一致し、E と F が残っていることを示しています。left_join() を使用すると、元のテーブルのすべての行が保持され、宛先テーブルにキー ペアがない行は無視されます。この例では、値 E はテーブル 1 に存在しないため、その行は削除されます。値 F は元のテーブルから取得されるため、left_join() の後も保持され、列 z には NA が返されます。

dplyr left_join() の例

以下の図は、left_join() の実行中に何が起こるかを再現したものです。

dplyrのleft_join keeの図ping 元のテーブルのすべての行を削除ping ID E

left_join(df_primary, df_secondary, by ='ID')

出力:

## 
# A tibble: 5 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>		
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     F     9    NA

両方のテーブルに同じ名前の列がある場合、dplyr は上記の .x および .y という接尾辞を使用してそれらを区別することに注意してください。

dplyr right_join()

right_join() 関数は left_join() とまったく同じように機能します。 唯一の違いは、削除された行です。 宛先データ フレームで使用可能な値 E は新しいテーブルに存在し、列 y の値 NA をとります。

dplyr right_join() の例

下の図は鏡像を示しています。

dplyr right_join kee の図ping 宛先テーブルのすべての行を削除ping ID F

right_join(df_primary, df_secondary, by = 'ID')

出力:

##
# A tibble: 5 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     E    NA    29

dplyr inner_join()

一致しない観測値が全く役に立たない場合は、 存在する行 両言語で データセット。これは、完全なデータセットが必要で、欠損値を平均値や中央値で補完したくない場合に最適な選択肢です。

ここで役立つのが inner_join() 関数です。この関数は、両側の一致しない行を除外します。

dplyr inner_join() の例

下の図は、結合後も残る4つのIDを強調表示しています。

dplyr inner_join の図。両方のテーブルに存在する 4 つの ID のみを返す。

inner_join(df_primary, df_secondary, by ='ID')

出力:

## 
# A tibble: 4 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25

dplyr full_join()

最後に、full_join() 関数はすべての観測値を保持し、欠損値を NA に置き換えます。

dplyr full_join() の例

下の図は、結合後も残る両方のテーブルのすべてのIDを示しています。

dplyr full_join kee の図ping 6つのIDすべてと、欠損値をNAで埋める

full_join(df_primary, df_secondary, by = 'ID')

出力:

## # A tibble: 6 x 3
##      ID   y.x   y.y
##   <chr> <dbl> <dbl>
## 1     A     5    30
## 2     B     5    21
## 3     C     8    22
## 4     D     0    25
## 5     F     9    NA
## 6     E    NA    29

複数のキーペア

最後に、データセットには複数のキーを含めることができます。顧客が購入した年と製品リストを含む以下のデータセットを考えてみましょう。下のスクリーンショットは、2つのテーブルと、行を識別するID列と年列を示しています。

ID列と年列で構成される複合キーを共有する2つのデータフレーム

IDのみで両方のテーブルを結合すると、すべての年がすべての年と照合され、行数が爆発的に増加します。この状況を改善するには、2つのキーペア変数、つまり両方のデータセットに存在するIDと年を渡すことができます。テーブル1とテーブル2をマージするには、次のコードを使用できます。

df_primary <- tribble(
  ~ID, ~year, ~items,
  "A", 2015,3,
  "A", 2016,7,
  "A", 2017,6,
  "B", 2015,4,
  "B", 2016,8,
  "B", 2017,7,
  "C", 2015,4,
  "C", 2016,6,
  "C", 2017,6)
df_secondary <- tribble(
  ~ID, ~year, ~prices,
  "A", 2015,9,
  "A", 2016,8,
  "A", 2017,12,
  "B", 2015,13,
  "B", 2016,14,
  "B", 2017,6,
  "C", 2015,15,
  "C", 2016,15,
  "C", 2017,13)
left_join(df_primary, df_secondary, by = c('ID', 'year'))

出力:

## # A tibble: 9 x 4
##      ID  year items prices
##   <chr> <dbl> <dbl>  <dbl>
## 1     A  2015     3      9
## 2     A  2016     7      8
## 3     A  2017     6     12
## 4     B  2015     4     13
## 5     B  2016     8     14
## 6     B  2017     7      6
## 7     C  2015     4     15
## 8     C  2016     6     15
## 9     C  2017     6     13

dplyr 1.1.0 (2023 年 1 月) 以降、同じキーを join_by(ID, year) と記述することができ、dplyr は予期しない多対多の一致について警告するようになりました。 dplyr 1.1.0 がアナウンスに参加しました 説明しています。

R のデータ クリーニング関数

マージしても問題の半分しか解決しません。なぜなら、結合されたテーブルも整形する必要があるからです。データを整理(クリーンアップ)するための重要な関数は次の4つです。

演算 DevOps Tools Engineer試験のObjective Arguments
集める() データをワイドからロングに変換する (データ、キー、値、na.rm = FALSE)
広める() データを長いデータから広いデータに変換する (データ、キー、値)
別() 1つの変数を2つに分割する (データ、列、挿入、区切り文字 = "", 削除 = TRUE)
団結() 2つの変数を1つに統合する (データ、列、コントラスト、区切り文字 = "", remove = TRUE)

バージョンノート: gather() と spread() は tidyr 1.0.0 で pivot_longer() と pivot_wider() に置き換えられ、separate() は tidyr 1.3.0 で separate_wider_delim() ファミリーに置き換えられました。置き換えられた関数は引き続き実行されるため、以下のすべての例は動作しますが、新しいコードでは、次の新しいファミリーを使用することをお勧めします。 整理整頓されたピボット式ビネットunite() は引き続き有効です。

データ操作、クリーニング、視覚化には、tidyverse コレクションの一部である tidyr パッケージを使用します。R が Anaconda でインストールされている場合、パッケージは既に以下から入手できます。 https://anaconda.org/r/r-tidyr.

まだインストールされていない場合は、次のコマンドを入力して tidyr をインストールします。

install.packages("tidyr")

集める()

gather() 関数の目的は、データをワイド形式からロング形式に変換することです。

構文

gather(data, key, value, na.rm = FALSE)
Arguments:
-data: The data frame used to reshape the dataset 
-key: Name of the new column created
-value: Select the columns used to fill the key column
-na.rm: Remove missing values. FALSE by default

例:

以下では、resha の概念を視覚化することができます。ping 幅広から長さ広へ。ここでは、「成長」という名前の単一の列を作成し、四半期変数の行で埋めます。下の図は、左側に幅広の表、右側に形状変更後の長さ広の表を示しています。

レシャping tidyrのgather機能を使用して、幅の広い四半期表を長い形式に変換する

library(tidyr)
# Create a messy dataset
messy <- data.frame(
  country = c("A", "B", "C"),
  q1_2017 = c(0.03, 0.05, 0.01),
  q2_2017 = c(0.05, 0.07, 0.02),
  q3_2017 = c(0.04, 0.05, 0.01),
  q4_2017 = c(0.03, 0.02, 0.04))
messy

出力:

##   country q1_2017 q2_2017 q3_2017 q4_2017
## 1       A    0.03    0.05    0.04    0.03
## 2       B    0.05    0.07    0.05    0.02
## 3       C    0.01    0.02    0.01    0.04
# Reshape the data
tidier <-messy %>%
gather(quarter, growth, q1_2017:q4_2017)
tidier

出力:

##    country quarter growth
## 1        A q1_2017   0.03
## 2        B q1_2017   0.05
## 3        C q1_2017   0.01
## 4        A q2_2017   0.05
## 5        B q2_2017   0.07
## 6        C q2_2017   0.02
## 7        A q3_2017   0.04
## 8        B q3_2017   0.05
## 9        C q3_2017   0.01
## 10       A q4_2017   0.03
## 11       B q4_2017   0.02
## 12       C q4_2017   0.04

gather() 関数では、元のデータセットには country というグループ変数とキーと値のペアが 1 つあるため、quarter と growth という 2 つの新しい変数を作成します。tidyr 1.0.0 以降では、同じ reshape は pivot_longer(messy, cols = q1_2017:q4_2017, names_to = “quarter”, values_to = “growth”) と記述されます。

広める()

spread() 関数は gather() 関数の逆の動作をします。

構文

spread(data, key, value)
arguments: 
data: The data frame used to reshape the dataset
key: Column to reshape long to wide
value: Rows used to fill the new column

例:

spread() 関数を使えば、整然としたデータセットを再び乱雑な状態に戻すことができます。

# Reshape the data
messy_1 <- tidier %>%
  spread(quarter, growth) 
messy_1

出力:

##   country q1_2017 q2_2017 q3_2017 q4_2017
## 1       A    0.03    0.05    0.04    0.03
## 2       B    0.05    0.07    0.05    0.02
## 3       C    0.01    0.02    0.01    0.04

現代版の同等のものは pivot_wider(tidier, names_from = quarter, values_from = growth) です。

別()

separate() 関数は、区切り文字に基づいて列を 2 つに分割します。この関数は、変数が日付である場合に役立ちます。分析では月と年に焦点を当てる必要があり、列を 2 つの新しい変数に分割したい場合があります。

構文

separate(data, col, into, sep= "", remove = TRUE)
arguments:
-data: The data frame used to reshape the dataset 
-col: The column to split
-into: The name of the new variables
-sep: Indicates the symbol used that separates the variable, i.e.:  "-", "_", "&"
-remove: Remove the old column. By default sets to TRUE.

例:

Separate() 関数を適用すると、より整理されたデータセット内の年から四半期を分割できます。

separate_tidier <-tidier %>%
separate(quarter, c("Qrt", "year"), sep ="_")
head(separate_tidier)

出力:

##   country Qrt year growth
## 1       A  q1 2017   0.03
## 2       B  q1 2017   0.05
## 3       C  q1 2017   0.01
## 4       A  q2 2017   0.05
## 5       B  q2 2017   0.07
## 6       C  q2 2017   0.02

団結()

unite() 関数は、2 つの列を 1 つの列に連結します。

構文

unite(data, col, conc ,sep= "", remove = TRUE)
arguments:
-data: The data frame used to reshape the dataset 
-col: Name of the new column
-conc: Name of the columns to concatenate
-sep: Indicates the symbol used that unites the variable, i.e:  "-", "_", "&"
-remove: Remove the old columns. By default, sets to TRUE

例:

上記の例では、四半期と年を分けて表示しました。これらを結合したい場合はどうすればよいでしょうか?次のコードを使用します。

unit_tidier <- separate_tidier %>%
  unite(Quarter, Qrt, year, sep ="_")
head(unit_tidier)

出力:

##   country Quarter growth
## 1       A q1_2017   0.03
## 2       B q1_2017   0.05
## 3       C q1_2017   0.01
## 4       A q2_2017   0.05
## 5       B q2_2017   0.07
## 6       C q2_2017   0.02

整形されたデータフレームは、残りの部分で説明するモデリング手順を実行する準備が整いました。 Rチュートリアルシリーズ.

よくあるご質問

merge() は all、all.x、all.y フラグを通してすべての結合を表現しますが、dplyr は動詞自体で動作に名前を付けます。dplyr は元の行の順序も保持し、tibble を返します。基本の R ルートについては、 データフレームをマージする ガイド。

これらは結合をフィルタリングするため、列を追加することはありません。semi_join(x, y)は、yに一致する行を持つxの行を保持し、anti_join(x, y)は一致しない行を保持します。どちらも、変更結合の前にキーを監査するのに役立ちます。

明示的に `by = c(“ID” = “customer_id”)` を使用してマッピングするか、新しい `join_by(ID == customer_id)` ヘルパーを使用してください。マップがない場合pingdplyr は共有列名すべてにマッチするため、結果を暗黙のうちに絞り込んだり、逆に拡大したりする可能性があります。

キーの値が両側で繰り返されるため、すべての組み合わせが生成されます。まず各キーに対して duplicated() をチェックし、多対多の側を集約するか、relationship = “many-to-many” を渡して意図を明示してください。dplyr は、予期しない多対多の一致について警告します。

filter() は行を選択し、select() は列を選択し、arrange() は行を選択します。 呪文mutate() は列を追加し、summarise() は group_by() で作成されたグループを統合します。パイプは 1 つの結果を次の動詞に渡します。%>% は dplyr に付属しており、|> は R のネイティブ機能です。

AIアシスタントはデータフレームをプロファイリングし、結合前に重複または入力ミスのあるキーをフラグ付けし、再共有を提案することができます。ping レイアウトに適した動詞を使用し、行数の急激な変化を分かりやすい言葉で説明してください。必ずコードを再実行し、寸法を自分で確認してください。

Yes. GitHubコパイロット RStudio Desktop 2023.09.0以降で動作し、コメントから結合パイプラインとピボットパイプラインを完成させます。Positは、提案は非決定論的であるため、実行する前に生成されたすべての行を確認するよう注意を促しています。

結合を連鎖させるか、Reduce(function(x, y) left_join(x, y, by = “ID”), list(df1, df2, df3)) を使用してリストを折りたたみます。purrr::reduce() も同じ処理を行います。重複するキーは結合をまたいで増えるため、各ステップの後に nrow() を確認してください。