今回は、データ加工に便利なmutate関数について紹介します。
mutate関数
mutate関数はdplyrパッケージに含まれており、新しく列を追加したり、すでにある列を編集したりすることができます。
では実際に次のサンプルデータで使用例を見ていきましょう。
身長(m)と体重(kg)が入ったデータです。
1 2 3 |
height <- c(1.77, 1.63, 1.52, 1.98, 1.83, 1.79, 1.56) weight <- c('54', '68','47', '97', '55', '110', '42') df <- data.frame(height, weight) |
height | weight |
---|---|
1.77 | 54 |
1.63 | 68 |
… | … |
身長(height)・体重(weight)ともに本当は数値データとして扱いたいのですが、このあとデータ型変換をするため、体重データはあえて文字列にしています。
str()で確認してみると、heightは数値型(num)、weightは文字型(chr)になっていることが分かります。
1 2 3 4 |
str(df) 'data.frame': 7 obs. of 2 variables: $ height: num 1.77 1.63 1.52 1.98 1.83 1.79 1.56 $ weight: chr "54" "68" "47" "97" ... |
データ型の変換
まずは文字型となっている体重(weight)を数値型に変換してみましょう。
数値型への変換は
as.numeric(列名)
で行います。
1 2 3 4 |
library(dplyr) df2 <- df %>% mutate(weight = as.numeric(weight)) |
str()で確認してみるとデータ型が両方とも「num」になっているのが確認できますね。
1 2 3 4 |
str(df2) 'data.frame': 7 obs. of 2 variables: $ height: num 1.77 1.63 1.52 1.98 1.83 1.79 1.56 $ weight: num 54 68 47 97 55 110 42 |
そのほかのデータ型に変換する場合も、as.〇〇で可能です。
他によく使われる例をいくつか挙げておきます。
as.numeric | 数値型への変換 |
as.integer | 数値型(整数)への変換 |
as.character | 文字型への変換 |
as.Date | 日付型への変換 |
as.logical | 論理値型への変換 |
as.factor | 因子型への変換 |
計算式で新しい列の追加
次は身長と体重を使ってBMI値を計算し、新しい列「bmi」を作成してみます。
BMIは体重を身長の2乗で割って計算します。(=kg/m2)
このように新規で列を追加する場合は
mutate(新しい列名 = 計算式)
と書きます。
1 2 3 4 5 6 7 8 9 |
df2 <- df %>% mutate(weight = as.numeric(weight)) %>% mutate(bmi = weight/height**2) head(df2,3) #最初の3行だけ確認 height weight bmi 1 1.77 54 17.23643 2 1.63 68 25.59374 3 1.52 47 20.34280 |
条件分岐で新しい列を追加
次は、計算したBMI値をもとに、”普通体重”、”やせ型”、”肥満”の3つのカテゴリに分類した「check」という新しい列を作成してみましょう。
ここでは日本肥満学会の基準に従って
18.5未満→やせ型
18.5~25→普通体重
25以上→肥満
として分類します。
条件分岐の方法にもいろいろありますが、この記事ではif_elseとcase_whenの2つを紹介します。
どちらもdplyrパッケージに含まれる関数です。
if_else
if_elseは
if_else(条件式, 条件式が真の場合の値, 偽の場合の値)
と書きます。
ちょっとややこしいので、まずはBMIが25以上だったら肥満、そうでなければ正常としてみましょう。
条件式の部分には「bmi>=25」として、それに当てはまる場合は”肥満”、当てはまらなければ”普通体重”となります。
1 2 3 4 5 6 7 8 9 10 |
df2 <- df %>% mutate(weight = as.numeric(weight)) %>% mutate(bmi = weight/height**2) %>% mutate(check = if_else(bmi>=25,"肥満","普通体重")) head(df2,3) #最初の3行だけ確認 height weight bmi check 1 1.77 54 17.23643 普通体重 2 1.63 68 25.59374 肥満 3 1.52 47 20.34280 普通体重 |
このように2つに分類するだけならシンプルですが、3つになると少しややこしくなります。
「bmi>=25」に当てはまらない人の中には普通体重の人とやせ型の人がどちらもいるので、さらに条件式を追加して次のように書きます。
1 2 3 4 5 6 7 8 9 10 11 |
df2 <- df %>% mutate(weight = as.numeric(weight)) %>% mutate(bmi = weight/height**2) %>% mutate(check = if_else(bmi>=25,"肥満", if_else(bmi<18.5,"やせ型","普通体重"))) head(df2,3) #最初の3行だけ確認 height weight bmi check 1 1.77 54 17.23643 やせ型 2 1.63 68 25.59374 肥満 3 1.52 47 20.34280 普通体重 |
まずは「bmi>=25」で肥満かどうかを判定し、
次に「bmi<18.5」でやせ型かどうかを判定し、
どちらにも当てはまらない人を”普通体重”に分類するという流れになっています。
式がややこしくなりますが、4つ、5つ…と分類数が多くなってもif_elseを重ねることでいくつでも条件分岐が可能です。
case_when
条件分岐の別の方法のcase_whenは
case_when(条件式~式が真の値の場合の値,
条件式~式が真の値の場合の値,…
TRUE~どれにも当てはまらない場合の値)
と条件式を並べて書きます。
1 2 3 4 5 6 7 8 9 10 11 12 |
df2 <- df %>% mutate(weight = as.numeric(weight)) %>% mutate(bmi = weight/height**2) %>% mutate(check = case_when(bmi>=25~"肥満", bmi<18.5~"やせ型", TRUE~"普通体重")) head(df2,3) #最初の3行だけ確認 height weight bmi check 1 1.77 54 17.23643 やせ型 2 1.63 68 25.59374 肥満 3 1.52 47 20.34280 普通体重 |
条件式は上から順に判定されるので、if_elseの場合と同じように
「bmi>=25」で肥満かどうかを判定し、
次に「bmi<18.5」でやせ型かどうかを判定し、
いずれにも当てはまらない人を”普通体重”に分類するという流れです。
個人的には、3つ以上に分類する場合はcase_whenの方が使いやすいのかなと思っています。
今回は以上です。
mutateを使い倒してデータを自在に操りましょう!
コメント