답변:
다음과 같은 결과는 각 데이터 프레임을 단일 목록에서 별도의 요소로 만들어야합니다.
temp = list.files(pattern="*.csv")
myfiles = lapply(temp, read.delim)
이는 CSV가 단일 디렉토리 (현재 작업 디렉토리)에 있고 모든 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 보다 두 배 이상 빠름 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(.))
(typecasting 및 하위 디렉토리 처리 방식은 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(.))
}
### *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()
여기 .fread()
. (에 대해 공부해야합니다 data.table
.)readAddFilename <- function(flnm) { read_csv(flnm) %>% mutate(filename = flnm) }
그런 단지에 그 드롭 map_df
대신 간단한의 읽기 전용 read_csv()
지금 거기입니다. 위의 항목을 업데이트하여 기능과 여전히 궁금한 점이 있거나 도움이 될 것 같으면 파이프에 어떻게 적용되는지 보여줄 수 있습니다.
read_csv
는보다 훨씬 느리다는 것 fread
입니다. 무언가 더 빠르다고 말하면 벤치 마크를 포함시킵니다. 한 가지 아이디어는 30 개의 1GB 파일을 만들고 읽는 것입니다. 성능이 중요한 경우입니다.
fread()
및 dplyr 의 read_csv()
: 14.2 19.9 대 초. TBH, 나는 기본 R을 dplyr과 비교하고 있었기 때문에 벤치마킹이 필요하지 않은 것 read_csv()
보다 약 2-4 배 빠릅니다 read.csv()
. 그러나 fread()
보다 완전한 벤치 마크 결과를 확인하기 위해 소용돌이를 치고 일시 중지하는 것이 흥미로 웠습니다 . 다시 감사합니다!
다음은 R base를 사용하여 .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
패키지. 이것은 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 파일을 하나의 파일로 병합 할 수 있습니다.
유닉스에서 파일에 헤더가 없으면 다음과 같이 쉽습니다.
cat *.csv > all.csv
또는 헤더가 있고 헤더와 헤더 만 일치하는 문자열을 찾을 수있는 경우 (예 : 헤더 행이 모두 "Age"로 시작한다고 가정) 다음을 수행하십시오.
cat *.csv | grep -v ^Age > all.csv
내가 Windows에서 당신이 할 수 있다고 생각 COPY
하고 SEARCH
(또는 FIND
또는 무언가) DOS 명령 상자에서, 그런데 왜 설치하지 cygwin
와 유닉스 명령 셸의 힘을 얻을?
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를 적용한 다음 결과 데이터를 rbind / rbindlist합니다. 나는 보통rbindlist(lapply(list.files("*.csv"),fread))
양식을 .
이것은 다른 R-internal 대안보다 낫고 많은 수의 큰 csvs에는 적합하지만 속도가 중요 할 때 많은 수의 작은 csvs에는 적합하지 않습니다. 이 경우 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 pre-v1.11.6 (2018 년 9 월 19 일)의 경우 cmd=
from을 생략하십시오 fread(cmd=
.
부록 : 직렬 랩핑 대신 병렬 라이브러리의 mclapply 사용 (예 : rbindlist(lapply(list.files("*.csv"),fread))
rbindlist lapply fread보다 훨씬 빠릅니다.
121401 csvs를 단일 데이터 테이블로 읽을 시간입니다. 각 csv에는 3 개의 열, 하나의 헤더 행 및 평균 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
요약하자면, 속도에 관심이 있고 많은 파일과 많은 코어를 가지고 있다면, far 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
에이블하여 50 %의 속도 증가 정도가 .parallel
약 30-40메가바이트 각각 400 개 CSV 파일을 읽는 동안 옵션. 예는 텍스트 진행 표시 줄을 포함합니다.
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 또는 base 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)
}
이것은 여러 파일을 읽고 하나의 데이터 프레임으로 결합하는 구체적인 예입니다.
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
... 또는 lambda 함수 내부를 통해 추가 인수를 전달하십시오.
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을 사용하거나 더 작은 데이터 세트에 적합한 기본 R 기능을 사용할 수 있습니다.