初心者セッション
〜データハンドリング編〜

y__mattu

2019/4/13 Tokyo.R #77

はじめに

誰?

icon

著書

R ユーザのための RStudio[実践]入門
− tidyverse によるモダンな分析フローの世界−

rstudiobook

通称: 「宇宙本

  1. RStudio 入門(@y__mattu)
  2. スクレイピングによるデータ取得(@y__mattu)
  3. dplyr を中心としたデータハンドリング(@yutannihilation)
  4. ggplot2 による可視化(@kyn02666)
  5. R Markdown によるレポーティング(@kazutan)

データハンドリング

データ分析の流れ

やること

  • 絞り込み(列・行)
  • 新しい変数の作成
  • 集計
  • テーブルのマージ
  • 縦横変換
  • etc…

今日のおはなし

  1. tidyverse
  2. dplyr
  3. FAQ

本題のまえに

Rとパッケージ

ざっくり

  • Rはパッケージで機能を拡張することができる
  • パッケージには機能特価の関数が詰まっている
  • install.packages() でインストール

パッケージ内の関数の表記

readr パッケージの read_csv 関数を使いたいとき

# 方法 1
library(readr)
dat <- read_csv("hoge.csv")
# 方法 2
dat <- readr::read_csv("hoge.csv")

tidyverse について

tidyverse(概念)

ざっくり:

  • R でやるいろんな操作(データハンドリング、可視化、スクレイピング、分析、etc)を直感的で統一的なインターフェースでできるようになったら嬉しくない?

tidyverse パッケージ

  • 上記の概念を実現するためのコアパッケージ群
  • install.packages("tidyverse")でインストール

tidyverse を読み込み

library(tidyverse)
── Attaching packages ────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.1.0       ✔ purrr   0.3.0  
✔ tibble  2.0.1       ✔ dplyr   0.8.0.1
✔ tidyr   0.8.3       ✔ stringr 1.4.0  
✔ readr   1.3.1       ✔ forcats 0.3.0  
── Conflicts ───────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()

読み込まれるパッケージ

  • ggplot2: 可視化
  • dplyr: データの操作
  • tidyr: データを tidy に
  • readr: データの読み書き
  • purrr: 関数型プログラミング
  • stringr: 文字列の操作
  • forcats: 因子型データの操作
  • tibble: tibble というモダンなデータフレーム

本日の主役は

dplyr

特徴

パッケージを使わないやり方より

  • (大きいデータだと特に)
    速い
  • 簡単
    ≒ わかりやすい
  • 他のtidyverseのパッケージと相性がいい

dplyrの思想

The dplyr package makes these steps fast and easy: - … - It provides simple “verbs”, functions that correspond to the most common data manipulation tasks, to help you translate your thoughts into code. - …

https://cran.r-project.org/web/packages/dplyr/vignettes/dplyr.html

ざっくりと日本語訳

  • dplyr は、あなたの考えをコードに翻訳するための「動詞」を提供する。
  • 「動詞」はデータ操作に関わる関数群

この発表のゴール

  • Rの dplyr パッケージで簡単な集計ができるようになること
  • dplyrや他のパッケージで何ができるのかをなんとなく把握して、「ググり力」を身につける
  • パッケージ名だけでも覚えて帰ってください m(__)m

本日のデータ

EC サイトのログデータ

データの説明

データの読み込み方

  1. RStudio のプロジェクトを作成
  2. Terminal ペインで以下を実行
    git clone https://github.com/ymattu/sampledata_small
  3. readr パッケージの関数で読み込み
sales <- read_csv("sampledata_small/csv/Sales.csv")
product <- read_csv("sampledata_small/csv/Products.csv")
user_master <- read_csv("sampledata_small/csv/UserMaster.csv")

データ読み込みについて詳しくはこちらも参照

dplyr

列選択

sales %>%
  select(UserID) %>%
  head()

%>%

パイプ演算子

  • “これまでの処理を次の関数の第1引数として渡す」という働き”
1:3 %>%
  sum()
[1] 6
# これと全く同じ
sum(1:3)

なんでパイプ演算子が必要なのか?

Tokyo.R#76 BeginneRSession-data pipeline

どう書くのか問題

思考の流れと書く流れ

パイプ演算子を使うときのポイント

結果 <- スタート地点 を書いて、やりたい処理をパイプでつないでいく

列選択のやりかたいろいろ

product %>%
  select(starts_with("P")) %>%
  head(4)

列選択のやりかたいろいろ 2

select(product, 1:3) # 列番号が連続している場合
select(product, ProductID:Price) # 列名でも連続していれば同様
select(product, -CreatedDate) # 特定の列を除く
select(product, -4) # 特定の列番号を除く
select(product, starts_with("p"), ignore.case = TRUE) # 大文字小文字を無視
select(product, matches("^(Product|Price)")) # "Product"または"Price"で始まる列を選択

列追加

  • 税込み価格を計算
product %>%
  mutate(zeikomi = Price * 1.08) %>%
  head(4)

行の絞り込み

user_master %>%
  filter(Age >= 20, Sex == "F") # 年齢 20 歳以上の女性

集計

  • グルーピング + 集計
sales %>%
  group_by(UserID) %>%
  summarise(buy_count = n())

ここまでやったところで

パッケージを使わないでできないの?

  • できるものもあります。
  • select, filter あたりはできます。
  • でもめんどくさい
  • しかもデータが大きいと遅い
  • このあたり、私の過去資料もみてね
  • でも$はお手軽だしよく使います。

$で 1 列だけ取り出す

product$Category %>%
  unique()
[1] "雑貨・日用品"           "花・グリーン"          
[3] "食品"                   "衣料品"                
[5] "ヘルス&ビューティー"   "家具・インテリア・家電"

日付の操作

lubridate パッケージ

lubridate

  • 日付の操作をよしなにやってくれるパッケージ
library(lubridate)
ymd("20110604")
[1] "2011-06-04"
ymd(20120101) + years(1)
[1] "2013-01-01"

詳しくはこちらこちらを参照

データハンドリングでの使い所

たくさんあるけど例えば

sales %>%
  mutate(buy_year = year(Timestamp)) %>%
  head()

ここから集計につなげる

ユーザー、年ごとに集計

sales %>%
  mutate(buy_year = year(Timestamp)) %>%
  group_by(UserID, buy_year) %>%
  summarise(buy_count = n()) %>%
  arrange(UserID) %>% 
  head()

その他、代表的な
(面倒くさい)型たち

文字列型

因子型(factor型)

テーブルのマージ

複数のテーブルを考える

a

b

  • 基本は SQL と同じ

inner_join()

a

b

inner_join(a, b, by = "x1")

left_join()

a

b

left_join(a, b, by = "x1")

full_join()

a

b

full_join(a, b, by = "x1")

anti_join()

a

b

anti_join(a, b, by = "x1")

FAQ

dplyr とかだと何で
R の標準関数より速いの?

Answer : C++を使っているから

  • dplyrreadrでは、メインの処理を C++でやり、結果を R で受け取る、という構造になっています。
  • Rcpp パッケージが活躍!

たくさんのテーブルを join したい!

例えばこんな感じ(a, b, c 3 つのデータ)

  x1 x2
1  A  1
2  B  2
3  C  3
  x1    x3
1  A  TRUE
2  B FALSE
3  D  TRUE
  x1 x4
1  B 10
2  C 11
3  D 12

こうする…?

a %>%
  full_join(b, by = "x1") %>%
  full_join(c, by = "x1")

数が増えると大変!

たくさんのテーブルを join したい!

Answer : 初心者セッションの範囲をこえますが、
purrrパッケージを使うと簡単です。

datlist <- list(a, b, c)
datlist %>%
  purrr::reduce(~full_join(.x, .y, by = "x1"))

purrr パッケージの参考資料→そろそろ手を出す purrr

まとめ

言いたいこと

  • (イマドキな)R でのデータハンドリングでは tidyverse は必須
  • 基礎的なことはTokyo.R初心者セッションや、宇宙本で!
  • 応用は、まずパッケージ名を知ることから(purrr, broom, etc…)
  • ぜひ使いこなせるようになりましょう。

本資料について

Enjoy!