Ma.03.「前処理」等復習用(Tidyverse的)
このページは、演習で活用した前処理に必要なRのTIPS(技)をまとめました。
分析のワークフローに沿って、各ステップの「目的」と「コピーして使えるコード」を紹介しています。
演習で使った資料を参考に生成AIの助けを得ながら公開しました。
1. 【準備】分析環境のセットアップ
分析を始める前の「おまじない」です。過去の作業内容をクリアにし、必要な道具(パッケージ)を読み込みます。
目的
- 過去に実行した変数(オブジェクト)をRのメモリからすべて削除し、クリーンな状態で作業を開始する。
tidyverseをはじめとする、データハンドリングや可視化に必要なパッケージを読み込む。
コピー用コード
# --- 環境のリセット --- 警告:現在Rのメモリ上にあるものがすべて消えます
rm(list=ls())
# --- 基本パッケージの読み込み ---
library(tidyverse)
library(readxl) #エクセルを読み込む
library(summarytools) # データの要約(記述統計)を素早く確認する
library(janitor) # 必要時のみ、変数名を自動でクリーンにするため (例: "Q1. 氏名" -> "q1_shimei")
library(naniar) # 必要時のみ、欠損値(NA)を視覚化するため
# --- RStudioのTIPS:セクション管理 ---
# 【 Ctrl + Shift + R 】で、目次作成&スクリプトを折り畳める
# 【 Ctrl + Shift + C 】で、スクリプト内のコメントをコメント化
2. 【読込】データのインポートと「健康診断」
データをRに読み込み、その「第一印象」と構造を確認します。
目的
- ExcelやCSVなどのファイルをRのデータフレーム(
df)として正しく読み込む。 - データが期待通りに読み込めているか(文字化け、型の違いなど)を素早く確認する。
- Rで扱いにくい変数名(日本語、スペース、記号など)を、扱いやすい形式に自動変換する。
コピー用コード
# --- Excelファイルの読み込み ---(基本はReadrを"右上"から扱うことを推奨しています)
# ※パス(/data/...)やシート名(YYYY)、スキップ行数(AA)は適宜変更
df <- read_excel("/data/XXXXXXXXX.xls",
sheet = "YYYY", # シート名を指定
skip = 10, # 最初の10行を読み飛ばす
col_names = TRUE) # 読み込んだ範囲の1行目を変数名とする
# --- データの「第一印象」を確認 ---
head(df) # 最初の6行を表示
tail(df) # 最後の6行を表示
# --- データの「構造(型)」を確認 ---
glimpse(df) # 変数名、型、値の例を一覧
# --- 変数名をクリーンにする (janitor) ---
df_clean <- clean_names(df)
# --- 難解な変数名を一覧表示(コピー用) ---
# 変数名が長い、日本語で入力が面倒なときは、names() で一覧を表示し、コンソールから変数名をコピーして使います
names(df)
3. 【把握】欠損値(NA)の確認
本格的な前処理の前に、データの「クセ」(特に欠損値)を掴みます。
目的
- データ全体にどの程度欠損値(NA)があるかを視覚的に把握する。
- 「欠損値が特に多い回答者(行)」や「欠損値が特に多い質問項目(列)」を特定する。
コピー用コード
# --- 欠損値の視覚化 (naniar) ---
# データが巨大な場合、vis_miss() は時間がかかるため、
# 5%程度をランダムサンプリングして傾向を掴みます
df_sample <- df %>%
slice_sample(prop = 0.05)
vis_miss(df_sample)
# --- 欠損値の多い「回答者(行)」を特定 ---
# pct_miss(欠損率)が高い順に並べ替えて上位を表示
miss_case_summary(df) %>%
arrange(desc(pct_miss)) %>%
head()
4. 【処理】データの前処理と変数作成
分析の目的に合わせてデータを加工する、最も重要なステップです。dplyr パッケージの mutate() 関数が主役です。
A. 値の変換と欠損値処理
回答の選択肢(例: 1=そう思う, 2=そう思わない)を、分析しやすい数値(例: 1, 0)に変換したり、特定の回答(例: 8=わからない)を欠損値(NA)として扱ったりします。
# --- 1. 単純な計算 (例: 1〜5点 -> 0〜4点に) ---
df_new <- df %>%
mutate(q1_1 = q1_1 - 1)
# --- 2. 複数の変数を一括変換 (across) ---
# "q3s" から始まるすべての変数(q3s1, q3s2...)を対象に、一括で「-1」する
df_new <- df %>%
mutate(across(starts_with("q3s"),
~ .x - 1)) # .x は「その変数自身」を指す
# --- 3. 逆転項目の処理 (across) ---
# 5点満点(1〜5)の項目を逆転させる & 0に意味をもたせる(5点→0点にしたい & 1点→4点にしたい )
# (逆転の処理は、ほぼ、【最大値+1 -.x】だと思いますが、今回みたいに違うケースもあります)
# ので、今回は・・・と毎回考える、(今回:最大 - 元の値 → 5 - .x)
df_new <- df %>%
mutate(across(starts_with("q40s"),
~ 5 - .x))
# --- 4. 特定の値を欠損値(NA)に変換 (na_if) ---
# 質問項目n_q36で「8 = わからない」と回答した人を NA にする
df_new <- df %>%
mutate(n_q36 = na_if(n_q36, 8))
B. 新しい変数の作成(合計点など)
複数の質問項目を足し合わせて、合計点(尺度得点)などを作ります。
# --- 合計点の作成 (rowSums + across) ---
# "q3s" から始まるすべての変数の「行ごと(row)」の合計(Sums)を計算し、
# 新しい変数 `q3` を作成する
# na.rm = TRUE は、計算途中にNAがあってもそれを除外して合計するオプション
df_new <- df %>%
mutate(q3 = rowSums(across(starts_with("q3s")), na.rm = TRUE))
C. 型の変換 (as.numeric)
数値として扱いたい変数が、文字型 (character) になっている場合に修正します。
# 'work' 変数を強制的に数値型(numeric)に変換
df_new <- df %>%
mutate(work = as.numeric(q15s1))
D. カテゴリ変数の作成 (Factor化)
分析(特に ggplot や aov)で必須の作業です。数値(1, 2)に「男性, 女性」といったラベルを付けたり、順序を持たせたりします。
# --- 1. 単純なFactor化 (factor) ---
# sex変数の「1」に "male"、「2」に "female" というラベルを付ける
df_new <- df %>%
mutate(sex = factor(sex,
levels = c(1, 2),
labels = c("male", "female")))
# --- 2. 順序付きFactor化 (ordered) ---
# nensyu変数(1〜7)が「順序」を持つこと(1 < 2 < ... < 7)をRに教える
df_new <- df %>%
mutate(nensyu = ordered(n_q36,
levels = 1:7)) # 1:7 は c(1,2,3,4,5,6,7) と同じ
E. 条件分岐による変数作成 (if_else, case_when)
最もよく使う「技」です。ある条件に基づいて新しい変数を作成します。
# --- 2分岐 (if_else) ---
# 「もし kessler6 が 13以上 なら 1 を、 そうでなければ 0 を」
# 新しい変数 k6_h (high群) を作成
df_new <- df %>%
mutate(k6_h = if_else(kessler6 >= 13, 1, 0))
# --- 2分岐 + Factor化 (if_else + factor) ---
# if_else で 0/1 に分けた後、すぐに factor() でラベル付けするコンボ技
df_new <- df %>%
mutate(
k6_h = if_else(kessler6 >= 13, 1, 0),
k6_hf = factor(k6_h,
levels = c(0, 1),
labels = c("low", "high"))
)
# --- 多分岐 (case_when) ---
# 複数の「もし〜なら」を上から順に判定する
# 「条件式 ~ 結果」 のペアで書く
df_new <- df %>%
mutate(
age_g = case_when(
age_num >= 65 ~ 3, # 65歳以上なら 3
age_num >= 40 ~ 2, # (65歳未満で) 40歳以上なら 2
age_num <= 39 ~ 1, # (40歳未満で) 39歳以下なら 1
TRUE ~ NA_real_ # 上記すべてに当てはまらない場合 (念のため)
),
age_g = factor(age_g, # その変数ごとFactor化
levels = c(1, 2, 3),
labels = c("若年層", "中年層", "高齢層"))
)
# --- 多分岐 + %in% (case_when) ---
# %in% は「c(...) のどれかに当てはまるなら」という便利な記法
df_new <- df %>%
mutate(
work = as.numeric(q15s1), # 先に数値化
job_group = case_when(
work %in% c(1, 3, 4) ~ 1, # 正規・役員・自営
work %in% c(2, 5) ~ 2, # 非正規・パート
work %in% c(6, 7) ~ 3, # 学生・専業主婦
work %in% c(8, 9) ~ 4, # 無職・その他
TRUE ~ NA_real_
),
job_group = factor(job_group,
levels = c(1, 2, 3, 4),
labels = c("正規", "非正規", "学生主婦", "無職"))
)
F. 変数名の変更と選択 rename & select
扱いにくい変数名を変更したり、特定の変数群だけを抜き出したりします。
# --- 1. 変数名の変更 (rename) ---
# rename(新しい名前 = "古い名前")
# ※ `dplyr::rename` と明記すると他パッケージとの衝突を防げます
df_new <- df %>%
dplyr::rename(jisatu = 'I910803_自殺率(人口10万対)【‐】')
df_new <- df_new %>%
dplyr::rename(area_code = `地域コード`) # ` ` で囲む
# --- 特定の変数群を文字列で作成 (paste0) ---
# "q3s1_1", "q3s2_1", ..., "q3s11_1" という変数名のリストを自動作成
vars <- paste0("q3s", 1:11, "_1")
# --- 上で 作成したリストで変数を抽出 (select + all_of) ---
# vars リストに含まれる変数「すべて(all_of)」を抜き出した新dfを作成
df_selected <- df %>%
select(all_of(vars))
G. 行のフィルタリング (filter)
分析に不要な行(例: 全国平均の行)を除外します。
# --- 特定の条件で行を絞り込む (filter) ---
# area_code が "R00000"(全国平均)「ではない」行だけを残す
※ dplyr::filter と明記しているのは、僕のR環境ではdplyrを明示しないと働いてくれないからです。(原因模索中)
df_filtered <- df %>%
dplyr::filter(area_code != "R00000")
H. 行・列の削除 (逆filter、逆Select、逆Slice)
Gと同様ではありますが、「これを選ぶ」よりも、「これ以外を選ぶ」方が効率的な場面がよくあります。
1. 逆セレクト (特定の列を「除く」)
select() で変数(列)名の前に - (マイナス記号) を付けると、その列以外をすべて選択できます。
分析に使わないID列や自由記述欄など、特定の列だけを一時的に除外したい。
# --- 1. 特定の1列を除く ---
# 'free_comment' 列「以外」をすべて選択
df_new <- df %>%
select( - free_comment)
# --- 2. 複数の列を除く ---
# 'id' と 'timestamp' の2列「以外」をすべて選択
df_new <- df %>%
select(-c(id, timestamp))
# --- 3. 条件で除く (starts_withなど) ---
# "q3s" から始まるすべての変数「以外」を選択
# ※ヘルパー関数の場合は `!` を使う
df_new <- df %>%
select(!starts_with("q3s"))
2. 逆フィルター (特定の行を「除く」)
filter() で条件式の全体を !() で囲むか、判定の前に ! を付けると、その条件に当てはまらない行(=それ以外)を抽出できる。
特定の条件(例: NA、特定のグループ、外れ値)に当てはまる行以外を抽出するときに利用できます。
# --- 1. 特定の値「以外」 ( != と同じ) ---
# area_code が "R00000"(全国平均)「ではない」行
# これは filter(area_code != "R00000") と全く同じ意味
df_filtered <- df %>%
dplyr::filter(!(area_code == "R00000"))
# --- 2. NA「以外」を抽出 (is.na) ---
# 'income' が NA「ではない」行だけを残す(=欠損値の完全除外)
df_complete <- df %>%
dplyr::filter(!is.na(income))
# --- 3. グループ「以外」を抽出 (%in%) ---
# 'age_g' が c(1, 3)(若年層と高齢層)「ではない」行(=中年層のみ)を抽出
# %in% の前に ! を付ける
df_middle_age <- df %>%
dplyr::filter(!age_g %in% c(1, 3))
3. 逆スライス (特定の行番号を「除く」)
slice()で行番号の前に-(マイナス)を付けると、その行番号以外をすべて選択できる。
データの先頭X行(例: 注釈やヘッダーが誤って含まれた行)だけを除外したい。
データの最後の行(例: 合計行など)を除外したい。ときに活用できます。
# --- 1. 最初の5行「以外」をすべて選択 ---
# -c(1:5) は「1行目から5行目まで」を「除く」という意味
df_new <- df %>%
slice(-c(1:5))
# --- 2. 特定の1行を除く ---
# 3行目だけを除外
df_new <- df %>%
slice(-3)
# --- 3. 最後の1行を除く ---
# n() は「総行数」(つまり最後の行)を指す
df_new <- df %>%
slice(-n())
5. 【結合】複数データのマージと集計
複数のデータフレーム(例: 個人データと、都道府県データ)を結合(マージ)したり、グループごと(例: 県ごと)に集計したりします。
A. データの結合 (left_join)
left_join(df_A, df_B, by = "キー変数") は、「df_A(左側)を基準にして、df_B(右側)からキー変数が一致する行の情報をくっつける」という意味です。
# --- 準備:結合される側(jisatu)のキー変数を準備 ---
# 例: `地域コード` (01000) から `tiiki` (01) を作成
jisatu_df <- jisatu_df %>%
mutate(tiiki = as.numeric(`地域コード`) * 0.001)
# --- 1. 基本的な結合 (left_join) ---
# ssdse (基準) に jisatu_df (加える) を "tiiki" をキーにして結合
join_df <- left_join(ssdse, jisatu_df,
by = "tiiki",
suffix = c("_x", "_y")) # 同名変数があった場合の接尾辞
# --- 2. 必要な変数だけ選んで結合 (TIPS) ---
# Bのdf(tfr_df)から必要な変数(tfr, tfr_f)だけをAのdf(naiman)に結合する
# (1) Bのdfから必要な変数だけ抜き出す
tfr_selected <- join_df %>%
dplyr::select(tfr, tiiki)
# (2) Aのdfに (1) を結合する
naiman_ketsugo <- left_join(naiman, tfr_selected,
by = "tiiki")
B. グループごとの集計 (group_by + summarize)
個人(行)のデータを、特定のグループ(例: 都道府県)ごとに集計し、新しいデータフレームを作成します。
# --- グループ集計 (group_by + summarize) ---
# (1) dfを `pref_name`(都道府県名)でグループ化
# (2) 新しい変数として、incomeの平均値、q3の平均値、N(人数)を計算
df_summary <- df %>%
group_by(pref_name) %>%
summarise(
mean_income = mean(income, na.rm = TRUE), # NAを除外して計算
mean_q3 = mean(q3, na.rm = TRUE),
N = n()
)
6. 【保存】中間データの保存
時間のかかった前処理の結果を保存し、いつでも作業を再開できるようにします。
目的
- 前処理済みのクリーンなデータ(
df_newなど)をファイルに保存する。 - 次回以降、
read_excelや前処理のステップをすべて飛ばし、分析用データを瞬時に読み込む。
コピー用コード
# --- R専用形式 (.rds) で保存 ---
# .rds は .csv と違い、Factorのラベル情報などもそのまま保存できるため推奨
write_rds(df_new, file = "preprocessed_data.rds")
# --- 保存した .rds ファイルを読み込む ---
# 次回作業時は、この1行だけで前処理済みのデータを読み込める
rm(list=ls()) # 念のため環境をクリアにしてから
df_analysis <- read_rds("preprocessed_data.rds")

