Press "Enter" to skip to content

[R] データフレームの改造

wyosis 0

しばらく間が空きましたが、http://r4ds.had.co.nz/transform.html#arrange-rows-with-arrange から続けていきたいと思います。

library(tidyverse)
library(nycflights13)

を読み込んで、

昇/降順に並べる

arrange() 関数はデータフレームのカラムを複数指定することで、そのカラムについて昇順に並べ替えることができる。

arrange(flights, year, month, day)

降順にしたい場合は、desc() をカラム名に付ける。

arrange(flights, desc(arr_delay))

データにNA(Missin Value)を含む場合、昇降順に関わらず常に最後にソートされる。

df <- tibble(x = c(5, 2, NA))
arrange(df, x)
arrange(df, desc(x))

カラムを抜き出す

flightsには19のカラムがあるが、例えばここから日付に関するカラムのみを抜き出したいというような場合はselect() 関数が便利である。

select(flights, year, month, day)
select(flights, year:day)
select(flights, -(year:day))

結果を見ればわかるかと思うが、「year:day」は「yearカラムから右にdayカラムまで」を表す記法だ。そして、「-」は否定表現である。また、Rには正規表現的な関数が用意されているのでそちらも合わせて使うと便利である。

  • starts_with(“abc”) … abcから始まる
  • ends_with(“xyz”) … xyzで終わる
  • contains(“ijk”) … ijkを含む
  • matches(“(.)\\1”) … ※正規表現
  • num_range(“x”, 1:3) … x1, x2, x3

詳細を更に知りたい場合は、?select コマンドで。

selectはカラムのリネームにも使えるが、指定しないカラムは消えてしまうのでrename() 関数を使ったほうがよい。

rename(flights, tail_num = tailnum)

everything は引数で指定されていない全てのカラムを返す。これを利用して、任意のカラムを先頭に持ってくることができる。どういうことかというと、

select(flights, time_hour, air_time, everything())

とすると、time_hour -> air_time -> その他(yearから) というように並べ替えられる。

カラムを追加する

カラムのデータを使って演算したいときがある。例えば今練習で使っているflightsには飛行距離(distance)と飛行時間(air_time)が含まれているが、ここから飛行機の速さを計算することができる。それが以下の例である。

flights_sml <- select(flights, 
 year:day, 
 ends_with("delay"), 
 distance, 
 air_time
)
mutate(flights_sml,
 gain = arr_delay - dep_delay,
 speed = distance / air_time * 60
)

一旦selectしているのは余計なカラムを省いて可読性を上げるためだろう。19個カラムがあるので、画面が小さいと見切れる可能性がある。というか見切れる可能性のほうが高い。とにかくこれでgainカラムとspeedカラムが追加されていることを確認できた。ちなみに、作ったばかりのカラムを即座に使用できる。

mutate(flights_sml,
 gain = arr_delay - dep_delay,
 hours = air_time / 60,
 gain_per_hour = gain / hours
)

また、新規のカラムのみをデータフレームにしたい場合は、transmute() 関数を使う。

transmute(flights,
 gain = arr_delay - dep_delay,
 hours = air_time / 60,
 gain_per_hour = gain / hours
)

ところで、mutateで行う演算はベクトルの演算と考えることができる、というと大げさだが。要は、「distance / air_time」としたとき同じ行同士の値で演算しているという話である。このとき、演算にかける2つのベクトルは同じ要素数である必要がある。大きさが異なるとき、例えば「air_time / 60」のように片方がスカラー(単一の数)の場合、自動的に同じ要素数のベクトルに拡張される。以下、有用な演算子を示す。

  • +, -, *, /, ^ … 言わずもがな
  • %/% … 割り算の商
  • %% … 割り算の余り
  • log(), log2(), log10() … ログ計算。log2スケールにすると、倍が+1・半分が-1に対応されて便利
  • lead(), lag() … 左シフトと右シフト(※1)
  • cumsum(), cumprod(), cummin(), cummax() … 統計的に有用(※2)
  • <, <=, >, >=, != … 条件演算子TRUE or FALSEで返される
  • min_rank(), row_number(), dense_rank(), percent_rank(), cume_dist(), ntile() … ランキング(※3)

※1 シフト

x <- 1:10
lag(x)
lead(x)

数字が全部左右にずれて、空いた部分にはNAが入る。

※2 統計

> cumsum(x) *1番目、1番目+2番目、1番目+2番目+3番目、...
 [1] 1 3 6 10 15 21 28 36 45 55
> cummean(x) *1番目の平均、1番目+2番目の平均、番目+2番目+3番目の平均、...
 [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
> cumprod(x) *1番目、1番目×2番目、1番目×2番目×3番目、...
 [1] 1 2 6 24 120 720 5040 40320 362880
[10] 3628800
> cummin(x) *1番目中で最小、1・2番目中で最小、1・2・3番目中で最小、...
 [1] 1 1 1 1 1 1 1 1 1 1
> cummax(x) *1番目中で最大、1・2番目中で最大、1・2・3番目中で最大、...
 [1] 1 2 3 4 5 6 7 8 9 10
> y <- c(TRUE,TRUE,FALSE)
> cumall(y) *1番目が全てT、1・2番目が全てT、1・2・3番目が全てT、...
[1] TRUE TRUE FALSE
> cumany(y) *1番目のいずれかがT、1・2番目のいずれかがT、1・2・3番目のいずれかがT、...
[1] TRUE TRUE TRUE

※3 ランキング

> min_rank(x) *昇順ランキング。同値は同じ順位。タイの分次の順位をスキップする
 [1] 1 2 3 4 5 6 7 8 9 10
> row_number(x) *昇順ランキング。同値は早い順
 [1] 1 2 3 4 5 6 7 8 9 10
> dense_rank(x) *昇順ランキング。同値は同じ順位。タイの分次の順位をスキップしない
 [1] 1 2 3 4 5 6 7 8 9 10
> percent_rank(x) *min_rankを0〜1にスケーリング
 [1] 0.0000000 0.1111111 0.2222222 0.3333333 0.4444444 0.5555556 0.6666667
 [8] 0.7777778 0.8888889 1.0000000
> cume_dist(x) *累積割合
 [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> ntile(x,5) *順位をn(左の例では5個)に収める
 [1] 1 1 2 2 3 3 4 4 5 5

参考文献

https://qiita.com/matsuou1/items/db6e8c48fcfd791dd876

特に※2統計と※3ランキングの参考にしました

コメントを残す

メールアドレスが公開されることはありません。