매우 큰 테이블을 데이터 프레임으로 빠르게 읽기


503

R의 데이터 프레임으로로드 할 매우 큰 테이블 (3 천만 행)이 있습니다. read.table()편리한 기능이 많이 있지만 구현에 속도가 느려지는 논리가 많이있는 것 같습니다. 내 경우에는 미리 열 유형을 알고 있다고 가정하고 테이블에는 열 머리글이나 행 이름이 없으며 걱정해야 할 병리학 적 문자가 없습니다.

나는 테이블을 사용하여 목록으로 읽는 scan()것이 매우 빠를 수 있다는 것을 알고 있습니다.

datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))

그러나 이것을 데이터 프레임으로 변환하려는 일부 시도는 위의 성능을 6 배 감소시키는 것으로 보입니다.

df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))

더 좋은 방법이 있습니까? 아니면 문제에 대한 완전히 다른 접근법일까요?

답변:


425

몇 년 후 업데이트

이 답변은 오래되었으며 R은 계속 진행했습니다. read.table조금 더 빨리 달리기 만해도 약간의 이점이 있습니다. 옵션은 다음과 같습니다.

  1. csv / tab으로 구분 된 파일에서 R 티 블로 직접 데이터를 가져 오기 위해 vroomtidyverse 패키지에서 사용 vroom.

  2. 사용 freaddata.table직접 R. 페이지로 CSV / 탭으로 구분 된 파일에서 데이터를 가져 오기위한 mnel의 대답 .

  3. 사용 read_tablereadr(4 월 2015 크랑에). 이것은 fread위와 매우 유사 합니다. 링크 의 readme 는 두 기능의 차이점을 설명합니다 ( readr현재는 "1.5-2 배 느리다"고 주장합니다 data.table::fread).

  4. read.csv.rawfrom iotools은 CSV 파일을 빠르게 읽을 수있는 세 번째 옵션을 제공합니다.

  5. 플랫 파일이 아닌 데이터베이스에 최대한 많은 데이터를 저장하려고합니다. (더 나은 영구 저장 매체 일뿐만 아니라 JD Long의 답변에 설명 된대로 패키지 read.csv.sql에서 데이터가 R에 이진 형식으로 R로 전달되는 속도가 빠릅니다.) 임시 SQLite 데이터베이스로 데이터를 가져온 다음 읽습니다. 참조 : 패키지 및 그 반대는 패키지 페이지의 섹션에 따라 다릅니다 . 는 데이터 프레임 인 것처럼 보이지만 실제로는 MonetDB 인 데이터 유형을 제공하여 성능을 향상시킵니다. 기능이있는 데이터를 가져옵니다 . 여러 유형의 데이터베이스에 저장된 데이터로 직접 작업 할 수 있습니다.sqldfRODBCDBIMonetDB.Rmonetdb.read.csvdplyr

  6. 이진 형식으로 데이터를 저장하면 성능을 향상시키는 데 유용 할 수 있습니다. 사용 saveRDS/ readRDS(아래 참조) h5또는 rhdf5HDF5 형식, 또는에 대한 패키지 write_fst/ read_fst로부터 fst패키지로 제공된다.


원래 답변

read.table을 사용하든 scan을 사용하든 몇 가지 간단한 시도가 있습니다.

  1. 설정 nrows= 데이터의 레코드 수 ( nmaxin scan)

  2. comment.char=""주석 해석을 해제 해야합니다 .

  3. colClassesin을 사용하여 각 열의 클래스를 명시 적으로 정의하십시오 read.table.

  4. 설정하면 multi.line=FALSE스캔 성능도 향상 될 수 있습니다.

이 중 어느 것도 작동하지 않으면 프로파일 링 패키지 중 하나를 사용하여 속도를 늦추는 라인을 결정하십시오. 아마도 read.table결과 에 따라 컷 다운 버전을 작성할 수 있습니다 .

다른 대안은 데이터를 R로 읽기 전에 필터링하는 것입니다.

또는 문제가 정기적으로 데이터를 읽어야하는 경우 이러한 방법을 사용하여 데이터를 한 번에 읽은 다음 데이터 프레임을 이진 blob으로 저장하십시오. save saveRDS다음에 더 빨리 검색 할 수 있습니다. load readRDS.


4
팁 Richie에게 감사합니다. 약간의 테스트를 수행했으며 read.table에 대해 nrow 및 colClasses 옵션을 사용하면 성능이 상당히 낮습니다. 예를 들어, ~ 7M 행 테이블을 읽으려면 옵션없이 78 초, 옵션으로 67 초가 걸립니다. (참고 : 테이블에는 1 개의 문자 열, 4 개의 정수 열이 있으며 comment.char = ''및 stringsAsFactors = FALSE를 사용하여 읽습니다). 가능한 경우 save () 및 load ()를 사용하는 것이 좋습니다. 일단 save ()로 저장하면 동일한 테이블을로드하는 데 12 초 밖에 걸리지 않습니다.
eytan

2
은 "깃털"패키지는 파이썬의 팬더 데이터 프레임 좋은 재생하는 새로운 바이너리 형식은
rsoren

4
패키지와 관련하여 게시물을 다시 업데이트해야 할 수도 있습니다 feather. 데이터를 읽는 feather것이보다 빠릅니다 fread. 예를 들어 방금로드 한 4GB 데이터 세트의 read_feather경우보다 약 4.5 배 빠릅니다 fread. 데이터를 저장하는 fwrite것이 여전히 빠릅니다. blog.dominodatalab.com/the-r-data-io-shootout
Z boson

2
그러나 파일 크기는 RDS보다 깃털의 경우 훨씬 큽니다. 압축을 지원한다고 생각하지 않습니다. RDS 파일은 216MB이고 페더 파일은 4GB입니다. 그래서 feather빨리 읽기위한이지만 많이 더 저장 공간을 사용합니다.
Z boson

@Zboson R과 Python에서 모두 액세스 할 수있는 파일에 데이터 프레임을 저장해야하는 경우 feather좋은 옵션입니다. R로만 데이터를 읽을 수있는 경우에만주의하십시오 rds.
Richie Cotton

279

다음은 1.8.7 fread부터 활용하는 예입니다.data.table

예제는 freadWindows XP Core 2 duo E8400의 타이밍과 함께 도움말 페이지에서로 제공됩니다 .

library(data.table)
# Demo speedup
n=1e6
DT = data.table( a=sample(1:1000,n,replace=TRUE),
                 b=sample(1:1000,n,replace=TRUE),
                 c=rnorm(n),
                 d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE),
                 e=rnorm(n),
                 f=sample(1:1000,n,replace=TRUE) )
DT[2,b:=NA_integer_]
DT[4,c:=NA_real_]
DT[3,d:=NA_character_]
DT[5,d:=""]
DT[2,e:=+Inf]
DT[3,e:=-Inf]

표준 판독 테이블

write.table(DT,"test.csv",sep=",",row.names=FALSE,quote=FALSE)
cat("File size (MB):",round(file.info("test.csv")$size/1024^2),"\n")    
## File size (MB): 51 

system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
##    user  system elapsed 
##   24.71    0.15   25.42
# second run will be faster
system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
##    user  system elapsed 
##   17.85    0.07   17.98

최적화 된 읽기 테이블

system.time(DF2 <- read.table("test.csv",header=TRUE,sep=",",quote="",  
                          stringsAsFactors=FALSE,comment.char="",nrows=n,                   
                          colClasses=c("integer","integer","numeric",                        
                                       "character","numeric","integer")))


##    user  system elapsed 
##   10.20    0.03   10.32

펼치다

require(data.table)
system.time(DT <- fread("test.csv"))                                  
 ##    user  system elapsed 
##    3.12    0.01    3.22

sqldf

require(sqldf)

system.time(SQLDF <- read.csv.sql("test.csv",dbname=NULL))             

##    user  system elapsed 
##   12.49    0.09   12.69

# sqldf as on SO

f <- file("test.csv")
system.time(SQLf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))

##    user  system elapsed 
##   10.21    0.47   10.73

ff / ffdf

 require(ff)

 system.time(FFDF <- read.csv.ffdf(file="test.csv",nrows=n))   
 ##    user  system elapsed 
 ##   10.85    0.10   10.99

요약하자면:

##    user  system elapsed  Method
##   24.71    0.15   25.42  read.csv (first time)
##   17.85    0.07   17.98  read.csv (second time)
##   10.20    0.03   10.32  Optimized read.table
##    3.12    0.01    3.22  fread
##   12.49    0.09   12.69  sqldf
##   10.21    0.47   10.73  sqldf on SO
##   10.85    0.10   10.99  ffdf

43
훌륭한 답변이며 벤치마킹은 다른 상황에서 유지됩니다. 로 1 분 이내에 4GB 파일을 읽어보십시오 fread. 기본 R 함수를 사용하여 읽었으며 약 15 시간이 걸렸습니다.
Ari B. Friedman

1
내 벤치 마크는 data.table의 read.csv에 대해 훨씬 더 빠른 속도 이점을 제안합니다. data.table은 표준 R이 아니지만 CRAN에서 제작자가 공유하는 "슬프게" "단지"입니다. 일반적인 R 패키지 목록을 만들 정도로 표준으로 간주되지는 않으며 데이터 프레임을 대체 할 수있는 자격이 훨씬 적습니다. 그것은 많은 장점을 가지고 있지만, 매우 직관적 인 측면도 있습니다. 패키지와 함께 as.data.frame (fread.csv ( "test.csv"))를 사용하여 표준 R 데이터 프레임 세계로 돌아갈 수 있습니다.
ivo Welch

3
@mnel 벤치 마크를 다시 실행하고 포함시킬 수 readr있습니까?
jangorecki 2018

2
두 번째 @jangorecki. 또한, 주어진이 fread지금 진짜 경쟁이 최적화에 대한 벤치 마크를 추가하는 것이 유용 할 수 있습니다 fread사용 - 지정 colClasses
MichaelChirico

1
@jangorecji @ MichaelChirico 주어진 코드는 완전히 생식 가능하기 때문에 판독기를 시뮬레이션하는 것이 간단합니다 ... 코드를 다시 실행하면 내 컴퓨터에서 코드를 다시 실행하면 대부분의 결과가 더 많지 않으면 두 배 빠릅니다. 지금은 시간이 지남에 따라 잘 업데이트 된 버전) ... 판독기와 함께 7 초이지만 두 번째로 실행하면 1 초 미만입니다 (0.66 초), 네트워크에 캐싱이나 병목이 있다고 생각합니다. 여기에 표시된 가장 빠른 솔루션에 대한 두려움은 어떤 이유로 느리게 비교를 위해 내 편에 2 초에 있습니다 (처음으로 8.69 초 실행).
R. Prost

249

처음에는이 질문을 보지 못했고 며칠 후에 비슷한 질문을했습니다. 이전 질문을 중단하려고했지만 여기에 어떻게 사용했는지 설명하기 위해 여기에 답변을 추가 할 것이라고 생각 sqldf()했습니다.

2GB 이상의 텍스트 데이터를 R 데이터 프레임으로 가져 오는 가장 좋은 방법 에 대해서는 약간의 논의 가있었습니다 . 어제 나는 스테이징 영역으로 SQLite로 데이터를 가져오고 SQLite에서 R로 데이터를 가져 오는 데 사용 하는 블로그 게시물을 작성했습니다 sqldf(). <5 분 안에 2GB (3 열, 40mm 행)의 데이터를 가져올 수있었습니다. 대조적으로, read.csv명령은 밤새 실행되었으며 완료되지 않았습니다.

내 테스트 코드는 다음과 같습니다.

테스트 데이터를 설정하십시오.

bigdf <- data.frame(dim=sample(letters, replace=T, 4e7), fact1=rnorm(4e7), fact2=rnorm(4e7, 20, 50))
write.csv(bigdf, 'bigdf.csv', quote = F)

다음 가져 오기 루틴을 실행하기 전에 R을 다시 시작했습니다.

library(sqldf)
f <- file("bigdf.csv")
system.time(bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))

다음 줄을 밤새도록했지만 완료되지 않았습니다.

system.time(big.df <- read.csv('bigdf.csv'))

1
안녕. 모든 데이터와 동시에 사용하도록 설계된 동물원과 같은 다른 패키지의 입력으로 사용하는 방법은 무엇입니까?
skan

@skan 최종 객체는 데이터 프레임입니다. 따라서 동물원과 함께 사용하려면 동물원 개체로 변환해야합니다. 동물원 문서의 예를보고 삽화를보십시오.
JD Long

@JD Long. 안녕, 문제는 당신이 그것을 동물원 개체로 변환 할 때 메모리에 맞추려고한다는 것입니다. 너무 크면 오류가 발생합니다. 또한 동물원 개체의 결과 (예 : 두 계열의 집계)도 너무 크면 SQL 또는 ff 개체 여야합니다.
skan

sqldf의 문제점을 모르겠습니다. 디스크에 2 개의 숫자 열이있는 간단한 1GB 파일을 만들고 DTSQL <-read.csv.sql ( "f2.txt", dbname = tempfile ())을 사용하여 전체 데이터를 메모리에로드하려고합니다. 내일 나는 대신 ff와 revoscaler를 시도 할 것이다.
skan

1
@m은 천이므로 mm은 천 또는 백만입니다. 아마 MM으로 대문자로 입력했을 것입니다. 그러나 다양한 관객이 있다면 약 백만 개의 약어가 누군가에게 혼란을 줄 수 있습니다. 지나치게 장황하게 만들려고해서 더 혼란스럽게해서 죄송합니다! accountingcoach.com/blog/what-does-m-and-mm-stand-for
JD Long

73

이상하게도 중요한 질문이지만 몇 년 동안 질문의 맨 아래 부분에 아무도 대답하지 못했습니다. data.frames 단순히 올바른 속성을 가진 목록이므로 큰 데이터 as.data.frame가있는 경우 목록에 사용 하거나 유사한 것을 원하지 않습니다 . 목록을 데이터 프레임으로 간단히 "전환"하는 것이 훨씬 빠릅니다.

attr(df, "row.names") <- .set_row_names(length(df[[1]]))
class(df) <- "data.frame"

이것은 데이터의 복사본을 만들지 않으므로 다른 모든 방법과 달리 즉시 있습니다. names()그에 따라 목록에 이미 설정 되어 있다고 가정합니다 .

[대량의 데이터를 R에 개인적으로로드하는 경우 개인적으로 열별로 이진 파일로 덤프하여 사용합니다 readBin(). 즉, mmapping 이외의 가장 빠른 방법이며 디스크 속도에 의해서만 제한됩니다. ASCII 파일 구문 분석은 이진 데이터에 비해 본질적으로 느립니다 (C에서도).]


6
사용이 tracmem제안 attr<-하고 class<-내부적으로 메이크업을 복사합니다. bit::setattr또는 data.table::setattr하지 않습니다.
mnel

6
어쩌면 당신은 잘못된 순서를 사용 했습니까? 사용하면 사본이 없습니다 df=scan(...); names(df)=...; attr...; class...-참조 tracemem()(R 2.15.2에서 테스트)
Simon Urbanek

3
열별로 큰 데이터를 이진 파일로 덤프하는 방법을 자세히 설명 할 수 있습니까?
dabsingh

32

이것은 이전 R-Help 에서 요청 되었으므로 검토 할 가치가 있습니다.

한 가지 제안 사용할 수 있었다 readChar()다음에 결과에 문자열 조작을 strsplit()하고 substr(). readChar에 관련된 논리가 read.table보다 훨씬 적다는 것을 알 수 있습니다.

여기서 메모리가 문제인지 모르겠지만 HadoopStreaming 패키지를 살펴볼 수도 있습니다 . 여기 에는 대용량 데이터 세트를 처리하기 위해 설계된 MapReduce 프레임 워크 인 Hadoop사용 됩니다. 이를 위해 hsTableReader 함수를 사용합니다. 이것은 예입니다 (그러나 하둡을 배우기위한 학습 곡선이 있습니다).

str <- "key1\t3.9\nkey1\t8.9\nkey1\t1.2\nkey1\t3.9\nkey1\t8.9\nkey1\t1.2\nkey2\t9.9\nkey2\"
cat(str)
cols = list(key='',val=0)
con <- textConnection(str, open = "r")
hsTableReader(con,cols,chunkSize=6,FUN=print,ignoreKey=TRUE)
close(con)

여기서 기본 아이디어는 데이터 가져 오기를 청크로 분할하는 것입니다. 병렬 프레임 워크 (예 : 스노) 중 하나를 사용하여 파일을 분할하여 병렬로 데이터 가져 오기를 실행할 수도 있지만 메모리 제약 조건이 발생하여 큰 도움이되지 않는 대규모 데이터 세트의 경우, 그렇기 때문에 map-reduce가 더 나은 방법입니다.


방금 빠른 테스트를 수행했으며 readChar는 설명 할 수없는 이유로 readLines보다 훨씬 빠릅니다. 그러나 간단한 C 테스트에 비해 죄만큼 느립니다. 10 배 느린 C 이상 - 100 메가 읽기의 간단한 작업에서, R은 약 5입니다
조나단 장

1
당신의 요점을 이해하지 마십시오. 하둡의 요점은 매우 큰 데이터를 처리하는 것입니다. 이것이 바로 질문이었습니다.
Shane

1
이름에도 불구하고 hsTableReader는 Hadoop 자체와 관련이 없으며 대용량 데이터를 조각으로 처리하기위한 것입니다. 한 번에 한 행의 행인 con에서 읽고 각 청크를 data.frame으로 FUN에 전달하여 처리합니다. ignoreKey = FALSE를 사용하면 Map / Reduce 접근 방식과 관련된 키 (첫 번째 열의 항목)를 기준으로 추가 그룹화가 수행됩니다.
DavidR

안녕. 이 Hadoop 데이터를 모든 데이터와 동시에 사용하도록 설계된 동물원과 같은 다른 패키지의 입력으로 어떻게 사용 하시겠습니까?
skan

10

대안은 vroom패키지 를 사용하는 것 입니다. 이제 CRAN에 있습니다. vroom전체 파일을로드하지 않고 각 레코드가있는 위치를 인덱싱하고 나중에 사용할 때 읽습니다.

사용한만큼만 지불하십시오.

참조 부르릉 소개를 , 부르릉 시작하기부르릉 벤치 마크 .

기본 개요는 큰 파일을 처음 읽을 때 속도가 훨씬 빠르며 이후 데이터 수정은 약간 느려질 수 있다는 것입니다. 따라서 사용 용도에 따라 최상의 옵션이 될 수 있습니다.

아래의 Vroom 벤치 마크 에서 단순화 된 예 를 참조하십시오.보아야 할 주요 부분은 초고속 읽기 시간이지만 집계 등과 같은 약간의 파종 작업입니다.

package                 read    print   sample   filter  aggregate   total
read.delim              1m      21.5s   1ms      315ms   764ms       1m 22.6s
readr                   33.1s   90ms    2ms      202ms   825ms       34.2s
data.table              15.7s   13ms    1ms      129ms   394ms       16.3s
vroom (altrep) dplyr    1.7s    89ms    1.7s     1.3s    1.9s        6.7s

5

언급 할 가치가있는 약간의 추가 사항. 파일이 매우 큰 경우 다음을 사용하여 행 수 (헤더가없는 경우)를 즉시 계산할 수 있습니다 (여기서 bedGraph작업 디렉토리의 파일 이름은 다음과 같습니다).

>numRow=as.integer(system(paste("wc -l", bedGraph, "| sed 's/[^0-9.]*\\([0-9.]*\\).*/\\1/'"), intern=T))

그런 다음에 그 중 하나를 사용할 수 있습니다 read.csv, read.table...

>system.time((BG=read.table(bedGraph, nrows=numRow, col.names=c('chr', 'start', 'end', 'score'),colClasses=c('character', rep('integer',3)))))
   user  system elapsed 
 25.877   0.887  26.752 
>object.size(BG)
203949432 bytes

4

종종 데이터베이스 (예 : Postgres) 내에 더 큰 데이터베이스를 유지하는 것이 좋은 습관이라고 생각합니다. 나는 (nrow * ncol) ncell = 10M보다 너무 큰 것을 사용하지 않습니다. 그러나 종종 여러 데이터베이스에서 쿼리하는 동안 R이 메모리 집약적 그래프를 작성하고 보유하기를 원합니다. 32GB 랩탑의 미래에는 이러한 유형의 메모리 문제 중 일부가 사라질 것입니다. 그러나 데이터베이스를 사용하여 데이터를 보유한 다음 결과 쿼리 결과 및 그래프에 R의 메모리를 사용하는 것이 여전히 유용 할 수 있습니다. 몇 가지 장점은 다음과 같습니다.

(1) 데이터는 데이터베이스에로드 된 상태로 유지됩니다. 랩톱을 다시 켤 때 pgadmin에서 원하는 데이터베이스에 다시 연결하기 만하면됩니다.

(2) R은 SQL보다 훨씬 더 많은 통계 및 그래프 작업을 수행 할 수 있습니다. 그러나 SQL은 R보다 많은 양의 데이터를 쿼리하도록 더 잘 설계되었다고 생각합니다.

# Looking at Voter/Registrant Age by Decade

library(RPostgreSQL);library(lattice)

con <- dbConnect(PostgreSQL(), user= "postgres", password="password",
                 port="2345", host="localhost", dbname="WC2014_08_01_2014")

Decade_BD_1980_42 <- dbGetQuery(con,"Select PrecinctID,Count(PrecinctID),extract(DECADE from Birthdate) from voterdb where extract(DECADE from Birthdate)::numeric > 198 and PrecinctID in (Select * from LD42) Group By PrecinctID,date_part Order by Count DESC;")

Decade_RD_1980_42 <- dbGetQuery(con,"Select PrecinctID,Count(PrecinctID),extract(DECADE from RegistrationDate) from voterdb where extract(DECADE from RegistrationDate)::numeric > 198 and PrecinctID in (Select * from LD42) Group By PrecinctID,date_part Order by Count DESC;")

with(Decade_BD_1980_42,(barchart(~count | as.factor(precinctid))));
mtext("42LD Birthdays later than 1980 by Precinct",side=1,line=0)

with(Decade_RD_1980_42,(barchart(~count | as.factor(precinctid))));
mtext("42LD Registration Dates later than 1980 by Precinct",side=1,line=0)

3

arrow패키지를 사용하여 데이터를 매우 빠르게 읽습니다 . 상당히 초기 단계 인 것 같습니다.

특히, 나는 마루 열 형식을 사용하고 있습니다. 이것은 data.frameR 로 다시 변환 되지만 그렇지 않은 경우 훨씬 더 빠른 속도를 얻을 수 있습니다. 이 형식은 Python에서도 사용할 수 있으므로 편리합니다.

이것에 대한 나의 주요 사용 사례는 상당히 제한적인 RShiny 서버에 있습니다. 이러한 이유로, 나는 데이터를 Apps에 첨부 된 (즉, SQL 외부에) 유지하는 것을 선호하므로 작은 파일 크기와 속도가 필요합니다.

이 링크 된 기사는 벤치마킹과 좋은 개요를 제공합니다. 나는 아래에 흥미로운 점을 인용했다.

https://ursalabs.org/blog/2019-10-columnar-perf/

파일 크기

즉, Parquet 파일은 gzipped CSV의 절반 크기입니다. Parquet 파일이 너무 작은 이유 중 하나는 사전 인코딩 (“사전 압축”이라고도 함) 때문입니다. 사전 압축은 LZ4 또는 ZSTD (FST 형식으로 사용)와 같은 범용 바이트 압축기를 사용하는 것보다 실질적으로 더 나은 압축을 생성 할 수 있습니다. Parquet는 매우 작은 파일을 빠르게 읽을 수 있도록 설계되었습니다.

읽기 속도

출력 유형별로 제어 할 때 (예 : 모든 R data.frame 출력을 서로 비교) Parquet, Feather 및 FST의 성능이 상대적으로 작은 마진 내에 있음을 알 수 있습니다. pandas.DataFrame 출력도 마찬가지입니다. data.table :: fread는 1.5GB 파일 크기와 경쟁이 치열하지만 다른 파일은 2.5GB CSV보다 느립니다.


독립적 인 테스트

1,000,000 개의 행의 시뮬레이션 된 데이터 세트에 대해 독립적 인 벤치마킹을 수행했습니다. 기본적으로 압축에 도전하기 위해 많은 것들을 섞었습니다. 또한 임의의 단어로 구성된 짧은 텍스트 필드와 두 가지 시뮬레이션 요소를 추가했습니다.

데이터

library(dplyr)
library(tibble)
library(OpenRepGrid)

n <- 1000000

set.seed(1234)
some_levels1 <- sapply(1:10, function(x) paste(LETTERS[sample(1:26, size = sample(3:8, 1), replace = TRUE)], collapse = ""))
some_levels2 <- sapply(1:65, function(x) paste(LETTERS[sample(1:26, size = sample(5:16, 1), replace = TRUE)], collapse = ""))


test_data <- mtcars %>%
  rownames_to_column() %>%
  sample_n(n, replace = TRUE) %>%
  mutate_all(~ sample(., length(.))) %>%
  mutate(factor1 = sample(some_levels1, n, replace = TRUE),
         factor2 = sample(some_levels2, n, replace = TRUE),
         text = randomSentences(n, sample(3:8, n, replace = TRUE))
         )

읽고 쓰기

데이터 쓰기가 쉽습니다.

library(arrow)

write_parquet(test_data , "test_data.parquet")

# you can also mess with the compression
write_parquet(test_data, "test_data2.parquet", compress = "gzip", compression_level = 9)

데이터를 읽는 것도 쉽습니다.

read_parquet("test_data.parquet")

# this option will result in lightning fast reads, but in a different format.
read_parquet("test_data2.parquet", as_data_frame = FALSE)

나는 경쟁 옵션 중 일부에 대해이 데이터를 읽는 것을 테스트했으며 위 기사와 약간 다른 결과를 얻었습니다.

벤치마킹

이 파일은 벤치 마크 기사만큼 크지 않으므로 차이가있을 수 있습니다.

테스트

  • rds : test_data.rds (20.3MB)
  • parquet2_native : (압축률이 높은 14.9MBas_data_frame = FALSE)
  • parquet2 : test_data2.parquet (압축률이 높은 14.9MB )
  • 쪽모이 세공 마루 : test_data.parquet (40.7 MB)
  • fst2 : test_data2.fst (높은 압축률의 27.9MB )
  • fst : test_data.fst (76.8MB)
  • fread2 : test_data.csv.gz (23.6MB)
  • fread : test_data.csv (98.7MB)
  • feather_arrow : test_data.feather ( 157.2MB 와 함께 읽음 arrow)
  • feather : test_data.feather (157.2MB와 함께 읽기 feather)

관찰

이 특정 파일의 경우 fread실제로 매우 빠릅니다. 압축률이 높은 parquet2테스트 의 작은 파일 크기가 마음에 듭니다. data.frame실제로 속도가 필요한 경우가 아니라 기본 데이터 형식으로 작업하는 데 시간을 투자 할 수 있습니다 .

여기 fst또한 훌륭한 선택입니다. 속도 또는 파일 크기 균형이 필요한지 여부에 따라 fst압축률이 높은 형식을 사용하거나 압축률이 높은 형식을 사용합니다 parquet.


0

기존의 read.table 대신 fread가 더 빠른 기능이라고 생각합니다. 필요한 열만 선택하는 것과 같은 추가 속성을 지정하고 colclass 및 문자열을 요인으로 지정하면 파일을 가져 오는 데 걸리는 시간이 줄어 듭니다.

data_frame <- fread("filename.csv",sep=",",header=FALSE,stringsAsFactors=FALSE,select=c(1,4,5,6,7),colClasses=c("as.numeric","as.character","as.numeric","as.Date","as.Factor"))

0

나는 위의 모든 것을 시도했고 [판독자] [1]가 최선을 다했습니다. 나는 단지 8 기가 바이트 RAM이

20 개 파일 (각 5GB, 7 개 열) :

read_fwf(arquivos[i],col_types = "ccccccc",fwf_cols(cnpj = c(4,17), nome = c(19,168), cpf = c(169,183), fantasia = c(169,223), sit.cadastral = c(224,225), dt.sitcadastral = c(226,233), cnae = c(376,382)))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.