Hızlı ve özlü bir tidyverse
çözüm: ( Base R'lerin iki katından daha hızlı read.csv
)
tbl <-
list.files(pattern = "*.csv") %>%
map_df(~read_csv(.))
ve data.table 'lar fread()
bu yükleme sürelerini tekrar yarıya indirebilir. ( Base R sürelerinin 1 / 4'ü için )
library(data.table)
tbl_fread <-
list.files(pattern = "*.csv") %>%
map_df(~fread(.))
stringsAsFactors = FALSE
Argüman, dataframe faktörü serbest tutar (ve mermer çıkış noktaları olarak, varsayılan ayardır fread
)
Yazım hatası arsız ise, tüm sütunları col_types
argümanla karakter olarak zorlayabilirsiniz .
tbl <-
list.files(pattern = "*.csv") %>%
map_df(~read_csv(., col_types = cols(.default = "c")))
Sonunda bağlanacak dosya listenizi oluşturmak için alt dizinlere daldırmak istiyorsanız, yol adını eklediğinizden ve dosyaları listenizde tam adlarıyla kaydettiğinizden emin olun. Bu, ciltleme çalışmasının geçerli dizinin dışında devam etmesini sağlar. (Tam yol adlarının, 'sınırlar' dizini boyunca hareket etmesine izin vermek için pasaport gibi çalıştığını düşünmek.)
tbl <-
list.files(path = "./subdirectory/",
pattern = "*.csv",
full.names = T) %>%
map_df(~read_csv(., col_types = cols(.default = "c")))
Hadley'in burada açıkladığı gibi (yaklaşık yarım):
map_df(x, f)
etkili bir şekilde aynı do.call("rbind", lapply(x, f))
....
Bonus Özellik - aşağıdaki yorumlarda Niks özellik isteği başına kayıtlara dosya adları ekleme:
* filename
Her kayda orijinal ekleyin .
Kod açıklandı: tabloların ilk okunması sırasında her kayda dosya adını eklemek için bir işlev yapın. Ardından basit read_csv()
işlev yerine bu işlevi kullanın .
read_plus <- function(flnm) {
read_csv(flnm) %>%
mutate(filename = flnm)
}
tbl_with_sources <-
list.files(pattern = "*.csv",
full.names = T) %>%
map_df(~read_plus(.))
(Yazım ve alt dizin işleme yaklaşımları, read_plus()
işlevin içinde, yukarıda önerilen ikinci ve üçüncü varyantlarda gösterildiği gibi de ele alınabilir .)
### 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)")
Orta Kullanım Davası
Daha Büyük Kullanım Durumu
Çeşitli Kullanım Durumları
Satırlar: dosya sayısı (1000, 100, 10)
Sütunlar: son veri çerçevesi boyutu (5MB, 50MB, 500MB)
(orijinal boyutunu görüntülemek için resme tıklayın)
Temel R sonuçları, daha büyük ölçekli işleme görevleri gerçekleştirilirken gözlenen performans kazanımlarından ağır basmak için purrr ve dplyr C kütüphanelerini getirme yükünün daha küçük olduğu durumlarda daha iyidir.
kendi testlerinizi yapmak istiyorsanız bu bash betiğini yararlı bulabilirsiniz.
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
dosyanızın sırayla numaralandırılmış 100 kopyasını oluşturur (dosya adının ilk 8 karakterinden ve alt çizgiden sonra).
Atıflar ve Takdirler
Özel teşekkürler:
- Tyler Rinker ve Akrun , mikrobenchmark gösterdikleri için.
- Jake Kaupp beni
map_df()
buraya tanıttığı için .
- Görselleştirmeleri iyileştirme ve küçük dosyada gözlemlenen performans terslemelerini tartışma / onaylama konusunda yararlı geri bildirim için David McLaughlin, küçük veri çerçevesi analiz sonuçları.
- için varsayılan davranışı belirtmek amacıyla işaretleyin
fread()
. (Üzerinde çalışmam gerek data.table
.)