tribbleパッケージのread_csv関数を使用する。まずは巨大なCSVファイルを作成する。PowerShellのコマンドラインで以下を実行する。
PS > $s = "1,abc,2.3`r`n2,あい,4.5`r`n3,えおyz,NA`r`n"
PS > [Text.Encoding]::GetEncoding("utf-8").GetByteCount($s)
40
PS > $n = 1024 * 1024 * 4
PS > $file = (gl).Path + "\temp_utf8nb.csv"
PS > [IO.File]::WriteAllText($file, $s * $n)
PS > Get-ChildItem .\temp_utf8nb.csv
ディレクトリ: ○○○
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2023/08/20 22:27 167772160 temp_utf8nb.csv
PS > Get-Content .\temp_utf8nb.csv -TotalCount 5 -Encoding utf8
1,abc,2.3
2,あい,4.5
3,えおyz,NA
1,abc,2.3
2,あい,4.5
変数$sには大きさが40バイトの文字列(改行コード含む)が格納され、それを1024倍して40KiB(キビバイト)、さらに1024倍して40MiB(メビバイト)、最後に4倍して160MiBにしてCSVファイル(temp_utf8nb.csv)に出力している。これの160MiBのCSVファイルを使用する。なお、FileクラスのWriteAllTextメソッドを使用して文字コードをUTF-8(BOM無し)で出力していることに注意。改行コードは$sの中身のとおりにCR+LF。
Rで標準で使うことができるread.table関数を使ってみる。
> system.time(dtf <- read.table("temp_utf8nb.csv", sep = ",", fileEncoding = "UTF-8"))
ユーザ システム 経過
7.50 0.16 7.84
> system.time(dtf <- read.table("temp_utf8nb.csv", sep = ",", fileEncoding = "UTF-8"))
ユーザ システム 経過
7.10 0.14 7.88
> system.time(dtf <- read.table("temp_utf8nb.csv", sep = ",", fileEncoding = "UTF-8"))
ユーザ システム 経過
7.33 0.15 7.83
> nrow(dtf)
[1] 12582912
> head(dtf, 5)
V1 V2 V3
1 1 abc 2.3
2 2 あい 4.5
3 3 えおyz NA
4 1 abc 2.3
5 2 あい 4.5
キャッシュの影響を考慮して3回試している。この環境では読み込みに7.8秒程度要する。次にreadrパッケージのread_csv関数を使ってみる。
> library(readr)
> system.time(tbl <- read_csv("temp_utf8nb.csv", col_names = FALSE, progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.70 0.12 1.34
> system.time(tbl <- read_csv("temp_utf8nb.csv", col_names = FALSE, progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.42 0.19 1.31
> system.time(tbl <- read_csv("temp_utf8nb.csv", col_names = FALSE, progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.56 0.22 1.36
> nrow(tbl)
[1] 12582912
> head(as.data.frame(tbl), 5)
X1 X2 X3
1 1 abc 2.3
2 2 あい 4.5
3 3 えおyz NA
4 1 abc 2.3
5 2 あい 4.5
キャッシュの影響を考慮して3回試している。この環境では読み込みに1.4秒程度要する。read_csvはread.tableよりもファイルの読み込みが5倍以上早いことがわかる。なお、read_delim関数でも同じくらい早ことがわかる。
> system.time(tbl <- read_delim("temp_utf8nb.csv", col_names = FALSE, delim = ",", progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.14 0.08 1.25
原因は不明だが、このテスト環境(Windows版4.2.2)では、read.csv関数はfileEncodingオプションが指定どおり動作しない。そのため、上の例では代わりにread.table関数を使用している。