sample.csv は 17035201 行の CSV ファイルである。最初の 7 行は以下のようになっている。
"id","label"
1,"aaa_あああ"
2,"aaa_いいい"
3,"bbb_ううう"
4,"bbb_えええ"
5,"ccc_おおお"
6,"ccc_かかか"
これを入力とし,以下のように変更を加え出力する。
"id",label"
1,"aaa"
1,"あああ"
2,"aaa"
2,"いいい"
3,"bbb"
3,"ううう"
4,"bbb"
4,"えええ"
5,"ccc"
5,"おおお"
6,"ccc"
6,"かかか"
# tidyr
あまり 'tidy' なプログラムでもないが,この 3 行のプログラムでの実行時間は 125.581, 122.979, 121.734 であった。
平均値は 123.431 秒。
しかし,システムが使用する時間が同程度あり,結局経過時間(計算開始から結果が出るまでの時間)は実に388.996, 283.905, 297.495 で,平均値は 323.465 秒,実に 5 分超である。
library(dplyr)
library(tidyr)
system.time({
sample = read.csv("sample.csv")
sample_row <- sample %>% separate_rows(label,sep="_")
write.csv(sample_row, "tidyr.csv", row.names=FALSE)
})
# Base R
最近では tidyr は知っているが,Base R は知らない(書けない)という人も多いようであるが,この 4 行のプログラムでの実行時間は 25.035, 25.480, 25.446 であった。
平均値は 25.320 秒。
経過時間は 24.190 秒である。tidyr によるものより 30 倍速い。
system.time({
sample = read.csv("sample.csv")
a = unlist(strsplit(sample$label, "_"))
sample = data.frame(id=rep(sample$id, each=2), label=a)
write.csv(sample, "BaseR.csv", row.names=FALSE)
})
# AWK
AWK を知らない人も多いと思うが,この例のような簡単なデータ前処理には十分使える。
この CSV ファイルの構造をフルに利用して,実質 5 行のプログラムを書く。実行時間は 21.380, 22.024, 21.848 であった。
平均値は 21.751 秒。
BaseR によるよりも 16% 速い。tidyr に比べると 5 倍速い。
BEGIN {
FS = ","
getline
print $0
}
{
split($2, t, "_")
printf "%s,%s\"\n%s,\"%s\n", $1, t[1], $1, t[2]
}
結果
またまた,AWK が最速という結果になった。
R はデータをすべてメモリ中に保存している。しかも,場合によってはそのコピーを作ったりすることもある。このプログラムが動いているとき R は 2GB ものメモリを消費している。
AWK はデータを「一行読んで,処理して,書き出して」を繰り返すのでメモリは殆ど使わない。
そのあたりがこういう結果になっているのであろう。
特に tidyr は,BaseR に比べてメモリ操作が下手くそ(余計なことをしている)なのであろう。