Chapter 6 データハンドリング
6.1 繰り返し・条件分岐
6.1.1 繰り返し構文
データを加工する際,変更箇所の少ない演算を何度も繰り返し行うことがあります.
そんなときに便利なのがfor
を使った繰り返し構文です.
ここで,i
は繰り返しを制御する文字です.「i
が範囲
内の値を順番に取ったときに~というコマンドを実行する」という指令を出しています.例を見てみましょう.No.1からNo.10を出力したいときには次のようなコードで実行できます.文字を出力したいときはcat()
関数が便利です.引数は出力したい文字です."\n"
で改行を指定します.
## No. 1
## No. 2
## No. 3
## No. 4
## No. 5
## No. 6
## No. 7
## No. 8
## No. 9
## No. 10
6.1.1.1 Tips: 空箱をつくる
繰り返し構文で出力したデータを1つにまとめて保存したい場合,予め「空箱」を作っておくと便利です.
## 空箱を作る ##
numbers <- rep(NA, 10) # NA 10個からなるベクトル
## 繰り返し ##
for(i in 1:10){
numbers[i] <- paste(i) # ベクトルnumbers の第i成分にiを代入
}
## 中身を確認 ##
numbers
## [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
ここで,rep()
はリピートを表す関数です.上の例では欠損NA
10個からなるベクトルを生成しています.
6.1.2 条件分岐
条件分岐もデータハンドリングでよく使われる構文です.if
の直後の()
には何らかの条件をいれ,真TRUE
であれば{}
内のコマンドが実行され,偽FALSE
であれば{}
内のコマンドはスキップされます.
複数の条件を順に分岐させたい場合はelse if(){}
やelse{}
を使います.条件が満たされない場合は次の分岐へと引き渡され,この手順が繰り返されます.どの条件も満たさない場合のコマンドはelse {}
で指定します.
if( 条件 1 ){
コマンド 1
} else if( 条件 2){
コマンド 2
} else if( 条件 3) {
コマンド 3
} ..... {
.....
} else {
コマンド n
}
たとえば,実数x
の偶奇を判定するプログラムは次の通り.
## x が4のとき ##
x <- 4
if(x %% 2 == 0){ # x %% 2 は「xを2で割った余り」を表す
cat(x, 'は偶数', sep ='')
} else if(x %% 2 == 1){
cat(x, 'は奇数', sep = '')
} else{
cat(x, 'は整数ではない', sep = '')
}
## 4は偶数
## x が43のとき ##
x <- 43
if(x %% 2 == 0){
cat(x, 'は偶数', sep = '')
} else if(x %% 2 == 1){
cat(x, 'は奇数', sep = '')
} else{
cat(x, 'は整数ではない', sep = '')
}
## 43は奇数
## x が円周率のとき ##
x <- pi
if(x %% 2 == 0){
cat(x, 'は偶数', sep = '')
} else if(x %% 2 == 1){
cat(x, 'は奇数', sep = '')
} else{
cat(x, 'は整数ではない', sep = '')
}
## 3.141593は整数ではない
Chapter 7 データハンドリング: dplyr入門
7.1 準備
7.1.1 dplyrとは?
dplyr
はデータフレームを効率良く処理するためのパッケージです.tidyverse
の中に入っています.
tidyverse
はdplyr
の他にもggplot2
などの便利なパッケージがたくさん入ってます.dplyr
だけを使用したい場合は以下のコマンドでOKです.
7.2 使用データ
パッケージggplot2
からmpg
という自動車に関するデータを取得します.
## # A tibble: 6 x 11
## manufacturer model displ year cyl trans drv cty hwy fl class
## <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr> <chr>
## 1 audi a4 1.8 1999 4 auto… f 18 29 p comp…
## 2 audi a4 1.8 1999 4 manu… f 21 29 p comp…
## 3 audi a4 2 2008 4 manu… f 20 31 p comp…
## 4 audi a4 2 2008 4 auto… f 21 30 p comp…
## 5 audi a4 2.8 1999 6 auto… f 16 26 p comp…
## 6 audi a4 2.8 1999 6 manu… f 18 26 p comp…
## [1] "manufacturer" "model" "displ" "year"
## [5] "cyl" "trans" "drv" "cty"
## [9] "hwy" "fl" "class"
7.3 dplyrを使ったデータフレーム処理
データフレームに様々な処理を行ってみましょう.
7.3.1 select(): 列(変数)の選択
select()
は列を選択する関数です.最初の引数はデータ,2番目以降の引数は列名です.
## # A tibble: 6 x 2
## manufacturer model
## <chr> <chr>
## 1 audi a4
## 2 audi a4
## 3 audi a4
## 4 audi a4
## 5 audi a4
## 6 audi a4
dplyr
などのtidyverse
に含まれるパッケージのコマンドの多くは最初の引数でデータを指定します.データの指定はパイプ%>%
を使って省略できます.次の例ではselect()
の最初の引数mpg
がパイプ%>%
によって引き継がれています.
## # A tibble: 6 x 2
## manufacturer model
## <chr> <chr>
## 1 audi a4
## 2 audi a4
## 3 audi a4
## 4 audi a4
## 5 audi a4
## 6 audi a4
列名ではなく列番号でも指定できます.
## # A tibble: 6 x 3
## manufacturer year displ
## <chr> <int> <dbl>
## 1 audi 1999 1.8
## 2 audi 1999 1.8
## 3 audi 2008 2
## 4 audi 2008 2
## 5 audi 1999 2.8
## 6 audi 1999 2.8
7.3.2 filter(): 行(観測)の選択
filter()
は行を選択します.引数は何らかの条件です.
## # A tibble: 10 x 11
## manufacturer model displ year cyl trans drv cty hwy fl
## <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
## 1 audi a4 1.8 1999 4 auto(… f 18 29 p
## 2 audi a4 1.8 1999 4 manua… f 21 29 p
## 3 audi a4 2.8 1999 6 auto(… f 16 26 p
## 4 audi a4 2.8 1999 6 manua… f 18 26 p
## 5 audi a4 quatt… 1.8 1999 4 manua… 4 18 26 p
## 6 audi a4 quatt… 1.8 1999 4 auto(… 4 16 25 p
## 7 audi a4 quatt… 2.8 1999 6 auto(… 4 15 25 p
## 8 audi a4 quatt… 2.8 1999 6 manua… 4 17 25 p
## 9 audi a6 quatt… 2.8 1999 6 auto(… 4 15 24 p
## 10 chevrolet c1500 su… 5.7 1999 8 auto(… r 13 17 r
## # … with 1 more variable: class <chr>
次のように複数のコマンドを組み合わせて使用することも可能です(それこそがtidyverse
の醍醐味です).
mpg_new <- mpg %>%
filter(year == 1999, manufacturer == 'toyota') %>%
select(manufacturer, model, displ, year)
# 確認
head(mpg_new, n = 10)
## # A tibble: 10 x 4
## manufacturer model displ year
## <chr> <chr> <dbl> <int>
## 1 toyota 4runner 4wd 2.7 1999
## 2 toyota 4runner 4wd 2.7 1999
## 3 toyota 4runner 4wd 3.4 1999
## 4 toyota 4runner 4wd 3.4 1999
## 5 toyota camry 2.2 1999
## 6 toyota camry 2.2 1999
## 7 toyota camry 3 1999
## 8 toyota camry 3 1999
## 9 toyota camry solara 2.2 1999
## 10 toyota camry solara 2.2 1999
7.3.3 group_by()/ungroup(): グループ化/解除
group_by()
はデータセットをグループ化するコマンドです.次の例では変数year
ごとにグループ化しています.
## # A tibble: 10 x 11
## # Groups: year [2]
## manufacturer model displ year cyl trans drv cty hwy fl
## <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
## 1 audi a4 1.8 1999 4 auto(l… f 18 29 p
## 2 audi a4 1.8 1999 4 manual… f 21 29 p
## 3 audi a4 2 2008 4 manual… f 20 31 p
## 4 audi a4 2 2008 4 auto(a… f 21 30 p
## 5 audi a4 2.8 1999 6 auto(l… f 16 26 p
## 6 audi a4 2.8 1999 6 manual… f 18 26 p
## 7 audi a4 3.1 2008 6 auto(a… f 18 27 p
## 8 audi a4 quat… 1.8 1999 4 manual… 4 18 26 p
## 9 audi a4 quat… 1.8 1999 4 auto(l… 4 16 25 p
## 10 audi a4 quat… 2 2008 4 manual… 4 20 28 p
## # … with 1 more variable: class <chr>
左上の“Groups:”を見るとyear
によってちゃんとグループが作られているのが確認できます.でも実はグループ化しただけではデータは何も変わりません.グループ化は以降のセクションで紹介するsummarize()
やmutate()
と組み合わせることで初めて効力を発揮します.
複数の変数でグループ化することもできます.次の例では企業×年度をグループとしています.
## # A tibble: 10 x 11
## # Groups: manufacturer, year [2]
## manufacturer model displ year cyl trans drv cty hwy fl
## <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
## 1 audi a4 1.8 1999 4 auto(l… f 18 29 p
## 2 audi a4 1.8 1999 4 manual… f 21 29 p
## 3 audi a4 2 2008 4 manual… f 20 31 p
## 4 audi a4 2 2008 4 auto(a… f 21 30 p
## 5 audi a4 2.8 1999 6 auto(l… f 16 26 p
## 6 audi a4 2.8 1999 6 manual… f 18 26 p
## 7 audi a4 3.1 2008 6 auto(a… f 18 27 p
## 8 audi a4 quat… 1.8 1999 4 manual… 4 18 26 p
## 9 audi a4 quat… 1.8 1999 4 auto(l… 4 16 25 p
## 10 audi a4 quat… 2 2008 4 manual… 4 20 28 p
## # … with 1 more variable: class <chr>
グループを解除したいときはungroup()
を指定します.先ほどのグループを解除してみましょう.
## # A tibble: 6 x 11
## manufacturer model displ year cyl trans drv cty hwy fl class
## <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr> <chr>
## 1 audi a4 1.8 1999 4 auto… f 18 29 p comp…
## 2 audi a4 1.8 1999 4 manu… f 21 29 p comp…
## 3 audi a4 2 2008 4 manu… f 20 31 p comp…
## 4 audi a4 2 2008 4 auto… f 21 30 p comp…
## 5 audi a4 2.8 1999 6 auto… f 16 26 p comp…
## 6 audi a4 2.8 1999 6 manu… f 18 26 p comp…
左上に“Groups:”という欄がないのでグループが解除されたことが確認できます.
7.3.4 summarize(): 集計
先ほど説明したgroup()
で指定したグループごとに変数を何らかの形で集計してみます.集計を指示するコマンドはsummarize()
です.引数は新しい変数名 = 集計の内容
のようなイメージ.
mpg_new <- mpg %>%
group_by(manufacturer, year) %>%
summarize(displ_mean = mean(displ)) %>%
ungroup()
## `summarise()` has grouped output by 'manufacturer'. You can override using the `.groups` argument.
## # A tibble: 10 x 3
## manufacturer year displ_mean
## <chr> <int> <dbl>
## 1 audi 1999 2.36
## 2 audi 2008 2.73
## 3 chevrolet 1999 4.97
## 4 chevrolet 2008 5.12
## 5 dodge 1999 4.32
## 6 dodge 2008 4.42
## 7 ford 1999 4.45
## 8 ford 2008 4.66
## 9 honda 1999 1.6
## 10 honda 2008 1.85
上の例では各グループごとに変数displ
を平均して集計しましたが,単純に観測数を数えたい場合はn()
を使用します.
## `summarise()` has grouped output by 'manufacturer'. You can override using the `.groups` argument.
## # A tibble: 10 x 3
## manufacturer year count
## <chr> <int> <int>
## 1 audi 1999 9
## 2 audi 2008 9
## 3 chevrolet 1999 7
## 4 chevrolet 2008 12
## 5 dodge 1999 16
## 6 dodge 2008 21
## 7 ford 1999 15
## 8 ford 2008 10
## 9 honda 1999 5
## 10 honda 2008 4
7.3.5 mutate(): 新しい変数作成
mutate()
は新しい変数を作成するコマンドです.次の例はcty
の自然対数をln_cty
という新しい変数として作成しています.
## # A tibble: 6 x 2
## cty ln_cty
## <int> <dbl>
## 1 18 2.89
## 2 21 3.04
## 3 20 3.00
## 4 21 3.04
## 5 16 2.77
## 6 18 2.89
mutate()
は先ほど説明したgroup()
と組み合わせて使用すると便利なときがあります.
mpg_new <- mpg %>%
group_by(manufacturer, year) %>%
mutate(displ_mean = mean(displ)) %>%
ungroup()
# 確認
mpg_new %>%
select(manufacturer, model, year, displ_mean)
## # A tibble: 234 x 4
## manufacturer model year displ_mean
## <chr> <chr> <int> <dbl>
## 1 audi a4 1999 2.36
## 2 audi a4 1999 2.36
## 3 audi a4 2008 2.73
## 4 audi a4 2008 2.73
## 5 audi a4 1999 2.36
## 6 audi a4 1999 2.36
## 7 audi a4 2008 2.73
## 8 audi a4 quattro 1999 2.36
## 9 audi a4 quattro 1999 2.36
## 10 audi a4 quattro 2008 2.73
## # … with 224 more rows
グループ化したデータにおけるmutate()
とsummarize()
の違いは行数を確認すれば一目瞭然です.
# summarize() ver
mpg_summarize <- mpg %>%
group_by(manufacturer, year) %>%
summarize(displ_mean = mean(displ)) %>%
ungroup()
## `summarise()` has grouped output by 'manufacturer'. You can override using the `.groups` argument.
# mutate() ver
mpg_mutate <- mpg %>%
group_by(manufacturer, year) %>%
mutate(displ_mean = mean(displ)) %>%
ungroup()
# 行数(観測数) を確認
nrow(mpg) ; nrow(mpg_summarize) ; nrow(mpg_mutate)
## [1] 234
## [1] 30
## [1] 234
7.3.6 pivot_*():wide型からlong型への変換 次回
7.3.7 arrange():行の並び替え
次回
7.3.8 distinct(): 重複行の操作
次回