Как импортировать несколько файлов.csv одновременно?
Предположим, у нас есть папка, содержащая несколько файлов data.csv, каждый из которых содержит одинаковое количество переменных, но каждый из них в разное время. Есть ли способ в R импортировать их все одновременно вместо того, чтобы импортировать их все по отдельности?
Моя проблема в том, что у меня есть около 2000 файлов данных для импорта, и мне нужно импортировать их по отдельности, просто используя код:
read.delim(file="filename", header=TRUE, sep="\t")
не очень эффективно.
21 ответ
Что-то вроде следующего должно привести к тому, что каждый фрейм данных будет отдельным элементом в одном списке:
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)
Но опять же, часто лучше оставить их в одном списке.
Быстрое и сжатое tidyverse
Решение:
(более чем в два раза быстрее, чем Base R read.csv
)
tbl <-
list.files(pattern = "*.csv") %>%
map_df(~read_csv(.))
и data.table 's fread()
может даже сократить время загрузки вдвое. (для 1/4 базового R раз)
library(data.table)
tbl_fread <-
list.files(pattern = "*.csv") %>%
map_df(~fread(., stringsAsFactors = FALSE))
stringsAsFactors = FALSE
Аргумент сохраняет фактор кадра данных свободным.
Если приведение типов является нахальным, вы можете сделать так, чтобы все столбцы были символами с 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()
функционируют так же, как показано во втором и третьем вариантах, предложенных выше.)
### 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(., stringsAsFactors = FALSE))
}
### *data.table*
rbindlist_fread <- function(path, pattern = "*.csv") {
files = list.files(path, pattern, full.names = TRUE)
rbindlist(lapply(files, function(x) fread(x, stringsAsFactors = FALSE)))
}
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)
Столбцы: окончательный размер кадра данных (5 МБ, 50 МБ, 500 МБ)
(нажмите на изображение, чтобы посмотреть оригинальный размер)
Базовые результаты R лучше для наименьших случаев использования, когда издержки, связанные с переносом библиотек C purrr и dplyr, перевешивают выигрыш в производительности, который наблюдается при выполнении более масштабных задач обработки.
если вы хотите запускать свои собственные тесты, вам может пригодиться этот скрипт 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
создаст 100 копий вашего файла с последовательной нумерацией (после начальных 8 символов имени файла и подчеркивания).
Атрибуты и благодарности
С особой благодарностью:
- Тайлер Ринкер и Акрун за демонстрацию микробенчмарка.
- Джейка Кауппа за то, что он представил меня
map_df()
здесь - Дэвида Маклафлина (David McLaughlin) за полезные отзывы об улучшении визуализации и обсуждении / подтверждении инверсий производительности, наблюдаемых в небольшом файле, результаты анализа небольших данных.
Вот еще один вариант преобразования файлов.csv в один файл 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
пакет. Это должен быть самый быстрый вариант.
library(data.table)
DT = do.call(rbind, lapply(files, fread))
# The same using `rbindlist`
DT = rbindlist(lapply(files, fread))
Использование readr, нового пакета Hadley для чтения CSV-файлов. Немного медленнее, чем фред, но с другой функциональностью.
library(readr)
library(dplyr)
tbl = lapply(files, read_csv) %>% bind_rows()
Три самых популярных ответа от @A5C1D2H2I1M1N2O1R2T1, @leerssej и @marbel, по сути, одинаковы: примените fread к каждому файлу, затем rbind/rbindlist выведите итоговые таблицы data.tables. Я обычно использую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
оболочка glob не работает?
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")
и это примерно такая же скорость, как у plain fread xargs cat:)
Примечание: для data.table до версии 1.11.6 (19 сентября 2018 г.) опустите cmd=
от fread(cmd=
.
Приложение: использование mclapply параллельной библиотеки вместо последовательного lapply, например, rbindlist(lapply(list.files("*.csv"),fread))
также намного быстрее, чем rbindlist lapply fread.
Пришло время прочитать 121401 csvs в единую таблицу data.table. Каждый CSV имеет 3 столбца, одну строку заголовка и в среднем 4,510 строк. Машина представляет собой виртуальную машину GCP с 96 ядрами:
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 примерно в 50 раз быстрее, чем самое быстрое решение из трех лучших ответов.
А также используя lapply
или какая-либо другая зацикливая конструкция в R, вы можете объединить ваши CSV-файлы в один файл.
В Unix, если файлы не имеют заголовков, это так же просто, как:
cat *.csv > all.csv
или если есть заголовки, и вы можете найти строку, которая соответствует заголовкам и только заголовкам (т.е. предположим, что все строки заголовка начинаются с "Age"), вы должны сделать:
cat *.csv | grep -v ^Age > all.csv
Я думаю, что в Windows вы могли бы сделать это с COPY
а также SEARCH
(или же FIND
или что-то) из командной строки DOS, но почему бы не установить cygwin
и получить мощность командной оболочки Unix?
Это код, который я разработал для чтения всех 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="")))
}
На мой взгляд, большинство других ответов устарели rio::import_list
, который является кратким однострочником:
library(rio)
my_data <- import_list(dir("path_to_directory", pattern = ".csv", rbind = TRUE))
Любые дополнительные аргументы передаются rio::import
, rio
может иметь дело практически с любым форматом файла R может читать, и он использует data.table
"s fread
где это возможно, так что это должно быть быстро.
С помощью plyr::ldply
увеличение скорости примерно на 50% .parallel
Вариант при чтении 400 CSV-файлов примерно 30-40 МБ каждый. Пример включает текстовый индикатор выполнения.
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)
С помощью
purrr
и включая идентификаторы файлов в виде столбца:
library(tidyverse)
p <- "my/directory"
files <- list.files(p, pattern="csv", full.names=TRUE) %>%
set_names()
merged <- files %>% map_dfr(read_csv, .id="filename")
Без
set_names()
,
.id=
будет использовать целочисленные индикаторы вместо фактических имен файлов.
Если вам нужно только короткое имя файла без полного пути:
merged <- merged %>% mutate(filename=basename(filename))
Это мой конкретный пример чтения нескольких файлов и объединения их в 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)))
Опираясь на комментарий 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 пакета fread или base R read.csv вместо 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)
}
Начиная с readr 2.0.0, вы можете читать сразу несколько файлов, просто предоставив список их путей к
file
аргумент. Вот пример, показывающий это с
readr::read_csv()
.
packageVersion("readr")
#> [1] '2.0.1'
library(readr)
library(fs)
# create files to read in
write_csv(read_csv("1, 2 \n 3, 4", col_names = c("x", "y")), file = "file1.csv")
write_csv(read_csv("5, 6 \n 7, 8", col_names = c("x", "y")), file = "file2.csv")
# get a list of files
files <- dir_ls(".", glob = "file*csv")
files
#> file1.csv file2.csv
# read them in at once
# record paths in a column called filename
read_csv(files, id = "filename")
#> # A tibble: 4 × 3
#> filename x y
#> <chr> <dbl> <dbl>
#> 1 file1.csv 1 2
#> 2 file1.csv 3 4
#> 3 file2.csv 5 6
#> 4 file2.csv 7 8
Создано 16.09.2021 пакетом REPEX (v2.0.1)
Следующие коды должны обеспечить максимальную скорость обработки больших данных, если на вашем компьютере много ядер:
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
Было предложено добавить эту функцию в пакет stackru R. Учитывая, что это пакет tinyverse (и он не может зависеть от сторонних пакетов), вот что я придумал:
#' 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{https://stackru.com/questions/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, если они того пожелают, или просто использовать базовые функции R, которые подходят для небольших наборов данных.
Мне нравится подход, использующий 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
Обновление «быстрого и лаконичного» решения tidyverse от @leerssej , посколькуmap_df
было заменено:
tbl <-
list.files(pattern = "*.csv") |>
map((\(fn) read_csv(fn)) |>
list_rbind()
Мой ответ на принятый ответ немного быстрее и удаляет .csv
от имени объекта в R.
temp = list.files(pattern="*.csv")
for (i in 1:length(temp)) assign(gsub(".csv", "", temp[i]), read_csv(temp[i]))
Опирается на readr
пакет (т.е. library(readr)
). Вы могли бы сделать что-то подобное с data.table
если ты желал.
Вы можете использовать превосходное sparklyr
пакет для этого:
# RStudio will help you get set-up with the Spark dependencies
library(sparklyr)
library(dplyr)
sc <- spark_connect(master = "local", version = "2.0.2")
df <- spark_read_csv(sc,
"dummy",
"file:////Users/bob/dev/data/results/*/*/*-metrics.csv") %>%
collect()
Если вы хотите собрать разные CSV-файлы в один data.frame, вы можете использовать следующее. обратите внимание, что data.frame "x" должен быть создан заранее.
temp <- list.files(pattern="*.csv")
for (i in 1:length(temp)) {
temp2 = read.csv(temp[i], header = TRUE)
x <- rbind(x,temp2)
}
Я успешно использую это:
xlist<-list.files(pattern = "*.csv")
for(i in xlist) {
x <- read.csv((i))
assign(i, x)
}
Это часть моего сценария.
#This cycle read the files in a directory and assign the filenames to datasets
files <- list.files(pattern=".csv$")
for(i in files) {
X <- read.table(i, header=TRUE)
SN<-X$A/X$B
X<-cbind(X,SN)
ds<-paste("data_",i, sep="")#this add "data_" to the name of file
ds<-substr(ds, 1, nchar(ds)-4)#remove the last 4 char (.csv)
assign(ds, X)
}