Fast reading and combining several files using data.table (with fread)
I've re-written the code to do this way too many times.. Finally rolled it into a handy function, below.
data.table_fread_mult <- function(filepaths = NULL, dir = NULL, recursive = FALSE, pattern = NULL, fileCol = FALSE, ...){
# fread multiple filepaths and then combine the results into a single data.table
# This function has two interfaces: either
# 1) provide `filepaths` as a character vector of filepaths to read or
# 2) provide `dir` (and optionally `pattern` and `recursive`) to identify the directory to read from
# If fileCol = TRUE, result will incude a column called File with the full source file path of each record
# ... should be arguments to pass on to fread()
# `pattern` is an optional regular expression to match files (e.g. pattern='csv$' matches files ending with 'csv')
if(!is.null(filepaths) & (!is.null(dir) | !is.null(pattern))){
stop("If `filepaths` is given, `dir` and `pattern` should be NULL")
} else if(is.null(filepaths) & is.null(dir)){
stop("If `filepaths` is not given, `dir` should be given")
}
# If filepaths isn't given, build it from dir, recursive, pattern
if(is.null(filepaths)){
filepaths <- list.files(
path = dir,
full.names = TRUE,
recursive = recursive,
pattern = pattern
)
}
# Read and combine files
if(fileCol){
return(rbindlist(lapply(filepaths, function(x) fread(x, ...)[, File := x]), use.names = TRUE))
} else{
return(rbindlist(lapply(filepaths, fread, ...), use.names = TRUE))
}
}
Use rbindlist()
which is designed to rbind
a list
of data.table
's together...
mylist <- lapply(all.files, readdata)
mydata <- rbindlist( mylist )
And as @Roland says, do not set the key in each iteration of your function!
So in summary, this is best :
l <- lapply(all.files, fread, sep=",")
dt <- rbindlist( l )
setkey( dt , ID, date )