Rによるデータ前処理実習

岩嵜 航 (Watal M. Iwasaki, PhD)
東北大学 生命科学研究科 進化ゲノミクス分野 特任助教
(Graduate School of Life Sciences, Tohoku University)
  1. 入門: 前処理とは。Rを使うメリット。Rの基本
  2. データ構造の処理: 抽出、集約、結合、変形など
  3. データ内容の処理: 数値、文字列、日時など
  4. 実践: 現実の問題に対処してみる
2019-12-21 東京医科歯科大学 M&Dタワー 情報検索室1

データ解析のおおまかな流れ

  1. コンピュータ環境の整備
  2. データの取得、読み込み
  3. 探索的データ解析
    • 前処理、加工 (地味。意外と重い。本実習の主題)
    • 可視化、仮説生成 (派手!楽しい!)
    • 統計解析、仮説検証 (みんな勉強したがる)
  4. 報告、発表
https://r4ds.had.co.nz/introduction.html

そもそもなぜ解析? 生の数字見ればよくない?

生データは情報が多すぎて関係性も何も見えない

print(diamonds)
      carat       cut color clarity depth table price     x     y     z
      <dbl>     <ord> <ord>   <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
    1  0.23     Ideal     E     SI2  61.5    55   326  3.95  3.98  2.43
    2  0.21   Premium     E     SI1  59.8    61   326  3.89  3.84  2.31
    3  0.23      Good     E     VS1  56.9    65   327  4.05  4.07  2.31
    4  0.29   Premium     I     VS2  62.4    58   334  4.20  4.23  2.63
   --                                                                  
53937  0.72      Good     D     SI1  63.1    55  2757  5.69  5.75  3.61
53938  0.70 Very Good     D     SI1  62.8    60  2757  5.66  5.68  3.56
53939  0.86   Premium     H     SI2  61.0    58  2757  6.15  6.12  3.74
53940  0.75     Ideal     D     SI2  62.2    55  2757  5.83  5.87  3.64

ダイヤモンド53,490個について10項目の値を持つデータセット

要約統計量(平均とか分散とか)を見てみる

まあ何となく分かった気になる

dplyr::summarize_if(diamonds, is.numeric, mean)
      carat   depth    table  price        x        y        z
      <dbl>   <dbl>    <dbl>  <dbl>    <dbl>    <dbl>    <dbl>
1 0.7979397 61.7494 57.45718 3932.8 5.731157 5.734526 3.538734
dplyr::summarize_if(diamonds, is.numeric, sd)
      carat    depth    table   price        x        y         z
      <dbl>    <dbl>    <dbl>   <dbl>    <dbl>    <dbl>     <dbl>
1 0.4740112 1.432621 2.234491 3989.44 1.121761 1.142135 0.7056988
summary(diamonds)
     carat               cut        color        clarity          depth           table      
 Min.   :0.2000   Fair     : 1610   D: 6775   SI1    :13065   Min.   :43.00   Min.   :43.00  
 1st Qu.:0.4000   Good     : 4906   E: 9797   VS2    :12258   1st Qu.:61.00   1st Qu.:56.00  
 Median :0.7000   Very Good:12082   F: 9542   SI2    : 9194   Median :61.80   Median :57.00  
 Mean   :0.7979   Premium  :13791   G:11292   VS1    : 8171   Mean   :61.75   Mean   :57.46  
 3rd Qu.:1.0400   Ideal    :21551   H: 8304   VVS2   : 5066   3rd Qu.:62.50   3rd Qu.:59.00  
 Max.   :5.0100                     I: 5422   VVS1   : 3655   Max.   :79.00   Max.   :95.00  
                                    J: 2808   (Other): 2531                                  
     price             x                y                z         
 Min.   :  326   Min.   : 0.000   Min.   : 0.000   Min.   : 0.000  
 1st Qu.:  950   1st Qu.: 4.710   1st Qu.: 4.720   1st Qu.: 2.910  
 Median : 2401   Median : 5.700   Median : 5.710   Median : 3.530  
 Mean   : 3933   Mean   : 5.731   Mean   : 5.735   Mean   : 3.539  
 3rd Qu.: 5324   3rd Qu.: 6.540   3rd Qu.: 6.540   3rd Qu.: 4.040  
 Max.   :18823   Max.   :10.740   Max.   :58.900   Max.   :31.800  
                                                                   

平均値ばかり見て可視化を怠ると構造を見逃す

https://www.autodeskresearch.com/publications/samestats/

データ可視化の重要性

情報の整理 → 正しい解析・新しい発見・仮説生成

plot of chunk simplify-diamonds

データ可視化の重要性

情報の整理 → 正しい解析・新しい発見・仮説生成

https://r4ds.had.co.nz/explore-intro.html

可視化だいじ。わかった。
でも「データ分析に費やす労力の8割は前処理」だって?

機械処理しやすい形 vs 人が読み書きしやすい形

作図や解析に使えるデータ形式はほぼ決まってる
ggplot(data, ...), glm(..., data, ...), …
出発点となるデータはさまざま
実験ノート、フィールドノート、データベース、…

Happy families are all alike;
every unhappy family is unhappy in its own way
— Leo Tolstoy “Anna Karenina”

tidy datasets are all alike,
but every messy dataset is messy in its own way
— Hadley Wickham

整然データ tidy data

  • 縦1列は1つの変数
  • 横1行は1つの観測
  • 1セルは1つの
print(diamonds)
      carat       cut color clarity depth table price     x     y     z
      <dbl>     <ord> <ord>   <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
    1  0.23     Ideal     E     SI2  61.5    55   326  3.95  3.98  2.43
    2  0.21   Premium     E     SI1  59.8    61   326  3.89  3.84  2.31
    3  0.23      Good     E     VS1  56.9    65   327  4.05  4.07  2.31
    4  0.29   Premium     I     VS2  62.4    58   334  4.20  4.23  2.63
   --                                                                  
53937  0.72      Good     D     SI1  63.1    55  2757  5.69  5.75  3.61
53938  0.70 Very Good     D     SI1  62.8    60  2757  5.66  5.68  3.56
53939  0.86   Premium     H     SI2  61.0    58  2757  6.15  6.12  3.74
53940  0.75     Ideal     D     SI2  62.2    55  2757  5.83  5.87  3.64

整然データ tidy data   vs   雑然データ messy data

縦1列は1つの変数
横1行は1つの観測
1セルは1つの値

整然データ tidy data   vs   雑然データ messy data

縦1列は1つの変数
横1行は1つの観測
1セルは1つの値

整然データ tidy data   vs   雑然データ messy data

縦1列は1つの変数
横1行は1つの観測
1セルは1つの値

整然データ tidy data   vs   雑然データ messy data

縦1列は1つの変数
横1行は1つの観測
1セルは1つの値

整然データのご利益

x軸、y軸、色分け、パネル分けなどを列の名前で指定して簡単作図:

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(mapping = aes(color = color, size = clarity)) +
  facet_wrap(~ cut)

plot of chunk aes-map

本日2時限目の話題: データ変形・整形

VADeaths
      Rural Male Rural Female Urban Male Urban Female
50-54       11.7          8.7       15.4          8.4
55-59       18.1         11.7       24.3         13.6
60-64       26.9         20.3       37.0         19.3
65-69       41.0         30.9       54.6         35.1
70-74       66.0         54.3       71.1         50.0

↓ 作図・解析で使いやすい整然データに変形

   lbound ubound region    sex death
    <int>  <int>  <chr>  <chr> <dbl>
 1     50     54  Rural   Male  11.7
 2     50     54  Rural Female   8.7
 3     50     54  Urban   Male  15.4
 4     50     54  Urban Female   8.4
--                                  
17     70     74  Rural   Male  66.0
18     70     74  Rural Female  54.3
19     70     74  Urban   Male  71.1
20     70     74  Urban Female  50.0

本日1時限目の話題

データ解析全体の流れ。可視化だいじ

作図・解析の前にデータの前処理が必要

⬜ なぜRを使うのか?

  • 退屈な作業は機械にやらせてラクしよう
  • 無料で誰でも使える

⬜ Rの基礎

Rを使わなかった場合の悲劇の例

動物園の混合展示で、各種動物はどのように分布・行動しているか、
それらを決める要因は何か。膨大な観察データに基づく超大作卒論。

生データ: ここはまだそんなに悪くない

週に1回、各個体の位置と行動を種ごとのファイルに記録。
タブは個体、A列B列はXY座標でそれ以降の列は行動、各行はある時刻。

マウスとコピペを駆使して条件ごとに複製・集計

ちゃんと合ってるのかな… ファイルもタブもたくさん…

マウスとコピペを駆使して条件ごとに複製・集計

ちゃんと合ってるのかな… ファイルもタブもたくさん…

目と手で数え、濃淡を計算し、画像ソフトで塗る

泣きながら何十枚も…。無料期間が終わって今は使えない…。

目作業・手作業 = シーシュポスの岩

Punishment sisyph.jpg
https://en.wikipedia.org/wiki/Sisyphus
  • 膨大な単純作業がそもそもツラい
  • 人間だもの、ミスは防ぎきれない
  • ミスを減らすためのチェックもツラい
  • ミスを発見 → 初めからやり直し
  • 新データ追加 → 初めからやり直し
  • 熟練してもツラいまま
  • そのときの自分しかできない、記録に残らない
    検証のしようがない
  • 卒論なら努力賞でいいかもしれないけど、科学の手続きとしては問題。

プログラミングで大量のファイルを捌く

先の例に負けず生データはどっさり。でも頑張るのは機械。

Iwasaki, Kijima, Innan (2019)

こんな感じの図もRでラクラク描けるよ


Iwasaki and Innan (2017)

Rにやらせて楽しよう

  • 規則性のある退屈な仕事は人間よりも機械のほうが得意。
  • 一度書いたプログラムは、データが変わっても使いまわせる
  • 自分以外の人でも再現・検証できる
  • きれいな図を簡単に描ける
  • 部分的に改変しながらいろんな解析を試せる。
    仮説検証 だけでなく、 仮説生成(探索的データ解析) もやりやすい
  • やれば上達する。どんどん楽になる!
https://r4ds.had.co.nz/introduction.html

Rとは

統計解析と作図の機能が充実したプログラミング言語・環境

https://cran.r-project.org/
クロスプラットフォーム
Linux, Mac, Windows で動く
オープンソース
永久に無償で、すべての機能を使える。
集合知によって常に進化している。
コミュニティ
相談できる人や参考になるウェブサイトがたくさん見つかる。

他のプログラミング言語でもいいよ:
PythonとかJuliaとか。

本日1時限目の話題

データ解析全体の流れ。可視化だいじ

作図・解析の前にデータの前処理が必要

なぜRを使うのか?

⬜ Rの基礎

  • R環境のセットアップ
  • Rとの対話
  • 表形式データの読み書き
  • Rパッケージ
  • エラーや疑問への対処

R環境のセットアップ

R本体
コマンドを解釈して実行するコア部分。
よく使われる関数なども標準パッケージとして同梱。
RStudio Desktop
Rをより快適に使うための総合開発環境 (IDE)
必須じゃないけど便利なので結構みんな使ってる。

RStudioを起動してみよう

そしてコンソールでRと会話してみよう

“Project” を新規作成する

File → New Project… → New Directory → ~/project/r-training-2019

Rスクリプトに書いてから、実行する

File → New File → R script

Rスクリプトに書いてから、実行する

File → New File → R script

Rスクリプトに書いてから、実行する

テキスト選択: shift
コンソールに送る: ctrlreturn

Rスクリプトをプロジェクト内に保存: commands

スクリプト、データ、結果は分けておくのが良い。

r-training-2019/           # プロジェクトの最上階
├── data/                  # 元データを置くところ
│   ├── iris.tsv
│   └── diamonds.xlsx
├── r-training-2019.Rproj  # これダブルクリックでRStudioを起動
├── hello.R
├── output/                # 結果の出力先
│   ├── iris-petal.png
│   └── iris-summary.tsv
├── transform.R            # データ整理・変形のスクリプト
└── visualize.R            # 作図のスクリプト

プロジェクト最上階を作業ディレクトリとし、
ファイル読み書きの基準にする。(後で詳しく)

毎回まっさらなワークスペースで始める設定

RStudio → Preferences   command,
Tools → Global options
“Restore …” のチェックを外して、 “Save …” のNeverを選択

https://r4ds.had.co.nz/workflow-projects.html

Rと接する上での心構え

エラー文を恐れない
熟練プログラマでも頻繁にエラーを起こす。
エラーはRからのメッセージ。意図を読み取って修正しよう。
困ったらウェブ検索
あなたの問題は全世界のRユーザーが既に通った道。
日本語で、英語で、エラー文そのもので検索すれば解決策に当たる。
それでも分からなかったら r-wakalang で相談しよう。
(コードの)コピペ推奨
打ち間違いによるエラーを防げるし、早い。
ネット上で見つけたコードもまずはコピペしてから自分用に改変。
(ただし、ライセンスには注意…)

変数/オブジェクトを作ってみよう

x = 42       # Create x
x            # What's in x?
[1] 42
y = "24601"  # Create y
y            # What's in y?
[1] "24601"
x + y        # Error!
Error in x + y: non-numeric argument to binary operator

変数/オブジェクトの型

class(x)
[1] "numeric"
is.numeric(x)
[1] TRUE
is.character(x)
[1] FALSE
as.character(x)
[1] "42"

さっき作った y にも同じ関数を適用してみよう。

変数/オブジェクトの型

  • NULL: 空っぽ
  • vector: 基本型。一次元の配列。
    • logical: 論理値 (TRUE or FALSE)
    • numeric: 数値 (整数 42L or 実数 3.1416)
    • character: 文字列 ("historgram.png")
    • factor: 因子 (文字列っぽいけど微妙に違う)
    • ↑それぞれに欠損値 NA も定義されてる
  • matrix: 二次元の行列。vector同様、全要素が同じ型。
  • list: 異なる型でも詰め込める太っ腹ベクトル。
  • data.frame: 同じ長さのベクトルを並べた長方形のテーブル。重要。
    tibble とか tbl_df と呼ばれる亜種もあるけどほぼ同じ。

vector: 一次元の配列

1個の値でもベクトル扱い。
同じ長さ(または長さ1)の相手との計算が得意。

x = c(1, 2, 9)  # 長さ3の数値ベクトル
x + x           # 同じ長さ同士の計算
[1]  2  4 18
y = 10          # 長さ1の数値ベクトル
x + y           # 長さ3 + 長さ1 = 長さ3 (それぞれ足し算)
[1] 11 12 19
sqrt(x)         # square root
[1] 1.000000 1.414214 3.000000
# We don't have to write for-loop like this
z = c(0, 0, 0)
for (i in seq_len(3)) {
  z[i] = sqrt(x[i])
}

data.frame: 長方形のテーブル (重要!)

iris はアヤメ属3種150個体に関する測定データ。
Rに最初から入ってて、例としてよく使われる。

print(iris)
    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
           <dbl>       <dbl>        <dbl>       <dbl>     <fct>
  1          5.1         3.5          1.4         0.2    setosa
  2          4.9         3.0          1.4         0.2    setosa
  3          4.7         3.2          1.3         0.2    setosa
  4          4.6         3.1          1.5         0.2    setosa
 --                                                            
147          6.3         2.5          5.0         1.9 virginica
148          6.5         3.0          5.2         2.0 virginica
149          6.2         3.4          5.4         2.3 virginica
150          5.9         3.0          5.1         1.8 virginica

150行5列: 長さ150の数値ベクトル4本と因子ベクトル1本。

data.frameを眺める

概要を掴む:

head(iris, 6)   # 先頭だけ見てみる
nrow(iris)      # 行数: Number of ROWs
ncol(iris)      # 列数: Number of COLumns
names(iris)     # 列名
summary(iris)   # 要約
View(iris)      # RStudioで閲覧
str(iris)       # 構造が分かる形で表示
tibble [150 × 5] (S3: tbl_df/tbl/data.frame)
 $ Sepal.Length: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

ほかのデータもいろいろ見てみよう, e.g., mtcars, quakes, data()

data.frameを眺める

部分的なdata.frameを取得する:

iris[2, ]                  # 2行目
iris[2:5, ]                # 2行目から5行目まで
iris[, 3:4]                # 3-4列目
iris[2:5, 3:4]             # 2-5行目, 3-4列目

vectorとして取得する:

iris[[3]]                  # 3列目
iris$Petal.Length          # Petal.Length列
iris[["Petal.Length"]]     # Petal.Length列
iris[["Petal.Length"]][2]  # Petal.Length列の2番目

結果がdata.frameになるかvectorになるか微妙:

iris[, 3]                  # 3列目
iris[, "Petal.Length"]     # Petal.Length列
iris[2, 3]                 # 2行目3列目
iris[2, "Petal.Length"]    # 2行目Petal.Length列

行 (row), 列 (column) の憶え方

data.frameの新規作成

同じ長さの 列(column) vector を結合して作る:

x = c(1, 2, 3)
y = c("A", "B", "C")
mydata = data.frame(x, y)
print(mydata)
  x y
1 1 A
2 2 B
3 3 C

data.frameの読み書き

  • readxlパッケージを使えば .xlsx ファイルも読める、けど

  • カンマ区切り(CSV)とかタブ区切り(TSV)のテキストが無難。

  • ファイル名は作業ディレクトリからの相対パスで指定。

    install.packages("readr") # R標準の read.table() とかは難しいので
    library(readr)            # パッケージのやつを使うよ
    readr::write_tsv(iris, "data/iris.tsv")   # 書き出し
    iris2 = readr::read_tsv("data/iris.tsv")  # 読み込み
    
  • 現在の作業ディレクトリとその中身を確認しておこう:

    getwd()               # Get Working Directory
    list.files(".")       # List files in "."
    list.files("data")    # List files in "./data"
    

R組み込みデータや自作データを読み書きしてみよう

Rパッケージ

便利な関数やデータセットなどをひとまとめにしたもの。

Standard Packages
Rの標準機能。何もしなくても使用可能
Contributed Packages
有志により開発され、 CRAN にまとめて公開されている。
要インストール。使う前に読み込むおまじないが必要。
install.packages("readr")  # 一度やればOK
library(readr)             # 読み込みはRを起動するたびに必要
update.packages()          # たまには更新しよう
素のRも覚えきってないのにいきなりパッケージ?
大丈夫。誰も覚えきってない。
パッケージを使わないR作業 = 火もナイフも使わない料理

tidyverse

Rでデータを上手に扱うためのパッケージ群

install.packages("tidyverse")
library(tidyverse)
# 関連パッケージが一挙に読み込まれる
  • 統一的な使い勝手
  • 暗黙の処理をなるべくしない安全設計
  • シンプルな関数を繋げて使うデザイン
https://r4ds.had.co.nz/introduction.html

便利なパッケージはほかにもたくさん

  • readxl: エクセル形式の読み込み
  • stringr: 文字列の処理
  • Bioconductor: バイオインフォマティクス関連
  • igraph: グラフ(ネットワーク)関連
  • rgl: 3Dの作図
  • R Markdown: Rコマンドと結果を埋め込んだPDFやHTMLを作る。
    この発表スライドもそうやって作った。
    研究ノート、レポート作成、共同研究者への報告にも便利!

疑問やエラーの解決方法

  • RStudio内にヘルプを表示: ?sum, help.start()
  • 変数の構造を確かめる: str(iris), attributes(iris)
  • エラー文をちゃんと読む: No such file or directory
  • パッケージの公式ドキュメントをちゃんと読む
  • パッケージ名やエラー文をコピペしてウェブ検索
    StackOverflow や個人サイトに解決策
  • 身近な経験者に訊く
  • Slackの r-wakalang で質問を投稿する。
    内容によってチャンネルを選ぶ: #r_beginners, #ggplot2
  • 状況を再現できる小さな例 (reprex) を添えて質問すると回答を得やすい。

本日1時限目の話題

✅ データ解析全体の流れ。可視化だいじ。

✅ 作図・解析の前にデータの前処理が必要

✅ なぜRを使うのか?

✅ Rの基礎

  • まずRスクリプトに書いてから、コンソールで実行
  • “Project"構造を意識してファイルを配置
  • 変数には型がある: 数値、文字列、データフレーム
  • 便利なパッケージを使おう
  • ヘルプはそこら中に転がってる

参考、協力

R for Data Science — Hadley Wickham & Garrett Grolemund
Website, Book
日本語版書籍(Rではじめるデータサイエンス)
整然データとは何か — @f_nisihara
https://speakerdeck.com/fnshr/zheng-ran-detatutenani
https://id.fnshr.info/2017/01/09/tidy-data-intro/
過去の講義資料
Rにやらせて楽しよう — データの可視化と下ごしらえ」 岩嵜航 2018
「Rを用いたデータ解析の基礎と応用」石川由希 2019 名古屋大学
Hands-on R Lecture for Makino Lab」 岩嵜航 2019 東北大学
壮絶な手作業の例
総研大の学生 M. S. さん (現在はRユーザー)