문제

내가 매우 큰 테이블(30million 행)하고 싶은 것이드로 dataframes R. 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))))

은 거기에 더 나은 방법을 이?또는 매우 가능성이 완전히 다른 접근 방식이 문제입니까?

도움이 되었습니까?

해결책

몇 년 후 업데이트

이 대답은 오래되었고 R은 계속되었습니다. 조정 read.table 조금 더 빨리 달리는 것은 귀중한 이점이 거의 없습니다. 귀하의 옵션은 다음과 같습니다.

  1. 사용 fread 안에 data.table CSV/Tab-Delimited 파일에서 직접 R으로 데이터를 가져 오기 위해 Mnel의 대답.

  2. 사용 read_table 안에 readr (2015 년 4 월의 크랜에서). 이것은 매우 작용합니다 fread 위에. 그만큼 readme 링크에서 두 기능의 차이를 설명합니다 (readr 현재 "1.5-2 배 느린 느린"이라고 주장합니다 data.table::fread).

  3. read.csv.raw ~에서 iotools CSV 파일을 신속하게 읽기위한 세 번째 옵션을 제공합니다.

  4. 플랫 파일이 아닌 데이터베이스에서 가능한 많은 데이터를 저장하려고합니다. (더 나은 영구 저장 매체 일뿐 만 아니라 데이터는 이진 형식으로 R을 오가는 것이 더 빠릅니다.) read.csv.sql 에서 sqldf 그림에 설명 된대로 패키지 JD Long의 답변, 데이터를 임시 SQLITE 데이터베이스로 가져온 다음 R으로 읽습니다. RODBC 패키지 및 반대는의 섹션에 따라 다릅니다 DBI 패키지 페이지. MonetDB.R 데이터 프레임 인 척하는 데이터 유형을 제공하지만 실제로는 그 아래에있는 monetdb이므로 성능이 향상됩니다. 그것으로 데이터를 가져옵니다 monetdb.read.csv 기능. dplyr 여러 유형의 데이터베이스에 저장된 데이터로 직접 작업 할 수 있습니다.

  5. 이진 형식으로 데이터를 저장하면 성능 향상에 유용 할 수 있습니다. 사용 saveRDS/readRDS (아래 참조), h5 또는 rhdf5 HDF5 형식의 패키지, OR write_fst/read_fst ~로부터 fst 패키지.


원래 답변

Read.table 또는 Scan을 사용하든 간단한 몇 가지 간단한 것들이 있습니다.

  1. 세트 nrows=데이터의 레코드 수 (nmax 안에 scan).

  2. 그것을 확인하십시오 comment.char="" 주석 해석을 해제합니다.

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

  4. 환경 multi.line=FALSE 또한 스캔 성능을 향상시킬 수 있습니다.

이 일 중 하나가 작동하지 않으면 중 하나를 사용하십시오. 프로파일 링 패키지 어떤 라인이 속도를 늦추고 있는지 결정합니다. 아마도 당신은 컷 다운 버전을 쓸 수 있습니다 read.table 결과를 기반으로합니다.

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

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

다른 팁

다음은 사용하는 예입니다 fread ~에서 data.table 1.8.7

예제는 도움말 페이지에서 나옵니다 fread, 내 Windows 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]

표준 read.table

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

최적화 된 read.table

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

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

있었어요 약간의 토론 2GB 이상의 텍스트 데이터를 R 데이터 프레임으로 가져 오는 가장 좋은 방법에 관해서. 어제 나는 a 블로그 게시물 사용에 대해 sqldf() 스테이징 영역으로 데이터를 SQLITE로 가져온 다음 SQLITE에서 R으로 빨아 넣는다. <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'))

이상하게도, 아무도 중요한 것이라도 몇 년 동안 질문의 맨 아래 부분에 대답하지 않았습니다. 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에서도) 느린다.

이것은 이전에있었습니다 물었다 R- 헬프, 검토 할 가치가 있습니다.

사용해야 할 제안이있었습니다 readChar() 그런 다음 결과에 문자열 조작을하십시오 strsplit() 그리고 substr(). readchar와 관련된 논리가 read.table보다 훨씬 적다는 것을 알 수 있습니다.

메모리가 여기에 문제인지는 모르겠지만 그것을보고 싶다 Hadoopstreaming 패키지. 이것 Hadoop을 사용합니다, 큰 데이터 세트를 다루기 위해 설계된 MapReduce 프레임 워크입니다. 이를 위해서는 hstablereader 함수를 사용합니다. 이것은 예입니다 (그러나 Hadoop을 배우는 학습 곡선이 있습니다) : :

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)

여기서 기본 아이디어는 데이터 가져 오기를 청크로 나누는 것입니다. Parallel Frameworks 중 하나 (예 : Snow)를 사용하고 파일을 분할하여 데이터 가져 오기를 병렬로 실행할 수도 있지만 메모리 제약 조건을 실행하기 때문에 도움이되지 않는 대규모 데이터 세트의 경우에는 데이터 가져 오기를 실행할 수도 있습니다. 그렇기 때문에 Map-Reduce가 더 나은 접근 방식입니다.

언급 할 가치가있는 사소한 추가 포인트. 파일이 매우 큰 경우 즉시 (헤더가없는 경우) (헤더가없는 경우)를 계산할 수 있습니다. 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

대안은 vroom 패키지. 이제 크랜에.vroom 전체 파일을로드하지 않으며 각 레코드가있는 위치에 색인이 표시되며 사용하면 나중에 읽습니다.

사용하는 것에 대해서만 지불하십시오.

보다 vroom 소개, vroom을 시작하십시오 그리고 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

종종 제가 생각하는것이 좋습 유지하는 데이터베이스의 크기가 큰 경우에는 데이터베이스 안에(예를들면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)

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

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"))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top