データフレームの結合

キー列を使用する結合

  • データフレーム同士を正しく結合するためには、行を合致させるために、基準となるキー列が必要
    • 両方のデータフレームに共通して存在する列をキー列とする
    • キー列は1つでも複数でも良い

  • 以下の3つの表を結合したい
campus <- tibble::tribble(
  ~キャンパス, ~学部,
  "三田", "文",
  "三田", "経済",
  "三田", "法",
  "三田", "商",
)

campus
dep <- tibble::tribble(
  ~faculty, ~学科,
  "文", "人文社会",
  "法", "政治",
  "法", "法律",
)

dep
mita_grade <- tibble::tribble(
  ~学部, ~学年,
  "文", 4,
  "文", 3,
  "文", 2,
  "経済", 4,
  "経済", 3,
  "法", 4,
  "法", 3,
  "商", 4,
  "商", 3,
)

mita_grade
  • 全ての表に共通する列は「学部」
    • よって、学部列がキー列となる

データの結合

dplyr::left_join()

  • 第1引数に指定するデータフレーム: 全ての
  • 第2引数に指定するデータフレーム: 第1引数のデータフレームにも存在する行
  • join_by関数を用いて、キー列を指定
    • キー列はカンマで区切って複数指定可
    • join_by関数の中では、filter関数のように条件指定が可能
dplyr::left_join(dep, campus, dplyr::join_by(faculty == 学部))

dplyr::right_join()

  • left_join()の逆
  • 第1引数に指定するデータフレーム: 第2引数のデータフレームにも存在する行
  • 第2引数に指定するデータフレーム: 全ての
dplyr::right_join(dep, campus, dplyr::join_by(faculty == 学部))

dplyr::inner_join()

  • 2つの引数で指定したデータフレーム両方に共通して存在するのみ抽出
dplyr::inner_join(dep, mita_grade, dplyr::join_by(faculty == 学部))
Warning in dplyr::inner_join(dep, mita_grade, dplyr::join_by(faculty == : Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 1 of `x` matches multiple rows in `y`.
ℹ Row 6 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship =
  "many-to-many"` to silence this warning.

dplyr::full_join()

  • 2つの引数で指定したデータフレームの少なくともどちらかに存在するを抽出
dplyr::full_join(dep, mita_grade, dplyr::join_by(faculty == 学部))
Warning in dplyr::full_join(dep, mita_grade, dplyr::join_by(faculty == 学部)): Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 1 of `x` matches multiple rows in `y`.
ℹ Row 6 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship =
  "many-to-many"` to silence this warning.

dplyr::semi_join

  • 第1引数のデータフレームのうち、第1引数・第2引数のデータフレームの両方に存在する行を抽出
    • チェックに便利
dplyr::semi_join(campus, dep, dplyr::join_by(学部 == faculty))

dplyr::anti_join

  • 第1引数のデータフレームのうち、第1引数のデータフレームには存在するが第2引数のデータフレームには存在しない行を抽出
    • チェックに便利
dplyr::anti_join(campus, dep, dplyr::join_by(学部 == faculty))

dplyr::cross_join

  • 行の組み合わせとして考えうる全パターンを抽出
campus_2 <- tibble::tibble(campus = c("三田", "日吉"))

faculty_2 <- tibble::tibble(faculty = c("文", "経済", "法", "商"))

year_2 <- tibble::tibble(year = 1:4)

dplyr::cross_join(campus_2, faculty_2) |> 
  dplyr::cross_join(year_2)

キー列を使用しない結合

  • bind関数を用いれば、キー列を使用せずとも結合が可能
  • joinとは異なり、2つ以上のデータフレームを一括して結合できる

bind_rows()

  • の結合
    • データの重複は処理されない
tokyo_00_04 <- tibble::tribble(
  ~year, ~max_temp, ~min_temp,
  2000, 37.8, -0.7,
  2001, 38.1, -2.4,
  2002, 35.8, -0.3,
  2003, 34.3, -0.8,
  2004, 39.5, 0.2,
)

tokyo_05_09 <- tibble::tribble(
  ~year, ~max_temp, ~min_temp,
  2005, 36.2, -0.8,
  2006, 36.1, -1.5,
  2007, 37.5, 0.2,
  2008, 35.3, -0.1,
  2009, 34.2, 0,
)

tokyo_10_14 <- tibble::tribble(
  ~year, ~max_temp, ~min_temp,
  2010, 37.2, -0.4,
  2011, 36.1, -1.1,
  2012, 35.7, -1.0,
  2013, 38.3, -1.4,
  2014, 36.1, -1.3
)

dplyr::bind_rows(tokyo_00_04, tokyo_05_09, tokyo_10_14)

bind_cols()

  • の結合
    • キー列を使用しないため、両方のデータフレームの行の順番が異なっている場合、ずれて結合してしまうリスクがある
      • よって、全ての行が合うことが明確なケース以外では非推奨(極力、join関数を使う)
      • データの重複は処理されない
year <- tibble::tibble(year = 2000:2014)
max_temp <- tibble::tibble(max_temp = c(37.8, 38.1, 35.8, 34.3, 39.5, 36.2, 36.1, 37.5, 35.3, 34.2, 37.2, 36.1, 35.7, 38.3, 36.1))

min_temp <- tibble::tibble(min_temp = c(-0.7, -2.4, -0.3, -0.8, 0.2, -0.8, -1.5, 0.2, -0.1, 0, -0.4, -1.1, -1, -1.4, -1.3))

dplyr::bind_cols(year, max_temp, min_temp)

データフレームの正規化

第1正規形

  • データ分析をするために適切なデータフレームの形がある
    • その最低条件が、データフレームが第1正規形を満たしていることである
  • 第1正規形とは、項目が結合されていたり(=Excelのイメージで考える)、ネストされていたり(=項目の中に項目が入っている)、他の列の内容から算出できるような列が存在したりする状態ではない形の表のこと
    • 非正規形 (=結合・ネストされている項目が存在) から第1正規形に変換しなければ、データ分析で扱うのは困難
      • この変換は最も手間がかかる!
      • R だと、dplyr::fill 関数が役に立つ
        • 「NAの処理」も参照

第2正規形

  • 「使うデータフレームを全部結合して保存しておけば良い」とは限らない
    • 複数のデータフレームへ適切に分割し保存しておいた方が効率が上がる
      • 重複項目が減り、ファイルサイズが小さくなる
      • データの変更時に影響を及ぼす範囲が小さくなる
    • データを効率的に管理するための最低条件が、データフレームが第2正規形を満たしていることである
  • 第2正規形とは、第1正規形を満たし、かつデータフレームの*主キー以外の列の内容が、一つ以上の主キーの内容によって完全に定まる状態を満たす表のことである
    • joinの例での、campus, dep, mita_grade の表はすべて第2正規形でもある

第3正規形

  • 第3正規形とは、第2正規形を満たし、かつデータフレームの主キー以外の列の内容が、全ての主キーの内容によって完全に定まる状態を満たす表のことである
    • joinの例での、campus, dep, mita_grade の表はすべて第3正規形でもある