回答:
次のような結果になると、各データフレームは単一のリストの個別の要素になります。
temp = list.files(pattern="*.csv")
myfiles = lapply(temp, read.delim)
これは、CSVが単一のディレクトリ(現在の作業ディレクトリ)にあり、それらすべてに小文字の拡張子が付いていることを前提としています.csv
。
その後、それらのデータフレームを単一のデータフレームに結合する場合はdo.call(rbind,...)
、dplyr::bind_rows()
やを使用して、他の回答のソリューションを参照してくださいdata.table::rbindlist()
。
あまりお勧めできない場合でも、各データフレームを個別のオブジェクトに本当に入れたい場合は、次のようにしてassign
ください。
temp = list.files(pattern="*.csv")
for (i in 1:length(temp)) assign(temp[i], read.csv(temp[i]))
または、なしでassign
、(1)ファイル名をクリーンアップする方法、および(2)使用方法を示すためlist2env
に、以下を試すことができます。
temp = list.files(pattern="*.csv")
list2env(
lapply(setNames(temp, make.names(gsub("*.csv$", "", temp))),
read.csv), envir = .GlobalEnv)
しかし、繰り返しになりますが、それらを単一のリストに残しておく方が良い場合がよくあります。
assign
... を使用してこの回答の更新バージョンを実行する関数を記述しようとしている人は、割り当てられた値をグローバル環境に配置する場合は、を設定してくださいinherits=T
。
スピーディーで簡潔なtidyverse
ソリューション:(Base Rの 2倍以上の速さread.csv
)
tbl <-
list.files(pattern = "*.csv") %>%
map_df(~read_csv(.))
そしてdata.tableさんはfread()
さえ再び半分にそれらのロード時間を削減することができます。(ベースRの 1/4 倍)
library(data.table)
tbl_fread <-
list.files(pattern = "*.csv") %>%
map_df(~fread(.))
stringsAsFactors = FALSE
引数には、データフレームの要因の自由を維持し(とmarbelが指摘するように、デフォルトの設定ですfread
)
型キャストが生意気な場合は、すべての列をcol_types
引数付きの文字にすることができます。
tbl <-
list.files(pattern = "*.csv") %>%
map_df(~read_csv(., col_types = cols(.default = "c")))
サブディレクトリにディップして、最終的にバインドするファイルのリストを作成する場合は、パス名を含め、ファイルを完全な名前でリストに登録してください。これにより、バインド作業を現在のディレクトリの外で行うことができます。(完全なパス名をパスポートのように動作して、ディレクトリ「境界」を越えて移動できるように考える)
tbl <-
list.files(path = "./subdirectory/",
pattern = "*.csv",
full.names = T) %>%
map_df(~read_csv(., col_types = cols(.default = "c")))
map_df(x, f)
do.call("rbind", lapply(x, f))
... と実質的に同じです。
ボーナス機能 - 以下のコメントでNiks機能リクエストごとにレコードにファイル名を追加します。
* filename
各レコードにオリジナルを追加します。
コードの説明:テーブルの最初の読み取り中に各レコードにファイル名を追加する関数を作成します。次に、単純なread_csv()
関数の代わりにその関数を使用します。
read_plus <- function(flnm) {
read_csv(flnm) %>%
mutate(filename = flnm)
}
tbl_with_sources <-
list.files(pattern = "*.csv",
full.names = T) %>%
map_df(~read_plus(.))
(型キャストとサブディレクトリ処理のアプローチは、read_plus()
上記で提案された2番目と3番目のバリアントに示されているのと同じ方法で関数内でも処理できます。)
### Benchmark Code & Results
library(tidyverse)
library(data.table)
library(microbenchmark)
### Base R Approaches
#### Instead of a dataframe, this approach creates a list of lists
#### removed from analysis as this alone doubled analysis time reqd
# lapply_read.delim <- function(path, pattern = "*.csv") {
# temp = list.files(path, pattern, full.names = TRUE)
# myfiles = lapply(temp, read.delim)
# }
#### `read.csv()`
do.call_rbind_read.csv <- function(path, pattern = "*.csv") {
files = list.files(path, pattern, full.names = TRUE)
do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))
}
map_df_read.csv <- function(path, pattern = "*.csv") {
list.files(path, pattern, full.names = TRUE) %>%
map_df(~read.csv(., stringsAsFactors = FALSE))
}
### *dplyr()*
#### `read_csv()`
lapply_read_csv_bind_rows <- function(path, pattern = "*.csv") {
files = list.files(path, pattern, full.names = TRUE)
lapply(files, read_csv) %>% bind_rows()
}
map_df_read_csv <- function(path, pattern = "*.csv") {
list.files(path, pattern, full.names = TRUE) %>%
map_df(~read_csv(., col_types = cols(.default = "c")))
}
### *data.table* / *purrr* hybrid
map_df_fread <- function(path, pattern = "*.csv") {
list.files(path, pattern, full.names = TRUE) %>%
map_df(~fread(.))
}
### *data.table*
rbindlist_fread <- function(path, pattern = "*.csv") {
files = list.files(path, pattern, full.names = TRUE)
rbindlist(lapply(files, function(x) fread(x)))
}
do.call_rbind_fread <- function(path, pattern = "*.csv") {
files = list.files(path, pattern, full.names = TRUE)
do.call(rbind, lapply(files, function(x) fread(x, stringsAsFactors = FALSE)))
}
read_results <- function(dir_size){
microbenchmark(
# lapply_read.delim = lapply_read.delim(dir_size), # too slow to include in benchmarks
do.call_rbind_read.csv = do.call_rbind_read.csv(dir_size),
map_df_read.csv = map_df_read.csv(dir_size),
lapply_read_csv_bind_rows = lapply_read_csv_bind_rows(dir_size),
map_df_read_csv = map_df_read_csv(dir_size),
rbindlist_fread = rbindlist_fread(dir_size),
do.call_rbind_fread = do.call_rbind_fread(dir_size),
map_df_fread = map_df_fread(dir_size),
times = 10L)
}
read_results_lrg_mid_mid <- read_results('./testFolder/500MB_12.5MB_40files')
print(read_results_lrg_mid_mid, digits = 3)
read_results_sml_mic_mny <- read_results('./testFolder/5MB_5KB_1000files/')
read_results_sml_tny_mod <- read_results('./testFolder/5MB_50KB_100files/')
read_results_sml_sml_few <- read_results('./testFolder/5MB_500KB_10files/')
read_results_med_sml_mny <- read_results('./testFolder/50MB_5OKB_1000files')
read_results_med_sml_mod <- read_results('./testFolder/50MB_5OOKB_100files')
read_results_med_med_few <- read_results('./testFolder/50MB_5MB_10files')
read_results_lrg_sml_mny <- read_results('./testFolder/500MB_500KB_1000files')
read_results_lrg_med_mod <- read_results('./testFolder/500MB_5MB_100files')
read_results_lrg_lrg_few <- read_results('./testFolder/500MB_50MB_10files')
read_results_xlg_lrg_mod <- read_results('./testFolder/5000MB_50MB_100files')
print(read_results_sml_mic_mny, digits = 3)
print(read_results_sml_tny_mod, digits = 3)
print(read_results_sml_sml_few, digits = 3)
print(read_results_med_sml_mny, digits = 3)
print(read_results_med_sml_mod, digits = 3)
print(read_results_med_med_few, digits = 3)
print(read_results_lrg_sml_mny, digits = 3)
print(read_results_lrg_med_mod, digits = 3)
print(read_results_lrg_lrg_few, digits = 3)
print(read_results_xlg_lrg_mod, digits = 3)
# display boxplot of my typical use case results & basic machine max load
par(oma = c(0,0,0,0)) # remove overall margins if present
par(mfcol = c(1,1)) # remove grid if present
par(mar = c(12,5,1,1) + 0.1) # to display just a single boxplot with its complete labels
boxplot(read_results_lrg_mid_mid, las = 2, xlab = "", ylab = "Duration (seconds)", main = "40 files @ 12.5MB (500MB)")
boxplot(read_results_xlg_lrg_mod, las = 2, xlab = "", ylab = "Duration (seconds)", main = "100 files @ 50MB (5GB)")
# generate 3x3 grid boxplots
par(oma = c(12,1,1,1)) # margins for the whole 3 x 3 grid plot
par(mfcol = c(3,3)) # create grid (filling down each column)
par(mar = c(1,4,2,1)) # margins for the individual plots in 3 x 3 grid
boxplot(read_results_sml_mic_mny, las = 2, xlab = "", ylab = "Duration (seconds)", main = "1000 files @ 5KB (5MB)", xaxt = 'n')
boxplot(read_results_sml_tny_mod, las = 2, xlab = "", ylab = "Duration (milliseconds)", main = "100 files @ 50KB (5MB)", xaxt = 'n')
boxplot(read_results_sml_sml_few, las = 2, xlab = "", ylab = "Duration (milliseconds)", main = "10 files @ 500KB (5MB)",)
boxplot(read_results_med_sml_mny, las = 2, xlab = "", ylab = "Duration (microseconds) ", main = "1000 files @ 50KB (50MB)", xaxt = 'n')
boxplot(read_results_med_sml_mod, las = 2, xlab = "", ylab = "Duration (microseconds)", main = "100 files @ 500KB (50MB)", xaxt = 'n')
boxplot(read_results_med_med_few, las = 2, xlab = "", ylab = "Duration (seconds)", main = "10 files @ 5MB (50MB)")
boxplot(read_results_lrg_sml_mny, las = 2, xlab = "", ylab = "Duration (seconds)", main = "1000 files @ 500KB (500MB)", xaxt = 'n')
boxplot(read_results_lrg_med_mod, las = 2, xlab = "", ylab = "Duration (seconds)", main = "100 files @ 5MB (500MB)", xaxt = 'n')
boxplot(read_results_lrg_lrg_few, las = 2, xlab = "", ylab = "Duration (seconds)", main = "10 files @ 50MB (500MB)")
行:ファイル数(1000、100、10)
列:最終データフレームサイズ(5MB、50MB、500MB)
(画像をクリックして元のサイズを表示)
ベースRの結果は、purrrとdplyrのCライブラリをもたらすオーバーヘッドが、大規模な処理タスクを実行するときに観察されるパフォーマンスの向上を上回る、最小のユースケースに適しています。
独自のテストを実行したい場合は、このbashスクリプトが役立ちます。
for ((i=1; i<=$2; i++)); do
cp "$1" "${1:0:8}_${i}.csv";
done
bash what_you_name_this_script.sh "fileName_you_want_copied" 100
(ファイル名の最初の8文字とアンダースコアの後に)番号が付けられたファイルの100コピーが作成されます。
特別な感謝を込めて:
map_df()
ここに紹介してくれたJake Kaupp 。fread()
。(私は勉強する必要がありdata.table
ます。)readAddFilename <- function(flnm) { read_csv(flnm) %>% mutate(filename = flnm) }
して、今そこにあるmap_df
単純な読み取り専用の代わりにそれをドロップしread_csv()
ます。上記のエントリを更新して、機能と、質問がまだある場合や参考になると思われる場合にパイプにどのように適合するかを示します。
read_csv
は、それよりもはるかに遅いことfread
です。あなたが何かがより速いと言うつもりなら、私はベンチマークを含めます。1つのアイデアは、1 GBのファイルを30個作成して読み取ることです。これは、パフォーマンスが重要な場合です。
fread()
とdplyrさんread_csv()
:14.2 19.9対秒。TBH、私はベースRとdplyrを比較するだけでしたが、のread_csv()
約2〜4倍速いためread.csv()
、ベンチマークは必要ないようでした。ただしfread()
、より完全なベンチマーク結果を確認するために、少しの間、少しの間、一時停止するのは興味深いことです。再度、感謝します!
R baseを使用して.csvファイルを1つのdata.frameに変換するオプションと、Rでファイルを読み取るために利用可能なパッケージの一部を次に示します。
これは、以下のオプションよりも低速です。
# Get the files names
files = list.files(pattern="*.csv")
# First apply read.csv, then rbind
myfiles = do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))
編集: - data.table
およびを使用してさらにいくつかの追加の選択肢readr
fread()
関数であるバージョン、data.table
パッケージ。これはRの中で最速のオプションです。
library(data.table)
DT = do.call(rbind, lapply(files, fread))
# The same using `rbindlist`
DT = rbindlist(lapply(files, fread))
csvファイルを読み取るための別のパッケージであるreadrの使用。fread
ベースRよりも低速で高速ですが、機能は異なります。
library(readr)
library(dplyr)
tbl = lapply(files, read_csv) %>% bind_rows()
data.table
パフォーマンスを向上させるバージョンを追加しました。
do.call
lapply
Rでやその他のループ構造を使用するだけでなく、CSVファイルを1つのファイルにマージできます。
Unixでは、ファイルにヘッダーがない場合、次のように簡単です。
cat *.csv > all.csv
または、ヘッダーがあり、ヘッダーとヘッダーのみに一致する文字列を見つけることができる場合(つまり、ヘッダー行がすべて「Age」で始まる場合)、次のようにします。
cat *.csv | grep -v ^Age > all.csv
私は、Windowsにあなたがこれを行うことができると思うCOPY
とSEARCH
(またはFIND
DOSコマンドボックスからか何か)が、なぜインストールしないでcygwin
Unixコマンドシェルのパワーをしてもらいますか?
Git
ますか?
これは、すべてのcsvファイルをRに読み込むために開発したコードです。各csvファイルのデータフレームを個別に作成し、そのデータフレームにファイルの元の名前を付けます(スペースと.csvを削除します)。
path <- "C:/Users/cfees/My Box Files/Fitness/"
files <- list.files(path=path, pattern="*.csv")
for(file in files)
{
perpos <- which(strsplit(file, "")[[1]]==".")
assign(
gsub(" ","",substr(file, 1, perpos-1)),
read.csv(paste(path,file,sep="")))
}
@ A5C1D2H2I1M1N2O1R2T1、@ leerssej、@ marbelによる上位3つの回答はすべて基本的に同じです。各ファイルにfreadを適用し、結果のdata.tablesをrbind / rbindlistします。通常はrbindlist(lapply(list.files("*.csv"),fread))
フォームを使用します。
これは他のR内部の代替よりも優れており、少数の大きなcsvの場合は問題ありませんが、速度が問題になる多数の小さなcsvの場合は最適ではありません。その場合、cat
@ Spacedmanが4番目にランク付けされた回答で示唆しているように、最初に使用する方がはるかに速くなる可能性があります。R内からこれを行う方法の詳細をいくつか追加します。
x = fread(cmd='cat *.csv', header=F)
ただし、各csvにヘッダーがある場合はどうなりますか?
x = fread(cmd="awk 'NR==1||FNR!=1' *.csv", header=T)
そして、*.csv
シェルグロブが失敗するほど多くのファイルがある場合はどうでしょうか?
x = fread(cmd='find . -name "*.csv" | xargs cat', header=F)
そして、すべてのファイルにヘッダーがあり、ファイルが多すぎる場合はどうなりますか?
header = fread(cmd='find . -name "*.csv" | head -n1 | xargs head -n1', header=T)
x = fread(cmd='find . -name "*.csv" | xargs tail -q -n+2', header=F)
names(x) = names(header)
そして、結果の連結されたcsvがシステムメモリに対して大きすぎる場合はどうなりますか?
system('find . -name "*.csv" | xargs cat > combined.csv')
x = fread('combined.csv', header=F)
ヘッダーあり?
system('find . -name "*.csv" | head -n1 | xargs head -n1 > combined.csv')
system('find . -name "*.csv" | xargs tail -q -n+2 >> combined.csv')
x = fread('combined.csv', header=T)
最後に、ディレクトリ内のすべての.csvではなく、特定のファイルセットが必要な場合はどうでしょうか。(また、それらにはすべてヘッダーがあります。)(これは私の使用例です。)
fread(text=paste0(system("xargs cat|awk 'NR==1||$1!=\"<column one name>\"'",input=paths,intern=T),collapse="\n"),header=T,sep="\t")
そして、これは普通のfread xargs catとほぼ同じ速度です:)
注:data.table v1.11.6(2018年9月19日)より前の場合は、cmd=
fromを省略しfread(cmd=
ます。
補遺:シリアルlapplyの代わりに並列ライブラリのmclapplyを使用すると、たとえばrbindlist(lapply(list.files("*.csv"),fread))
rbindlist lapply freadよりもはるかに高速になります。
121401 CSVを単一のdata.tableに読み込む時間。各csvには3つの列、1つのヘッダー行、および平均で4.510行があります。マシンは96コアのGCP VMです。
rbindlist lapply fread 234.172s 247.513s 256.349s
rbindlist mclapply fread 15.223s 9.558s 9.292s
fread xargs cat 4.761s 4.259s 5.095s
要約すると、速度に興味があり、多くのファイルと多くのコアがある場合、fread xargs catは、上位3つの回答の中で最速のソリューションよりも約50倍高速です。
私の見解では、他のほとんどの回答はによって廃止されていますrio::import_list
。これは簡潔なワンライナーです:
library(rio)
my_data <- import_list(dir("path_to_directory", pattern = ".csv", rbind = TRUE))
追加の引数はに渡されrio::import
ます。rio
ほぼすべてのファイル形式のRを扱うことができます読んで、それが使用できるdata.table
のfread
それはあまりにも高速である必要がありますので、可能な場合。
このオプションをplyr::ldply
有効にすると、.parallel
400個のcsvファイルをそれぞれ約30〜40 MBずつ読み取ることで、速度が約50%向上します。例には、テキストプログレスバーが含まれます。
library(plyr)
library(data.table)
library(doSNOW)
csv.list <- list.files(path="t:/data", pattern=".csv$", full.names=TRUE)
cl <- makeCluster(4)
registerDoSNOW(cl)
pb <- txtProgressBar(max=length(csv.list), style=3)
pbu <- function(i) setTxtProgressBar(pb, i)
dt <- setDT(ldply(csv.list, fread, .parallel=TRUE, .paropts=list(.options.snow=list(progress=pbu))))
stopCluster(cl)
fread
またはに追加の引数をどのように渡しますかuser-defined functions
?ありがとう!
?ldply
ショー...
、他の引数はに渡さ.fun
。どちらfread, skip = 100
かfunction(x) fread(x, skip = 100)
を使用するか、機能する
function(x) fread(x, skip = 100)
私にとっては使用できませんでしたが、裸の関数名の後に追加の引数を指定するとうまくいきました。再度、感謝します!
dnlbrkのコメントを基にすると、大きなファイルの場合、assignはlist2envよりもかなり高速になります。
library(readr)
library(stringr)
List_of_file_paths <- list.files(path ="C:/Users/Anon/Documents/Folder_with_csv_files/", pattern = ".csv", all.files = TRUE, full.names = TRUE)
full.names引数をtrueに設定すると、各ファイルへのフルパスがファイルリスト内の個別の文字列として取得されます。たとえば、List_of_file_paths [1]は "C:/ Users / Anon / Documents / Folder_with_csv_files / file1.csv "
for(f in 1:length(List_of_filepaths)) {
file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
file_df <- read_csv(List_of_filepaths[f])
assign( x = file_name, value = file_df, envir = .GlobalEnv)
}
read_csvの代わりに、data.tableパッケージのfreadまたはベースR read.csvを使用できます。file_nameステップでは、名前を整頓して、各データフレームがファイルへのフルパスで名前が残らないようにすることができます。ループを拡張して、グローバル環境に転送する前に、データテーブルに対してさらに処理を行うことができます。次に例を示します。
for(f in 1:length(List_of_filepaths)) {
file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
file_df <- read_csv(List_of_filepaths[f])
file_df <- file_df[,1:3] #if you only need the first three columns
assign( x = file_name, value = file_df, envir = .GlobalEnv)
}
これは、複数のファイルを読み取り、それらを1つのデータフレームに結合するための具体的な例です。
path<- file.path("C:/folder/subfolder")
files <- list.files(path=path, pattern="/*.csv",full.names = T)
library(data.table)
data = do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))
rbindlist()
data.table
次のコードを使用すると、コンピューターに多くのコアがある限り、ビッグデータの速度が最も速くなります。
if (!require("pacman")) install.packages("pacman")
pacman::p_load(doParallel, data.table, stringr)
# get the file name
dir() %>% str_subset("\\.csv$") -> fn
# use parallel setting
(cl <- detectCores() %>%
makeCluster()) %>%
registerDoParallel()
# read and bind all files together
system.time({
big_df <- foreach(
i = fn,
.packages = "data.table"
) %dopar%
{
fread(i, colClasses = "character")
} %>%
rbindlist(fill = TRUE)
})
# end of parallel work
stopImplicitCluster(cl)
2020/04/16に更新:並列計算に使用できる新しいパッケージを見つけたので、次のコードを使用して代替ソリューションを提供します。
if (!require("pacman")) install.packages("pacman")
pacman::p_load(future.apply, data.table, stringr)
# get the file name
dir() %>% str_subset("\\.csv$") -> fn
plan(multiprocess)
future_lapply(fn,fread,colClasses = "character") %>%
rbindlist(fill = TRUE) -> res
# res is the merged data.table
list.files()
、lapply()
およびlist2env()
(またはfs::dir_ls()
、purrr::map()
およびlist2env()
)を使用するアプローチが好きです。それはシンプルで柔軟なようです。
または、小さなパッケージ{ tor }(to-R)を試すこともできます。デフォルトでは、作業ディレクトリからリスト(list_*()
バリアント)またはグローバル環境(load_*()
バリアント)にファイルをインポートします。
たとえば、次のコマンドを使用して、作業ディレクトリからすべての.csvファイルをリストに読み取りますtor::list_csv()
。
library(tor)
dir()
#> [1] "_pkgdown.yml" "cran-comments.md" "csv1.csv"
#> [4] "csv2.csv" "datasets" "DESCRIPTION"
#> [7] "docs" "inst" "LICENSE.md"
#> [10] "man" "NAMESPACE" "NEWS.md"
#> [13] "R" "README.md" "README.Rmd"
#> [16] "tests" "tmp.R" "tor.Rproj"
list_csv()
#> $csv1
#> x
#> 1 1
#> 2 2
#>
#> $csv2
#> y
#> 1 a
#> 2 b
そして今私はこれらのファイルを私のグローバル環境にロードしますtor::load_csv()
:
# The working directory contains .csv files
dir()
#> [1] "_pkgdown.yml" "cran-comments.md" "CRAN-RELEASE"
#> [4] "csv1.csv" "csv2.csv" "datasets"
#> [7] "DESCRIPTION" "docs" "inst"
#> [10] "LICENSE.md" "man" "NAMESPACE"
#> [13] "NEWS.md" "R" "README.md"
#> [16] "README.Rmd" "tests" "tmp.R"
#> [19] "tor.Rproj"
load_csv()
# Each file is now available as a dataframe in the global environment
csv1
#> x
#> 1 1
#> 2 2
csv2
#> y
#> 1 a
#> 2 b
特定のファイルを読み取る必要がある場合は、ファイルパスをregexp
、ignore.case
およびと一致させることができますinvert
。
さらに柔軟性を高めるためにlist_any()
。引数を介してリーダー関数を提供できます.f
。
(path_csv <- tor_example("csv"))
#> [1] "C:/Users/LeporeM/Documents/R/R-3.5.2/library/tor/extdata/csv"
dir(path_csv)
#> [1] "file1.csv" "file2.csv"
list_any(path_csv, read.csv)
#> $file1
#> x
#> 1 1
#> 2 2
#>
#> $file2
#> y
#> 1 a
#> 2 b
...またはラムダ関数内で追加の引数を渡します。
path_csv %>%
list_any(readr::read_csv, skip = 1)
#> Parsed with column specification:
#> cols(
#> `1` = col_double()
#> )
#> Parsed with column specification:
#> cols(
#> a = col_character()
#> )
#> $file1
#> # A tibble: 1 x 1
#> `1`
#> <dbl>
#> 1 2
#>
#> $file2
#> # A tibble: 1 x 1
#> a
#> <chr>
#> 1 b
path_csv %>%
list_any(~read.csv(., stringsAsFactors = FALSE)) %>%
map(as_tibble)
#> $file1
#> # A tibble: 2 x 1
#> x
#> <int>
#> 1 1
#> 2 2
#>
#> $file2
#> # A tibble: 2 x 1
#> y
#> <chr>
#> 1 a
#> 2 b
この機能をstackoverflow Rパッケージに追加するように依頼されました。それが小さなパッケージである(そしてサードパーティのパッケージに依存することはできない)ことを考えると、ここに私が思いついたものがあります:
#' Bulk import data files
#'
#' Read in each file at a path and then unnest them. Defaults to csv format.
#'
#' @param path a character vector of full path names
#' @param pattern an optional \link[=regex]{regular expression}. Only file names which match the regular expression will be returned.
#' @param reader a function that can read data from a file name.
#' @param ... optional arguments to pass to the reader function (eg \code{stringsAsFactors}).
#' @param reducer a function to unnest the individual data files. Use I to retain the nested structure.
#' @param recursive logical. Should the listing recurse into directories?
#'
#' @author Neal Fultz
#' @references \url{/programming/11433432/how-to-import-multiple-csv-files-at-once}
#'
#' @importFrom utils read.csv
#' @export
read.directory <- function(path='.', pattern=NULL, reader=read.csv, ...,
reducer=function(dfs) do.call(rbind.data.frame, dfs), recursive=FALSE) {
files <- list.files(path, pattern, full.names = TRUE, recursive = recursive)
reducer(lapply(files, reader, ...))
}
リーダーとレデューサー関数をパラメーター化することにより、人々は、必要に応じてdata.tableまたはdplyrを使用できます。