複数のファイルを一度に読みこむ方法

Rで複数のファイルを一度に読み込みたい場合がたまにある。
例えば、売り上げのデータが日付ごとに分かれたファイルに収められているような場合。
しょっちゅう発生するわけでもなく、いつも忘れてしまって調べるのに時間がかかるのでここにメモしておく。

ここではそうしたファイルが一つのフォルダに収められているものとする。

方法は大きく三つある

  • Tidyverse流(read_csv & map_dfr)
  • data.table流(fread & rbindlist)
  • vroom流(vroom)

デモデータの用意

必要なパッケージを読み込みつつ、実験用のデモデータの用意。

library(tidyverse)
library(data.table)
library(vroom)
library(microbenchmark)

DIR <- "data/"

row_n <- 10000
col_n <- 10
files <- 10
file_names <- paste0(DIR, formatC(1:files, width = 3, flag = "0"), ".csv")

for (i in file_names) {
  rnorm(col_n * row_n) %>%
    round(4) %>%
    matrix(row_n, col_n) %>%
    data.frame() %>%
    fwrite(i)
}

Tidyverse流

  DIR %>%
    list.files(pattern = "*.csv", full.names = TRUE) %>%
    set_names() %>%
    map_dfr(read_csv,
      .id = "file_name"
    ) -> dat

data.table流

  DIR %>%
    list.files(pattern = "*.csv", full.names = TRUE) %>%
    set_names() %>%
    map(fread) %>%
    rbindlist(idcol = "file_name") -> dat

vroom流

  DIR %>%
    list.files(pattern = "*.csv", full.names = TRUE) %>%
    vroom(id = "file_name") -> dat

比較

Tidyverseに慣れてる人なら read_csv と map_dfr を組み合わせるのが分かりやすいだろう。
data.table流はとにかく速い。爆速。
vroomはファイル数が多くなるとエラーになる。今後に期待。

f:id:bob3:20190707154441p:plain
複数ファイルの読み込み速度比較

# read_csv + map_dfr -----------------------------------------------------------------
read_csv_and_map_dfr <- function() {
  DIR %>%
    list.files(pattern = "*.csv", full.names = TRUE) %>%
    set_names() %>%
    map_dfr(read_csv,
      .id = "file_name"
    )
}

# fread + rbindlist ---------------------------------------------------------
fread_and_rbindlist <- function() {
  DIR %>%
    list.files(pattern = "*.csv", full.names = TRUE) %>%
    set_names() %>%
    map(fread) %>%
    rbindlist(idcol = "file_name")
}

# vroom -------------------------------------------------------------------
# ファイル数が多いとエラーになる場合がある。
my_vroom <- function() {
  DIR %>%
    list.files(pattern = "*.csv", full.names = TRUE) %>%
    vroom(id = "file_name")
}

# microbenchimark ---------------------------------------------------------

gc()
gc()

compare <- microbenchmark(
  "read_csv & map_dfr" = read_csv_and_map_dfr(),
  "fread & rbindlist" = fread_and_rbindlist(),
  "vroom" = my_vroom(),
  times = 30L
)

compare

autoplot(compare) +
  labs(title = "R 3.6.1") 

以上。