Rにおけるデータを操作するパッケージとしてはdplyrがおそらく最もメジャーですが、 大規模なデータを扱う場合、data.tableを検討した方がよいかもしれません。 data.tableは高速かつ非常に簡潔な構文でデータを扱うことができます。 この記事では、dplyrに慣れ親しんでいたユーザーのために、 data.tableでのデータ操作と同等の操作をdplyrで行った場合を 確認しながら、data.tableでのデータ操作を学んでいきます。
練習課題としてdata.tableのvignette https://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.html を参照しました。 data.tableのソースコードは基本的にここに書かれているものと同じです。 dplyrのコードは、元記事のコードとだいたい同じものになるように 私が吟味して書きました。 では、まずライブラリを読み込んでいきます。
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff,
#> setequal, union
library(data.table)
#> data.table 1.14.2 using 4 threads (see ?getDTthreads). Latest news: r-datatable.com
#>
#> Attaching package: 'data.table'
#> The following objects are masked from 'package:dplyr':
#>
#> between, first, last
使用するデータは、 vignetteで使われているflights14を使います。 元々はhttps://github.com/arunsrinivasan/flightsで公開されているデータで、 以下のコードが示すように、csvとしても公開されているので、 いずれか好きな方法でダウンロードしてから利用します。 何度も読み込んだりするなら、 あらかじめバイナリデータとして保存しておいた方がよいかもしれません。 そうすれば、 load("data/flights.rda")
でいつでもすぐにデータを呼び出すことができます。
"https://raw.githubusercontent.com/Rdatatable/data.table/master/vignettes/flights14.csv"
input <-download.file(input, "inst/extdata/flights14.csv")
fread("inst/extdata/flights14.csv")
flights <-save(flights, file = "data/flights.rda")
ちなみにflights
データは、 2014 年にニューヨークにある3つの空港 JFK, LGA, EWR から出発した飛行機のデータで、発着の時間、飛行距離、遅延時間などが記録されています。
まず、最初の問題、 出発時間の遅れと到着時間の遅れを合わせたときに0より小さい、 つまり総合的には遅れがなかったといえるフライトは全体の何パーセントでしょうか。
これをdplyrで解くには
|> summarise(mean((arr_delay + dep_delay) < 0))
flights #> mean((arr_delay + dep_delay) < 0)
#> 1 0.5598304
data.tableで解くには
mean((arr_delay + dep_delay) < 0)]
flights[, #> [1] 0.5598304
となります。 念のため、計算の内訳を示してみましょう。 遅延時間の合計が0より小さいフライト数と、 全てのフライト数を数え、 その比が上記の計算結果と一致するか確認します。
|>
flights summarise(
delay = sum((arr_delay + dep_delay) < 0),
n = n(),
ratio = delay / n
)#> delay n ratio
#> 1 141814 253316 0.5598304
data.tableでは
flights[, .(delay = sum((arr_delay + dep_delay) < 0),
n = .N,
ratio = sum((arr_delay + dep_delay) < 0) / .N
)
]#> delay n ratio
#> 1: 141814 253316 0.5598304
となります。 dplyrでは、要約した変数の名前をdelay / n
というふうに、 すぐに使うことができますが、 data.tableではこの機能はありません。 そのため、ちょっと冗長な書き方をしなくてはなりませんでした。 いずれにせよ、計算は一致しました。
つぎに、 6月にJFK(ジョン・F・ケネディ空港)から出発した飛行機の 出発時間と目的地の到着時間の遅延時間をそれぞれ計算します。 dplyrでは次のように書けるでしょう。
|>
flights filter(origin == "JFK", month == 6) |>
summarise(
m_dep = mean(dep_delay),
m_arr = mean(arr_delay)
)#> m_dep m_arr
#> 1 9.807884 5.839349
これをdata.tableでは
flights[== "JFK" & month == 6,
origin
.(m_dep = mean(dep_delay),
m_arr = mean(arr_delay)
)
]#> m_dep m_arr
#> 1: 9.807884 5.839349
のように書きます。 ちなみにdplyrでは
|>
flights filter(origin == "JFK", month == 6) |>
summarise(across(matches("_delay"), mean))
#> dep_delay arr_delay
#> 1 9.807884 5.839349
と書くこともでき、この場合、列名に"_delay"が含まれる列を一括で処理することができます。