डेटाफ़्रेम के रूप में बहुत बड़ी तालिकाओं को जल्दी से पढ़ना


502

मेरे पास बहुत बड़ी टेबल (30 मिलियन पंक्तियाँ) हैं जिन्हें मैं आर में डेटाफ़्रेम के रूप में लोड करना चाहता हूं। 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. सीधे आर / टिबेल में सीएसवी / टैब-सीमांकित फ़ाइलों से डेटा आयात करने के लिए vroomtidyverse पैकेज का उपयोग करना vroom

  2. का उपयोग freadमें data.tableसीधे आर सी में सीएसवी / टैब-सीमांकित फ़ाइलों से डेटा आयात करने के mnel का जवाब

  3. का उपयोग read_tableमें readr(अप्रैल 2015 से क्रैन पर)। यह बहुत freadऊपर की तरह काम करता है। रीडमी कड़ी में दो कार्यों के बीच अंतर (बताते हैं readrवर्तमान में होना करने के लिए "1.5-2x धीमी" से दावा करता है data.table::fread)।

  4. read.csv.rawसे iotoolsCSV फ़ाइलों को जल्दी से पढ़ने के लिए एक तीसरा विकल्प प्रदान करता है।

  5. फ्लैट फ़ाइलों के बजाय डेटाबेस में जितना संभव हो उतना डेटा संग्रहीत करने की कोशिश कर रहा है। (साथ ही एक बेहतर स्थायी भंडारण माध्यम होने के रूप में, आंकड़ों के और अनुसंधान से एक बाइनरी स्वरूप में पारित हो जाता है, जो तेजी से होता है।) read.csv.sqlमें sqldfपैकेज, में वर्णित के रूप जद लांग का जवाब एक अस्थायी SQLite डेटाबेस में आयात डेटा और फिर इसे पढ़ता आर। में यह भी देखें: RODBCपैकेज, और रिवर्स DBIपैकेज पेज के अनुभाग पर निर्भर करता है । MonetDB.Rआपको एक डेटा प्रकार देता है जो एक डेटा फ़्रेम होने का दिखावा करता है लेकिन वास्तव में एक MonetDB नीचे है, बढ़ते प्रदर्शन। इसके monetdb.read.csvफ़ंक्शन के साथ डेटा आयात करें । dplyrआपको कई प्रकार के डेटाबेस में संग्रहीत डेटा के साथ सीधे काम करने की अनुमति देता है।

  6. प्रदर्शन को बेहतर बनाने के लिए द्विआधारी प्रारूपों में डेटा संग्रहीत करना भी उपयोगी हो सकता है। उपयोग saveRDS/ readRDS(नीचे देखें), h5या rhdf5HDF5 प्रारूप, या के लिए पैकेज write_fst/ read_fstसे fstपैकेज।


मूल उत्तर

कोशिश करने के लिए कुछ सरल चीजें हैं, चाहे आप read.table का उपयोग करें या स्कैन करें।

  1. सेट nrows= आपके डेटा में अभिलेखों की संख्या ( nmaxमें scan)।

  2. सुनिश्चित करें कि comment.char=""टिप्पणियों की व्याख्या को बंद करें।

  3. स्पष्ट रूप से उपयोग करते हुए प्रत्येक स्तंभ के वर्गों को परिभाषित colClassesमें read.table

  4. सेटिंग multi.line=FALSEस्कैन में प्रदर्शन में सुधार कर सकती है।

अगर इनमें से कोई भी काम नहीं करता है, तो प्रोफाइलिंग पैकेजों में से एक का उपयोग करके यह निर्धारित करें कि कौन सी रेखाएं चीजों को धीमा कर रही हैं। शायद आप read.tableपरिणामों के आधार पर कट-डाउन संस्करण लिख सकते हैं ।

दूसरा विकल्प आपके डेटा को आर में पढ़ने से पहले फ़िल्टर कर रहा है।

या, यदि समस्या यह है कि आपको इसे नियमित रूप से पढ़ना है, तो डेटा को एक बार पढ़ने के लिए इन विधियों का उपयोग करें, फिर डेटा फ्रेम को बाइनरी ब्लॉब के रूप में सहेजें save saveRDS, तो अगली बार आप इसे तेजी से प्राप्त कर सकते हैं load readRDS


4
सुझावों के लिए धन्यवाद रिची। मैंने थोड़ा परीक्षण किया, और ऐसा लगता है कि read.table के लिए nrow और colClasses विकल्पों का उपयोग करने के साथ प्रदर्शन लाभ काफी मामूली हैं। उदाहरण के लिए, ~ 7M पंक्ति तालिका पढ़ने पर विकल्पों के बिना 78s और विकल्पों के साथ 67s लगते हैं। (ध्यान दें: तालिका में 1 वर्ण स्तंभ, 4 पूर्णांक स्तंभ हैं, और मैं comment.char = '' और stringsAsFactors = FALSE का उपयोग करके पढ़ता हूं)। सेव () और लोड () का उपयोग करना जब संभव हो तो एक शानदार टिप है - एक बार सेव () के साथ संग्रहीत होने पर, उसी टेबल को लोड होने में केवल 12s लगते हैं।
ईटान

2
"पंख" पैकेज में एक नया बाइनरी प्रारूप है जो पायथन के पांडा डेटा फ्रेम के साथ अच्छा खेलता है
rsoren

4
मुझे लगता है कि शायद आपको पैकेज के संबंध में अपनी पोस्ट को फिर से अपडेट करने की आवश्यकता है feather। पढ़ने के लिए डेटा featherकी तुलना में बहुत तेज है fread। उदाहरण के लिए एक 4 जीबी डेटासेट पर जिसे मैंने अभी लोड किया read_featherथा वह लगभग 4.5 गुना तेज था fread। डेटा fwriteकी बचत के लिए अभी भी तेजी है। blog.dominodatalab.com/the-r-data-io-shootout
Z boson

2
लेकिन आरडीएस की तुलना में फ़ाइल का आकार पंख के लिए बहुत बड़ा है। मुझे नहीं लगता कि यह संपीड़न का समर्थन करता है। आरडीएस फ़ाइल 216 एमबी है और पंख फ़ाइल 4 जीबी है। तो featherपढ़ने के लिए तेज़ है लेकिन यह बहुत अधिक भंडारण स्थान का उपयोग करता है।
जेड बोसोन

@Zboson यदि आपको एक फ़ाइल में डेटा फ़्रेम को संग्रहीत करने की आवश्यकता है जिसे R और पायथन दोनों से एक्सेस किया जा सकता है, तो featherएक अच्छा विकल्प है। यदि आप केवल R में अपने डेटा को पढ़ने में सक्षम होने के बारे में परवाह करते हैं, rdsतो बेहतर है।
रिची कॉटन

279

यहां एक उदाहरण है जो 1.8.7 freadसे उपयोग करता हैdata.table

उदाहरण freadमेरी विंडो 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

अनुकूलित पठनीय

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

fread

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

एफएफ / एफएफडीएफ

 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
महान जवाब, और बेंचमार्किंग अन्य संदर्भों में है। बस के साथ एक मिनट के तहत एक 4GB फ़ाइल में पढ़ा fread। बेस आर फ़ंक्शन के साथ इसे पढ़ने की कोशिश की थी और इसमें लगभग 15 घंटे लगे।
अरी बी। फ्रीडमैन

1
मेरे बेंचमार्क में data.table में read.csv के लिए और भी अधिक गति लाभ का सुझाव दिया गया है। ध्यान दें कि data.table मानक R नहीं है, लेकिन (दुख की बात है) CRAN पर इसके रचनाकारों द्वारा अच्छी तरह से "सिर्फ" साझा किया गया है। यह सामान्य आर पैकेज सूची बनाने के लिए पर्याप्त मानक नहीं माना जाता है, डेटा फ्रेम के प्रतिस्थापन के रूप में बहुत कम योग्य है। इसके बहुत सारे फायदे हैं, लेकिन कुछ बहुत ही स्पष्ट पहलू भी हैं। आप मानक R डेटा फ़्रेम की दुनिया में वापस आने के लिए पैकेज के साथ as.data.frame (fread.csv ("test.csv")) का उपयोग करना चाह सकते हैं।
आइवो वेल्च

3
@ आप बेंचमार्क को फिर से चला सकते हैं और इसमें शामिल readrहो सकते हैं ?
जंगोरकी

2
दूसरा @ जंजोरेकी। इसके अलावा, दिए गए freadकुछ वास्तविक प्रतियोगियों के लिए, अनुकूलित freadउपयोग के लिए बेंचमार्क जोड़ने के लिए उपयोगी हो सकता है - निर्दिष्ट करना colClasses, आदि
माइकलचेरिको

1
@jangorecji @ MichaelChirico दिया गया कोड पूरी तरह से प्रजनन योग्य है इसलिए यह सीधे रीड अनुकरण करने के लिए आगे है ... कोड को पुन: डायनामिक करें, मेरी मशीन पर समय समाप्त होने पर दो बार तेजी से होता है यदि अधिकांश परिणाम के लिए अधिक नहीं तो अंततः यह एक नेटवर्क (और) पर चल रहा है अच्छी तरह से अद्यतन किए गए संस्करणों के रूप में यह अभी कुछ समय है) ... और रीड के साथ मैं 7 एस पर हूं, लेकिन एक सेकंड के तहत भी जब मैं दूसरी बार (0.66) चलाता हूं, तो मुझे संदेह है कि नेटवर्क में कुछ कैशिंग या कुछ बोतल गर्दन है। यहाँ दिखाए गए सबसे तेज़ समाधान के लिए फैडर 2 एस पर मेरी तुलना में (पहली बार 8.69 के दशक में किसी कारण से धीमी गति से चल रहा है)
आर। प्रोस्ट

249

मैंने इस सवाल को शुरू में नहीं देखा और कुछ दिन बाद इसी तरह का सवाल पूछा। मैं अपने पिछले प्रश्न को नीचे ले जा रहा हूं, लेकिन मैंने सोचा कि मैं यहां एक उत्तर जोड़ूंगा कि मैं यह बताऊं कि मैं यह कैसे sqldf()करता था।

आर डेटा फ्रेम में 2GB या अधिक टेक्स्ट डेटा आयात करने के सर्वोत्तम तरीके के रूप में बहुत कम चर्चा हुई है । कल मैंने एक मंचन क्षेत्र के रूप में डेटा को SQLite में आयात करने के लिए उपयोग करने के बारे में एक ब्लॉग पोस्ट लिखा था sqldf(), और फिर इसे SQLite से R में चूस रहा था। यह मेरे लिए वास्तव में अच्छा काम करता है। मैं <5 मिनट में 2GB (3 कॉलम, 40 मिमी पंक्तियों) डेटा में खींचने में सक्षम था। इसके विपरीत, 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
नमस्ते। आप चिड़ियाघर जैसे अन्य पैकेजों के लिए एक इनपुट के रूप में इसका उपयोग कैसे करते हैं, इसे एक साथ सभी डेटा के साथ उपयोग करने के लिए डिज़ाइन किया गया है?
स्केन

@sk अंत वस्तु एक डेटा फ्रेम है। इसलिए आपको इसे चिड़ियाघर के साथ उपयोग करने के लिए इसे एक चिड़ियाघर ऑब्जेक्ट में बदलना होगा। उदाहरणों के लिए चिड़ियाघर डॉक्स में उदाहरण देखें।
जेडी लॉन्ग

@ जद लंबे। नमस्ते, समस्या यह है कि जब आप इसे एक चिड़ियाघर ऑब्जेक्ट में परिवर्तित करते हैं तो यह इसे मेमोरी पर फिट करने की कोशिश करता है। यदि यह बहुत बड़ा है तो यह एक त्रुटि पैदा करता है। और अगर चिड़ियाघर की वस्तु का परिणाम (उदाहरण के लिए दो श्रृंखलाओं का एकत्रीकरण) भी है, तो इसे एक sql या ff वस्तु भी होना चाहिए।
14

मुझे नहीं पता कि sqldf में क्या गलत है। मैंने डिस्क पर एक साधारण 1GB फ़ाइल (2 संख्यात्मक कॉलम के साथ) बनाई है और DTSQL का उपयोग किया है - <read.csv.sql ("f2.txt", dbname = tempfile ()) और यह मेमोरी पर पूरे डेटा को लोड करने की कोशिश करता है। कल मैं इसके बजाय ff और पुनरावर्ती कोशिश करूँगा।
स्कान

1
@ क्या मीटर हजार है तो मिमी हजार, या मिलियन है। मुझे संभवतः इसे एमएम के रूप में पूंजीकृत करना चाहिए था। लेकिन मुझे लगता है कि यदि आपके पास पर्याप्त विविध श्रोता हैं तो किसी भी संक्षिप्त नाम के बारे में किसी को भ्रम हो सकता है। अत्यधिक क्रियात्मक होने के मेरे प्रयास में, मुझे खेद है कि मैंने इसे और अधिक भ्रमित कर दिया! accountingcoach.com/blog/what-does-m-and-mm-stand-for
जद लांग

73

अजीब बात है, किसी ने भी सवाल के निचले हिस्से का जवाब नहीं दिया, भले ही यह एक महत्वपूर्ण है - data.frameएस केवल सही विशेषताओं के साथ सूचियां हैं, इसलिए यदि आपके पास बड़ा डेटा है जिसे आप as.data.frameसूची के लिए उपयोग या समान नहीं करना चाहते हैं । किसी सूची को डेटा फ़्रेम में बस "टर्न" करना बहुत तेज़ है:

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

यह डेटा की कोई प्रतिलिपि नहीं बनाता है इसलिए यह तत्काल है (अन्य सभी विधियों के विपरीत)। यह मानता है कि आपने पहले ही names()सूची के अनुसार सेट कर लिया है।

[आर में बड़े डेटा लोड करने के लिए - व्यक्तिगत रूप से, मैं उन्हें बाइनरी फ़ाइलों और उपयोग में कॉलम द्वारा डंप करता हूं readBin()- जो कि अब तक का सबसे तेज़ तरीका है (मिमीमैपिंग के अलावा) और यह केवल डिस्क की गति द्वारा सीमित है। बाइनरी डेटा की तुलना में ASCII फ़ाइलों को पार्स करना स्वाभाविक रूप से धीमा है (C में भी)।]


6
उपयोग करने से tracmemपता चलता है कि attr<-और class<-प्रतियां आंतरिक रूप से बनाते हैं। bit::setattrया data.table::setattrनहीं होगा।
मेलन

6
हो सकता है कि आपने गलत ऑर्डर का इस्तेमाल किया हो? यदि आप उपयोग करते हैं तो कोई प्रतिलिपि नहीं है df=scan(...); names(df)=...; attr...; class...- देखें tracemem()(आर 2.15.2 में परीक्षण किया गया है)
साइमन अर्बनक

3
क्या आप बाइनरी फ़ाइलों में कॉलम द्वारा बड़े डेटा को डंप करने के तरीके के बारे में विस्तार से बता सकते हैं?
dabsingh

32

यह पहले आर-हेल्प पर पूछा गया था , इसलिए यह समीक्षा के लायक है।

वहाँ एक सुझाव का उपयोग करना था readChar()और फिर परिणाम के साथ स्ट्रिंग हेरफेर strsplit()और substr()। आप देख सकते हैं readChar में शामिल तर्क read.table से बहुत कम है।

मुझे नहीं पता कि स्मृति यहाँ एक मुद्दा है, लेकिन आप भी HadoopStreaming पैकेज पर एक नज़र रखना चाहते हैं । यह Hadoop का उपयोग करता है , जो एक MapReduce ढांचा है जो बड़े डेटा सेट से निपटने के लिए डिज़ाइन किया गया है। इसके लिए, आप 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)

यहाँ मूल विचार डेटा आयात को विखंडू में तोड़ना है। आप समांतर फ्रेमवर्क (जैसे स्नो) में से किसी एक का उपयोग करने के लिए और फ़ाइल आयात करके समानांतर में डेटा आयात चलाने के लिए इतनी दूर जा सकते हैं, लेकिन बड़े डेटा सेटों के लिए सबसे अधिक संभावना है, जो तब तक मदद नहीं करेंगे जब तक आप मेमोरी की कमी में भाग लेंगे, यही कारण है कि मैप-कम एक बेहतर तरीका है।


मैंने अभी एक त्वरित परीक्षण किया है और कुछ अचूक कारणों के लिए रीडचेयर, रीडलाइन की तुलना में बहुत तेज़ प्रतीत होता है। हालांकि, यह अभी भी एक साधारण सी परीक्षण की तुलना में पाप के रूप में धीमा है। 100 megs पढ़ने के सरल कार्य में, R, C की तुलना में लगभग 5 - 10x धीमा है
जोनाथन चांग

1
आपकी बात समझ में नहीं आती। Hadoop की बात बहुत बड़े डेटा को हैंडल करना है, जो कि सवाल था।
शेन

1
नाम के बावजूद, hsTableReader का Hadoop से कुछ भी लेना-देना नहीं है, यह टुकड़ों में बड़े डेटा को संसाधित करने के लिए है। यह con से पढ़ता है, एक समय में पंक्तियों का एक हिस्सा है, और प्रसंस्करण के लिए FUN को डेटा के रूप में प्रत्येक chunk पास करता है। Igneyey = FALSE के साथ, यह कुंजी (पहले कॉलम में प्रवेश) द्वारा कुछ अतिरिक्त समूहीकरण करता है, जो मैप / कम दृष्टिकोण के लिए प्रासंगिक है।
डेविड म्र

नमस्ते। आप इस Hadoop डेटा को चिड़ियाघर जैसे अन्य पैकेजों के लिए एक इनपुट के रूप में कैसे उपयोग करेंगे, जिसे सभी डेटा के साथ एक साथ उपयोग करने के लिए डिज़ाइन किया गया है?
स्केन

10

vroomपैकेज का उपयोग करने के लिए एक विकल्प है । अब CRAN पर। 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

अक्सर बार मुझे लगता है कि डेटाबेस के अंदर बड़े डेटाबेस को रखना सिर्फ अच्छा अभ्यास है (जैसे पोस्टग्रेज़)। मैं कुछ भी बड़ा (nrow * ncol) ncell = 10M से अधिक का उपयोग नहीं करता, जो बहुत छोटा है; लेकिन मुझे अक्सर लगता है कि मैं आर को कई डेटाबेस से क्वेरी करते समय केवल मेमोरी गहन ग्राफ़ बनाना और पकड़ना चाहता हूं। 32 जीबी लैपटॉप के भविष्य में, इनमें से कुछ प्रकार की मेमोरी समस्याएं गायब हो जाएंगी। लेकिन डेटा को पकड़ने के लिए एक डेटाबेस का उपयोग करने का आकर्षण और फिर परिणामी क्वेरी परिणामों और ग्राफ़ के लिए आर की मेमोरी का उपयोग करना अभी भी उपयोगी हो सकता है। कुछ फायदे हैं:

(1) डेटा आपके डेटाबेस में लोड रहता है। जब आप अपने लैपटॉप को वापस चालू करते हैं, तो आप बस उस डेटाबेस में pgadmin को फिर से कनेक्ट करते हैं।

(2) यह सही है कि R, SQL की तुलना में कई अधिक सांख्यिकीय और रेखांकन कार्य कर सकता है। लेकिन मुझे लगता है कि आर की तुलना में बड़ी मात्रा में डेटा को क्वेरी करने के लिए SQL बेहतर तरीके से डिज़ाइन किया गया है।

# 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.frame आर में , लेकिन यदि आप नहीं करते हैं तो आप और भी तेज गति प्राप्त कर सकते हैं। यह प्रारूप सुविधाजनक है क्योंकि इसका उपयोग पायथन से भी किया जा सकता है।

इसके लिए मेरा मुख्य उपयोग मामला काफी संयमित RShiny सर्वर पर है। इन कारणों से, मैं ऐप्स (यानी, SQL से बाहर) से जुड़े डेटा को रखना पसंद करता हूं, और इसलिए छोटे फ़ाइल आकार के साथ-साथ गति की आवश्यकता होती है।

यह जुड़ा हुआ लेख बेंचमार्किंग और एक अच्छा अवलोकन प्रदान करता है। मैंने नीचे कुछ दिलचस्प बिंदुओं को उद्धृत किया है।

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

फाइल का आकार

यही है, Parquet फ़ाइल gzipped CSV जितनी बड़ी है, आधी है। Parquet फ़ाइल इतनी छोटी होने के कारणों में से एक शब्दकोष-एन्कोडिंग (जिसे "शब्दकोश संपीड़न" भी कहा जाता है) है। डिक्शनरी कम्प्रेशन एक सामान्य प्रयोजन बाइट्स कंप्रेसर जैसे LZ4 या ZSTD (जो FST प्रारूप में उपयोग किया जाता है) का उपयोग करने की तुलना में काफी बेहतर संपीड़न प्राप्त कर सकता है। लकड़ी की छत बहुत छोटी फ़ाइलों का उत्पादन करने के लिए डिज़ाइन किया गया था जो पढ़ने में तेज हैं।

स्पीड पढ़ें

आउटपुट प्रकार द्वारा नियंत्रित करते समय (जैसे सभी R डेटा.फ्रेम आउटपुट की एक-दूसरे से तुलना करना) हम देखते हैं कि एक दूसरे के अपेक्षाकृत छोटे अंतर के भीतर परक, पंख, और FST का प्रदर्शन गिरता है। वही पंडों का सच है। DataFrame आउटपुट। data.table :: fread प्रभावशाली रूप से 1.5 GB फ़ाइल आकार के साथ प्रतिस्पर्धात्मक है, लेकिन 2.5 GB 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.3 MB)
  • parquet2_native: (14.9 एमबी अधिक संपीड़न और as_data_frame = FALSE)
  • parquet2: test_data2.parquet (उच्च संपीड़न के साथ 14.9 MB)
  • लकड़ी की छत: test_data.parquet (40.7 एमबी)
  • fst2: test_data2.fst (उच्च संपीड़न के साथ 27.9 MB)
  • fst: test_data.fst (76.8 MB)
  • fread2: test_data.csv.gz (23.6MB)
  • fread: test_data.csv (98.7MB)
  • feather_arrow: test_data.feather (157.2 MB के साथ पढ़ा गया arrow)
  • पंख: test_data.feather (157.2 MB के साथ पढ़ा गया feather)

टिप्पणियों

इस विशेष फ़ाइल के लिए, freadवास्तव में बहुत तेज है। मुझे अत्यधिक संपीड़ित parquet2परीक्षण से छोटा फ़ाइल आकार पसंद है । मैं मूल डेटा प्रारूप के बजाय काम करने के लिए समय का निवेश कर सकता हूंdata.frameयदि मुझे वास्तव में गति की आवश्यकता है, तो मैं ।

यहाँ fstभी एक बढ़िया विकल्प है। मैं या तो अत्यधिक संकुचित fstप्रारूप या अत्यधिक संपीड़ित का उपयोग करेगा parquetयदि मुझे गति या फ़ाइल आकार के व्यापार की आवश्यकता होती है।


0

पारंपरिक read.table के बजाय मुझे लगता है कि भय एक तेज़ कार्य है। अतिरिक्त विशेषताओं को निर्दिष्ट करना जैसे कि केवल आवश्यक कॉलम का चयन करें, कॉलक्लेस और स्ट्रिंग निर्दिष्ट करें क्योंकि कारक फ़ाइल को आयात करने में लगने वाले समय को कम कर देंगे।

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

मैंने ऊपर और [readr] [1] सबसे अच्छा काम किया है। मेरे पास केवल 8 जीबी रैम है

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)))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.