いや、何をいまさらっていう感じなのですが書いておきます。
list.filesとlapply使う内容です。
あるディレクトリ内のcsvを一括で読み込みタイとします。
最初にlist.filesを使ってファイル名を取得します。
例えばlogというディレクトリ内のすべてのファイル名は以下で取得できます。
list.files(path = “log”, full.names = T)
この時full.names = Tにすると、ファイル名にディレクトリの名前も付けてくれます。
これを適当な名前を付けた変数に突っ込んでおきます。
lf <- list.files(path = “log”, full.names = T)
そしてlapplyを使ってまとめて読み込みます。
lapply(lf, read.csv)
ただ、lapplyで読むと結果がリストになってしまいます。
以下のように読んだとすると、
data <- lapply(lf,read.csv)
data[[1]]でlfの中の一番目のcsvファイルが読みだされます。
恐らく普通にほしいのは一つのデータフレームだと思うので、これをまとめる必要があります。
ということで、do.callを使います。
data <- lapply(lf,read.csv)
data_bind <- do.call(rbind, data)
これでdata_bindに全ての読み込まれたcsvが一つのデータフレームの状態で入ります。
もしlist.filesで取得したものの中でも特定のパターンのファイルだけ読みたいなどあれば、stringrのstr_detect等をlfに対して用いればよいかなと思います。
一応速さ的なものを見てみます。
複数のcsvを読もうとするとき、よく最初に見かけるのがforを使うものかと思います。
lf <- list.files(“log”,full.names = T)
data <- data.frame()
system.time(
for(i in 1:length(lf)){
add <- read.csv(lf[i])
data <- rbind(data,add)}
)
1.2MBのcsvを110個読み込もうとすると、
> lf <- list.files(“log”,full.names = T)
> data <- data.frame()
> system.time(
+ for(i in 1:length(lf)){
+ add <- read.csv(lf[i])
+ data <- rbind(data,add)
+ }
+ )
ユーザ システム 経過
58.60 8.62 67.53
こんな感じです。
一方今回説明した方法だと、
> system.time(
+ data_b <- do.call(rbind, lapply(lf,read.csv))
+ )
ユーザ システム 経過
10.53 1.41 11.95
圧倒的に早いですね。
ちなみにですが、data.tableパッケージのfreadを使えばもっと早いですね。
> data <- data.frame()
> system.time(
+ for(i in 1:length(lf)){
+ add <- fread(lf[i])
+ data <- rbind(data,add)
+ }
+ )
ユーザ システム 経過
3.82 0.16 3.96
forのほうでもこの速さ。
> system.time(
+ data_b <- do.call(rbind, lapply(lf,fread))
+ )
ユーザ システム 経過
1.19 0.04 1.23
なんか差が2秒しかないとありがたみが無さそうですw
気になったのでファイルの数を倍にしてみることにしました
> lf <- list.files(“log”,full.names = T)
> data <- data.frame()> system.time(
+ for(i in 1:length(lf)){
+ add <- fread(lf[i])
+ data <- rbind(data,add)
+ }
+ )
ユーザ システム 経過
18.92 1.55 20.49> system.time(
+ data_b <- do.call(rbind, lapply(lf,fread))
+ )
ユーザ システム 経過
2.44 0.03 2.47> length(lf)
[1] 220
forの方は20秒程度ですが、lapplyは3秒程度。
ファイルの数が多ければ恩恵が大きそうですね。
めでたしめでたし。