# dplyr 業務運用マニュアル

## 目次

**【基本操作】**
1. [システム概要](#1-システム概要)
2. [インストール・環境設定](#2-インストール環境設定)
3. [基本的な使い方](#3-基本的な使い方)

**【データ操作フローに沿った機能】**
4. [【STEP1】データの読み込みと確認](#4-step1データの読み込みと確認)
5. [【STEP2】データの抽出・フィルタリング](#5-step2データの抽出フィルタリング)
6. [【STEP3】データの変換・加工](#6-step3データの変換加工)
7. [【STEP4】データの集計・分析](#7-step4データの集計分析)

**【サポート機能】**
8. [結合操作](#8-結合操作)
9. [集合演算](#9-集合演算)
10. [ウィンドウ関数](#10-ウィンドウ関数)

**【運用ガイド】**
11. [日常業務の流れ](#11-日常業務の流れ)
12. [よくある質問と対処法](#12-よくある質問と対処法)
13. [トラブルシューティング](#13-トラブルシューティング)

---

## 1. システム概要

### 1.1 dplyrとは

dplyrは、Rにおけるデータ操作のための文法（Grammar of Data Manipulation）を提供するパッケージです。データフレームや類似オブジェクトに対して、一貫性のある直感的なAPIでデータの変換・集計・結合などの操作を行うことができます。

### 1.2 本パッケージで行う主要業務

dplyrは、主に以下のデータ操作業務を支援します：

| 業務カテゴリ | 具体的な業務内容 |
|------------|----------------|
| **行操作** | データの抽出（filter）、並び替え（arrange）、重複除去（distinct）、行の選択（slice） |
| **列操作** | 列の選択（select）、新規列の作成（mutate）、列名変更（rename）、列の並び替え（relocate） |
| **集計・グループ化** | グループ化（group_by）、集約処理（summarise）、件数カウント（count/tally） |
| **データ結合** | 内部結合（inner_join）、外部結合（left/right/full_join）、行/列の結合（bind_rows/bind_cols） |
| **集合演算** | 和集合（union）、積集合（intersect）、差集合（setdiff） |

### 1.3 データ操作フロー概要

dplyrにおけるデータ操作は、以下の流れで進行します：

```
+---------------------------------------------------------------------+
|                      データ操作フロー                                 |
+---------------------------------------------------------------------+
|                                                                     |
|  【STEP 1】データの読み込みと確認                                     |
|      tibble(), glimpse(), as_tibble()                               |
|      |                                                              |
|  【STEP 2】データの抽出・フィルタリング                               |
|      filter(), select(), slice(), distinct()                        |
|      |                                                              |
|  【STEP 3】データの変換・加工                                         |
|      mutate(), rename(), relocate(), if_else(), case_when()         |
|      |                                                              |
|  【STEP 4】データの集計・分析                                         |
|      group_by(), summarise(), count(), arrange()                    |
|      |                                                              |
|  【STEP 5】結果の出力                                                |
|      結果データフレームの利用、可視化、保存                            |
|                                                                     |
+---------------------------------------------------------------------+
```

**役割別の業務概要：**

| 役割 | 主な業務 |
|------|---------|
| **データアナリスト** | データの抽出・集計・分析、レポート作成 |
| **データサイエンティスト** | 特徴量エンジニアリング、データ前処理、モデル用データ準備 |
| **データエンジニア** | ETL処理、データパイプライン構築 |

### 1.4 主な機能

| 機能 | 説明 | データ操作フローでの位置 |
|------|------|------------------------|
| tibble/glimpse | データの確認・構造把握 | STEP 1 |
| filter/select | 行・列の抽出 | STEP 2 |
| mutate | 新規列の作成・既存列の変更 | STEP 3 |
| group_by/summarise | グループ化と集計 | STEP 4 |
| join関数群 | データの結合 | 随時利用 |
| arrange | データの並び替え | STEP 4/随時利用 |

### 1.5 ユーザー種別

dplyrは以下のユーザーを対象としています：

| ユーザー種別 | 説明 |
|-------------|------|
| 一般ユーザー | Rを使用してデータ分析を行うアナリスト |
| 上級ユーザー | カスタム関数やパッケージ開発を行う開発者 |
| データベース連携ユーザー | dbplyr等と連携してデータベース操作を行うユーザー |

### 1.6 対応環境

推奨環境：
- R >= 4.1.0
- RStudio（最新版推奨）
- 主要依存パッケージ: rlang, vctrs, tibble, tidyselect

---

## 2. インストール・環境設定

### 2.1 インストール方法

**CRANからのインストール（安定版）：**

```r
# dplyr単体でインストール
install.packages("dplyr")

# tidyverse全体をインストール（dplyrを含む）
install.packages("tidyverse")
```

**GitHubからのインストール（開発版）：**

```r
# pakパッケージを使用
install.packages("pak")
pak::pak("tidyverse/dplyr")
```

### 2.2 パッケージの読み込み

```r
# dplyrを読み込む
library(dplyr)

# または tidyverse 全体を読み込む
library(tidyverse)
```

### 2.3 バージョン確認

```r
# インストールされているバージョンを確認
packageVersion("dplyr")
```

---

## 3. 基本的な使い方

### 3.1 パイプ演算子

dplyrでは、パイプ演算子（`%>%` または `|>`）を使って、複数の操作を連結します。

```r
# パイプ演算子を使った処理の連結
data %>%
  filter(条件) %>%
  select(列名) %>%
  mutate(新列 = 計算式) %>%
  arrange(並び替え列)
```

### 3.2 サンプルデータセット

dplyrには練習用のサンプルデータセットが含まれています：

```r
# Star Warsキャラクターデータ
starwars

# 嵐の追跡データ
storms

# バンドメンバー（結合操作のデモ用）
band_members
band_instruments
```

### 3.3 データの表示

```r
# データの概要を表示
glimpse(starwars)

# 先頭数行を表示
head(starwars)

# tibbleとして表示
print(starwars)
```

---

## 4. 【STEP1】データの読み込みと確認

> **データ操作フローでの位置**: データ分析の最初のステップとして、データを読み込み、その構造と内容を把握します。

### 4.1 tibbleの作成

tibbleは、dplyrで使用する改良版のデータフレームです。

```r
# tibbleの作成
df <- tibble(
  id = 1:5,
  name = c("Alice", "Bob", "Carol", "Dave", "Eve"),
  score = c(85, 92, 78, 88, 95)
)

# tribble（行単位でのtibble作成）
df <- tribble(
  ~id, ~name, ~score,
  1,   "Alice", 85,
  2,   "Bob",   92,
  3,   "Carol", 78
)
```

### 4.2 データの変換

```r
# data.frameをtibbleに変換
df_tibble <- as_tibble(existing_dataframe)
```

### 4.3 データ構造の確認

```r
# データの概要を表示（glimpse）
glimpse(df)
# 出力例:
# Rows: 5
# Columns: 3
# $ id    <int> 1, 2, 3, 4, 5
# $ name  <chr> "Alice", "Bob", "Carol", "Dave", "Eve"
# $ score <dbl> 85, 92, 78, 88, 95
```

---

## 5. 【STEP2】データの抽出・フィルタリング

> **データ操作フローでの位置**: 必要なデータのみを抽出し、分析対象を絞り込みます。

### 5.1 行のフィルタリング（filter）

条件を満たす行のみを抽出します。

```r
# 単一条件
starwars %>%
  filter(species == "Human")

# 複数条件（AND）
starwars %>%
  filter(species == "Human", height > 180)

# 複数条件（OR）
starwars %>%
  filter(species == "Human" | species == "Droid")

# 条件を満たさない行を抽出
starwars %>%
  filter_out(is.na(height))
```

**注意点：**
- NAはFALSEとして扱われ、条件がNAの行は除外されます
- 複数条件をカンマで区切ると、AND条件として結合されます

### 5.2 列の選択（select）

必要な列のみを選択します。

```r
# 列名を指定して選択
starwars %>%
  select(name, height, mass)

# 列の範囲を指定
starwars %>%
  select(name:mass)

# 列を除外
starwars %>%
  select(-films, -vehicles, -starships)

# ヘルパー関数を使用
starwars %>%
  select(starts_with("h"))  # 'h'で始まる列

starwars %>%
  select(where(is.numeric))  # 数値型の列のみ
```

**主要なヘルパー関数：**
- `starts_with()`: 指定した文字列で始まる列
- `ends_with()`: 指定した文字列で終わる列
- `contains()`: 指定した文字列を含む列
- `matches()`: 正規表現にマッチする列
- `where()`: 条件関数を満たす列
- `everything()`: 残りの全ての列

### 5.3 行の位置指定選択（slice）

```r
# 先頭5行
starwars %>%
  slice_head(n = 5)

# 末尾5行
starwars %>%
  slice_tail(n = 5)

# 最小値を持つ行
starwars %>%
  slice_min(height, n = 3)

# 最大値を持つ行
starwars %>%
  slice_max(height, n = 3)

# ランダムサンプリング
starwars %>%
  slice_sample(n = 10)
```

### 5.4 重複の除去（distinct）

```r
# 特定の列の重複を除去
starwars %>%
  distinct(species)

# 全列で重複を除去
starwars %>%
  distinct()

# 重複除去時に他の列も保持
starwars %>%
  distinct(species, .keep_all = TRUE)
```

---

## 6. 【STEP3】データの変換・加工

> **データ操作フローでの位置**: データに新しい列を追加したり、既存の値を変換したりして、分析に適した形に加工します。

### 6.1 新規列の作成・変更（mutate）

```r
# 新しい列を作成
starwars %>%
  mutate(
    height_m = height / 100,
    bmi = mass / (height_m ^ 2)
  )

# 既存の列を上書き
starwars %>%
  mutate(height = height / 100)

# 列を削除
starwars %>%
  mutate(films = NULL)
```

**mutateのオプション：**
- `.before`/`.after`: 新列の挿入位置を指定
- `.keep`: 保持する列を制御（"all", "used", "unused", "none"）

```r
# 新列を特定の位置に挿入
starwars %>%
  mutate(height_m = height / 100, .after = height)
```

### 6.2 列名の変更（rename）

```r
# 列名を変更
starwars %>%
  rename(character_name = name)

# 関数を使って列名を変更
starwars %>%
  rename_with(toupper, starts_with("h"))
```

### 6.3 列の位置変更（relocate）

```r
# 列を先頭に移動
starwars %>%
  relocate(species, homeworld)

# 特定の列の後に移動
starwars %>%
  relocate(species, .after = name)
```

### 6.4 条件分岐（if_else, case_when）

```r
# 2値条件分岐
starwars %>%
  mutate(
    height_category = if_else(height > 180, "Tall", "Short")
  )

# 複数条件分岐
starwars %>%
  mutate(
    height_category = case_when(
      height > 200 ~ "Very Tall",
      height > 180 ~ "Tall",
      height > 160 ~ "Medium",
      TRUE ~ "Short"
    )
  )
```

### 6.5 複数列への一括操作（across）

```r
# 複数の数値列に同じ変換を適用
starwars %>%
  mutate(across(where(is.numeric), ~ . / 100))

# 特定の列に関数を適用
starwars %>%
  summarise(across(c(height, mass), mean, na.rm = TRUE))
```

---

## 7. 【STEP4】データの集計・分析

> **データ操作フローでの位置**: データをグループ化し、集約処理を行って分析結果を得ます。

### 7.1 グループ化（group_by）

```r
# 単一変数でグループ化
starwars %>%
  group_by(species)

# 複数変数でグループ化
starwars %>%
  group_by(species, homeworld)

# 一時的なグループ化（.by引数）
starwars %>%
  summarise(avg_height = mean(height, na.rm = TRUE), .by = species)
```

**注意点：**
- グループ化されたデータでは、後続の操作（summarise, mutate等）がグループごとに適用されます
- `ungroup()`でグループ化を解除できます

### 7.2 集約処理（summarise）

```r
# グループごとの集計
starwars %>%
  group_by(species) %>%
  summarise(
    count = n(),
    avg_height = mean(height, na.rm = TRUE),
    avg_mass = mean(mass, na.rm = TRUE)
  )
```

**主要な集計関数：**
- `n()`: 件数
- `mean()`: 平均
- `sum()`: 合計
- `min()`, `max()`: 最小・最大
- `sd()`: 標準偏差
- `first()`, `last()`: 最初・最後の値
- `n_distinct()`: ユニーク件数

### 7.3 カウント（count, tally）

```r
# グループごとの件数カウント
starwars %>%
  count(species)

# ソート付きカウント
starwars %>%
  count(species, sort = TRUE)

# 重み付きカウント
starwars %>%
  count(species, wt = mass)
```

### 7.4 並び替え（arrange）

```r
# 昇順で並び替え
starwars %>%
  arrange(height)

# 降順で並び替え
starwars %>%
  arrange(desc(height))

# 複数列での並び替え
starwars %>%
  arrange(species, desc(height))
```

**注意点：**
- NAは常に末尾に配置されます
- グループ化されたデータでは、グループ内でソートされます（.by_group = TRUEの場合）

---

## 8. 結合操作

### 8.1 ミューテーティング結合

2つのデータフレームを結合し、両方の列を含む結果を返します。

```r
# 左外部結合（xの全行を保持）
left_join(x, y, by = "key")

# 右外部結合（yの全行を保持）
right_join(x, y, by = "key")

# 内部結合（両方にある行のみ）
inner_join(x, y, by = "key")

# 完全外部結合（両方の全行を保持）
full_join(x, y, by = "key")
```

**結合キーの指定：**

```r
# 異なる列名で結合
left_join(x, y, by = c("x_key" = "y_key"))

# 複数キーで結合
left_join(x, y, by = c("key1", "key2"))
```

### 8.2 フィルタリング結合

```r
# セミ結合（yにマッチするxの行のみ）
semi_join(x, y, by = "key")

# アンチ結合（yにマッチしないxの行のみ）
anti_join(x, y, by = "key")
```

### 8.3 行・列の結合

```r
# 行方向に結合
bind_rows(df1, df2)

# 列方向に結合
bind_cols(df1, df2)
```

---

## 9. 集合演算

### 9.1 和集合・積集合・差集合

```r
# 和集合（重複なし）
union(x, y)

# 和集合（重複あり）
union_all(x, y)

# 積集合（両方に存在）
intersect(x, y)

# 差集合（xにのみ存在）
setdiff(x, y)

# 対称差（一方にのみ存在）
symdiff(x, y)
```

---

## 10. ウィンドウ関数

### 10.1 前後の値を参照（lead, lag）

```r
starwars %>%
  arrange(height) %>%
  mutate(
    prev_height = lag(height),
    next_height = lead(height),
    height_diff = height - lag(height)
  )
```

### 10.2 ランキング関数

```r
starwars %>%
  mutate(
    row_num = row_number(height),
    rank = min_rank(height),
    dense = dense_rank(height),
    percent = percent_rank(height),
    ntile = ntile(height, 4)
  )
```

**ランキング関数の違い：**
- `row_number()`: 一意のランク（同順位なし）
- `min_rank()`: 同順位あり、次の順位はスキップ
- `dense_rank()`: 同順位あり、次の順位はスキップしない
- `percent_rank()`: パーセンタイルランク（0-1）
- `ntile()`: n分位に分割

### 10.3 累積関数

```r
starwars %>%
  arrange(height) %>%
  mutate(
    cumulative_sum = cumsum(height),
    cumulative_mean = cummean(height),
    cumulative_max = cummax(height)
  )
```

---

## 11. 日常業務の流れ

本セクションでは、データ操作フローに沿った日常業務の流れを説明します。

```
データ操作フロー概要（再掲）
+------------------------------------------------------------------+
【STEP 1】データの読み込みと確認 -> 4章参照
    |
【STEP 2】データの抽出・フィルタリング -> 5章参照
    |
【STEP 3】データの変換・加工 -> 6章参照
    |
【STEP 4】データの集計・分析 -> 7章参照
    |
【STEP 5】結果の出力・保存
+------------------------------------------------------------------+
```

### 11.1 【分析者】STEP1: データの読み込み

データ分析の開始時に、対象データを読み込み確認します。

```r
# データを読み込み
library(dplyr)
data <- read_csv("data.csv") %>%
  as_tibble()

# データ構造を確認
glimpse(data)
```

### 11.2 【分析者】STEP2: データの抽出

分析に必要なデータを絞り込みます。

```r
# 必要な行・列を抽出
filtered_data <- data %>%
  filter(year >= 2020) %>%
  select(id, name, sales, region)
```

### 11.3 【分析者】STEP3: データの変換

分析に必要な加工を行います。

```r
# 新しい列を作成、値を変換
processed_data <- filtered_data %>%
  mutate(
    sales_category = case_when(
      sales > 10000 ~ "High",
      sales > 5000 ~ "Medium",
      TRUE ~ "Low"
    ),
    sales_normalized = sales / max(sales)
  )
```

### 11.4 【分析者】STEP4: データの集計

グループごとの集計を行います。

```r
# 集計処理
summary_data <- processed_data %>%
  group_by(region, sales_category) %>%
  summarise(
    count = n(),
    total_sales = sum(sales),
    avg_sales = mean(sales),
    .groups = "drop"
  ) %>%
  arrange(desc(total_sales))
```

---

## 12. よくある質問と対処法

### 12.1 基本操作に関するQ&A

**Q: filterで複数条件を指定する方法は？**

A: カンマ区切りでAND条件、`|`でOR条件を指定します。

```r
# AND条件
df %>% filter(a > 10, b < 5)

# OR条件
df %>% filter(a > 10 | b < 5)
```

**Q: NAを含む行を除外するには？**

A: `filter(!is.na(列名))` または `drop_na()` を使用します。

```r
df %>% filter(!is.na(height))
# または
df %>% tidyr::drop_na(height)
```

### 12.2 グループ操作に関するQ&A

**Q: group_byの後にungroupが必要？**

A: `summarise()`の後は自動的にグループが1段階解除されます。完全に解除するには`ungroup()`を使用するか、`.groups = "drop"`を指定します。

```r
df %>%
  group_by(a, b) %>%
  summarise(n = n(), .groups = "drop")
```

**Q: グループごとの上位N件を取得するには？**

A: `group_by()` と `slice_max()` を組み合わせます。

```r
df %>%
  group_by(category) %>%
  slice_max(value, n = 3)
```

### 12.3 結合操作に関するQ&A

**Q: 結合後に重複列が発生するのを防ぐには？**

A: `suffix`引数で接尾辞を指定するか、事前に不要な列を除外します。

```r
left_join(x, y, by = "key", suffix = c("_x", "_y"))
```

---

## 13. トラブルシューティング

### 13.1 エラーメッセージと対処法

| エラーメッセージ | 原因 | 対処法 |
|----------------|------|--------|
| `Column 'x' is not found` | 存在しない列を指定した | 列名を確認し、正しい名前を指定する |
| `object 'x' not found` | 変数が定義されていない | 変数名を確認する。文字列は引用符で囲む |
| `must return compatible types` | 型の不一致 | `if_else()`で同じ型を返すようにする |
| `Input must have size 1, not size n` | サイズの不一致 | グループ内で正しいサイズの値を返す |
| `Can't combine ... and ...` | 結合時の型不一致 | 型を揃えてから結合する |

### 13.2 よくあるトラブルと解決方法

**問題: filter()でNAが意図せず除外される**

解決: `filter()`はNAをFALSEとして扱います。NAを保持したい場合は明示的に条件を追加します。

```r
df %>% filter(x > 10 | is.na(x))
```

**問題: mutate()で計算結果が想定と異なる**

解決: グループ化されているかどうかを確認します。グループ化されていると、計算がグループごとに行われます。

```r
# グループの確認
group_vars(df)

# グループを解除
df %>% ungroup() %>% mutate(...)
```

**問題: summarise()で警告が出る**

解決: `.groups`引数を明示的に指定します。

```r
df %>%
  group_by(a, b) %>%
  summarise(n = n(), .groups = "drop")
```

### 13.3 サポートへの連絡方法

- **公式ドキュメント**: https://dplyr.tidyverse.org/
- **GitHub Issues**: https://github.com/tidyverse/dplyr/issues
- **Stack Overflow**: タグ `dplyr` で質問を検索・投稿
- **RStudio Community**: https://community.rstudio.com/

---

## 改訂履歴

| 版数 | 改訂日 | 改訂内容 |
|-----|--------|---------|
| 1.0 | 2026-02-19 | 初版作成 |

---

*本マニュアルは、dplyrパッケージのエンドユーザー向け業務運用マニュアルです。*
*パッケージの更新により、関数の仕様や動作が変更される場合があります。*
