आर में पढ़ने के लिए एक विशाल (3.5 जीबी) सीएसवी फ़ाइल को ट्रिम करना


87

इसलिए मुझे एक डेटा फ़ाइल (अर्धविराम अलग) मिली है जिसमें बहुत सारी डिटेल और अधूरी पंक्तियाँ हैं (प्रमुख एक्सेस और SQL को चोक करने के लिए)। यह काउंटी स्तर का डेटा सेगमेंट, सब-सेगमेंट और सब-सब-सेगमेंट (कुल ~ 200 कारकों के लिए) में 40 वर्षों से टूटा हुआ है। संक्षेप में, यह बहुत बड़ा है, और यदि मैं इसे केवल पढ़ने की कोशिश करता हूं तो यह स्मृति में फिट नहीं होगा।

तो मेरा सवाल यह है कि यह देखते हुए कि मैं सभी काउंटियों को चाहता हूं, लेकिन केवल एक वर्ष (और सिर्फ उच्चतम स्तर के खंड ... अंत में लगभग 100,000 पंक्तियों के लिए अग्रणी), क्या पाने के लिए सबसे अच्छा तरीका होगा इस रोलअप में आर?

वर्तमान में मैं अजगर के साथ अप्रासंगिक वर्षों को काटने की कोशिश कर रहा हूं, एक समय में एक पंक्ति में पढ़ने और संचालन करने से फाइल की सीमा के आसपास हो रही है, लेकिन मैं एक आर-केवल समाधान (सीआरएएन पैकेज ओके) पसंद करूंगा। क्या आर में एक समय में फ़ाइलों को एक टुकड़े में पढ़ने का एक समान तरीका है?

किसी भी विचार की बहुत प्रशंसा की जाएगी।

अपडेट करें:

  • प्रतिबन्ध
    • मेरी मशीन का उपयोग करने की आवश्यकता है , इसलिए कोई EC2 उदाहरण नहीं है
    • आर-केवल के रूप में संभव है। इस मामले में गति और संसाधन चिंता का विषय नहीं हैं ... बशर्ते मेरी मशीन में विस्फोट न हो ...
    • जैसा कि आप नीचे देख सकते हैं, डेटा में मिश्रित प्रकार होते हैं, जिन्हें मुझे बाद में संचालित करने की आवश्यकता होती है
  • डेटा
    • डेटा 3.5GB है, जिसमें लगभग 8.5 मिलियन पंक्तियाँ और 17 कॉलम हैं
    • एक दो हज़ार पंक्तियाँ (~ 2k) विकृत हैं, जिसमें 17 के बजाय केवल एक कॉलम है
      • ये पूरी तरह से महत्वहीन हैं और इन्हें गिराया जा सकता है
    • मुझे केवल इस फ़ाइल में से ~ 100,000 पंक्तियों की आवश्यकता है (नीचे देखें)

डेटा उदाहरण:

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ...
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ...
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ...
NC  [Malformed row]
[8.5 Mill rows]

मैं कुछ कॉलमों को काटना चाहता हूं और 40 उपलब्ध वर्षों में से दो (1980-2020 तक 2009-2010) चुनना चाहता हूं, ताकि डेटा आर में फिट हो सके:

County; State; Year; Quarter; Segment; GDP; ...
Ada County;NC;2009;4;FIRE;80.1; ...
Ada County;NC;2010;1;FIRE;82.5; ...
[~200,000 rows]

परिणाम:

किए गए सभी सुझावों के साथ छेड़छाड़ करने के बाद, मैंने फैसला किया कि जेडडी और मर्क द्वारा सुझाए गए रीडलाइन, सबसे अच्छा काम करेंगे। मैंने मर्क को चेक दिया क्योंकि उसने एक नमूना लागू किया था।

मैंने अपने अंतिम उत्तर के लिए मारेक के कार्यान्वयन का थोड़ा अनुकूलित संस्करण यहां पुन: प्रस्तुत किया है, स्ट्रैप्लिट और बिल्ली का उपयोग करके केवल उन कॉलमों को रखना जो मुझे चाहिए।

यह भी ध्यान दिया जाना चाहिए यह है ज्यादा कम अजगर से कुशल ... के रूप में, अजगर 5 मिनट में 3.5GB फ़ाइल के माध्यम से chomps आर 60 के बारे में लेता है ... लेकिन अगर आपके पास आर है तो यह टिकट है।

## Open a connection separately to hold the cursor position
file.in <- file('bad_data.txt', 'rt')
file.out <- file('chopped_data.txt', 'wt')
line <- readLines(file.in, n=1)
line.split <- strsplit(line, ';')
# Stitching together only the columns we want
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
## Use a loop to read in the rest of the lines
line <- readLines(file.in, n=1)
while (length(line)) {
  line.split <- strsplit(line, ';')
  if (length(line.split[[1]]) > 1) {
    if (line.split[[1]][3] == '2009') {
        cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
    }
  }
  line<- readLines(file.in, n=1)
}
close(file.in)
close(file.out)

दृष्टिकोण द्वारा विफलता:

  • sqldf
    • यह निश्चित रूप से है कि मैं भविष्य में इस प्रकार की समस्या के लिए उपयोग करूंगा यदि डेटा अच्छी तरह से बनता है। हालांकि, अगर यह नहीं है, तो SQLite चुटकुले।
  • मानचित्र छोटा करना
    • ईमानदार होने के लिए, डॉक्स ने मुझे इस पर थोड़ा डरा दिया, इसलिए मैं इसे आज़माने के लिए तैयार नहीं हुआ। ऐसा लग रहा था कि इसके लिए ऑब्जेक्ट को मेमोरी में होना आवश्यक है, जो कि अगर ऐसा होता तो बिंदु को हरा देता।
  • bigmemory
    • यह दृष्टिकोण सफाई से डेटा से जुड़ा हुआ है, लेकिन यह केवल एक समय में एक प्रकार को संभाल सकता है। नतीजतन, मेरे सभी चरित्र वैक्टर जब एक big.table में डाल दिया गया। अगर मुझे भविष्य के लिए बड़े डेटा सेट डिजाइन करने की आवश्यकता है, तो मैं केवल इस विकल्प को जीवित रखने के लिए केवल संख्याओं का उपयोग करने पर विचार करूंगा।
  • स्कैन
    • लगता है कि स्कैन में बड़ी मेमोरी के समान प्रकार के मुद्दे थे, लेकिन रीडलाइन के सभी यांत्रिकी के साथ। संक्षेप में, यह इस बार बिल के लायक नहीं था।

3
यदि आपके मानदंड काफी सरल हैं, तो आप संभवतः CSV का उपयोग करके sedऔर / या awkकट-डाउन संस्करण बनाने के लिए दूर हो सकते हैं जिसे आप सीधे पढ़ सकते हैं। चूँकि यह उत्तर से अधिक वर्कअराउंड है, इसलिए मैं इसे एक टिप्पणी के रूप में छोड़ दूँगा।
हांक गे

मैं हांक से सहमत - आप काम के लिए सही उपकरण का उपयोग करना चाहिए, और अगर यह सरल डेटा सफाई / अप्रासंगिक पंक्तियों को हटाने है / स्तंभों कमांड लाइन धारा उपकरण की तरह तरह / SED / awk महान हैं और होने जा रहे हैं जिस तरह से कम आर से गहन संसाधन या अजगर - यदि आप अपनी फ़ाइलों के प्रारूप का एक नमूना देते हैं तो हम शायद एक उदाहरण दे सकते हैं
हारून स्टेटम

महान। हमें पता है कि आप क्या खोजते हैं।
शेन

@ हंक और हारून: मैं आम तौर पर नौकरी के लिए सही उपकरण का उपयोग करने के लिए हूं, लेकिन यह काम पर एक विंडोज मशीन पर है और मैं आर सीख रहा हूं जैसे ही मैं जाता हूं, मुझे लगा कि यह एक अच्छा व्यायाम होगा। और यदि संभव हो तो केवल आर के रूप में यह प्रयास करें।
FTWynn

2
भविष्य के संदर्भ के लिए, data.table R पैकेज देखें। freadसमारोह बहुत तेजी से है read.tablex = fread(file_path_here, data.table=FALSE)किसी data.frameवस्तु के रूप में इसे लोड करने के लिए कुछ का उपयोग करें ।
paleo13

जवाबों:


39

साथ मेरे कोशिश readLines। एक कोड का यह टुकड़ा csvचयनित वर्षों के साथ बनाता है ।

file_in <- file("in.csv","r")
file_out <- file("out.csv","a")
x <- readLines(file_in, n=1)
writeLines(x, file_out) # copy headers

B <- 300000 # depends how large is one pack
while(length(x)) {
    ind <- grep("^[^;]*;[^;]*; 20(09|10)", x)
    if (length(ind)) writeLines(x[ind], file_out)
    x <- readLines(file_in, n=B)
}
close(file_in)
close(file_out)

यह लगभग वही है जो मैं लिख रहा था। मुझे लगता है कि यह भी सबसे अच्छा जवाब होगा, स्मृति की कमी, मिश्रित प्रकार, और विकृत पंक्तियाँ।
FTWynn

10

मैं इस पर एक विशेषज्ञ नहीं हूं, लेकिन आप MapReduce की कोशिश करने पर विचार कर सकते हैं , जिसका मूल रूप से "विभाजन और जीत" दृष्टिकोण लेना होगा। R के पास इसके लिए कई विकल्प हैं, जिनमें शामिल हैं:

  1. मेप्रेड्यूस (शुद्ध आर)
  2. RHIPE (जो Hadoop का उपयोग करता है ); फ़ाइलों को कम करने के उदाहरण के लिए प्रलेखन में उदाहरण देखें 6.2.2

वैकल्पिक रूप से, R बड़े डेटा से बाहर जाने वाली मेमोरी (डिस्क पर) से निपटने के लिए कई पैकेज प्रदान करता है। आप संभवत: पूरे डेटासेट को किसी bigmemoryऑब्जेक्ट में लोड कर सकते हैं और इसे पूरा करने के लिए टूल के सेट के लिए R. http://www.bigmemory.org/ देखें ।


अच्छा सुझाव है, लेकिन मुझे MapReduce और इसके ilk के साथ बहुत अनुभव नहीं है। मुझे इस पर पढ़ना होगा।
15

bigmemoryआपके लिए उस मामले में पहले प्रयास करना आसान हो सकता है।
शेन

10

क्या आर में एक समय में फ़ाइलों को एक टुकड़े में पढ़ने का एक समान तरीका है?

हाँ। ReadChar () समारोह संभालने वे अशक्त-समाप्त कर रहे हैं बिना वर्ण के एक ब्लॉक में पढ़ा जाएगा। यदि आप एक समय में एक पंक्ति में डेटा पढ़ना चाहते हैं तो आप रीडलाइन () का उपयोग कर सकते हैं । यदि आप एक ब्लॉक या एक पंक्ति पढ़ते हैं, एक ऑपरेशन करते हैं, तो डेटा को बाहर लिखें, आप मेमोरी मुद्दे से बच सकते हैं। हालाँकि अगर आपको ऐसा लगता है कि अमेजन के EC2 पर बड़ा मेमोरी इंस्टेंस फायरिंग कर रहा है तो आप 64GB तक की रैम पा सकते हैं। डेटा में हेरफेर करने के लिए आपकी फ़ाइल और कमरे में बहुत जगह होनी चाहिए।

यदि आपको अधिक गति की आवश्यकता है, तो शेन की मैप मैप को कम करने की सिफारिश बहुत अच्छी है। हालाँकि यदि आप EC2 पर एक बड़े मेमोरी इंस्टेंस का उपयोग करने के लिए जाते हैं, तो आपको मशीन पर सभी कोर का उपयोग करने के लिए मल्टीकोर पैकेज को देखना चाहिए।

यदि आप अपने आप को आर में सीमांकित डेटा के कई gigs को पढ़ने के लिए चाहते हैं, तो आपको कम से कम sqldf पैकेज पर शोध करना चाहिए जो आपको R से सीधे sqldf में आयात करने की अनुमति देता है और फिर R के भीतर से डेटा पर काम करता है। मैंने sqldf को एक पाया है इस पिछले प्रश्न में बताए अनुसार, डेटा के G को R में आयात करने के सबसे तेज़ तरीके ।


मैं एक EC2 उदाहरण को ध्यान में रखूंगा, लेकिन फिलहाल मुझे अपने डेस्कटॉप से ​​चिपकना है और यह 2GB RAM है। sqldf निश्चित रूप से ऐसा लगता है कि मेरे मन में क्या था। हालांकि, यह विकृत पंक्तियों पर भी चुटकुले हैं (17 कॉलम होने चाहिए, लेकिन कुछ हज़ार पंक्तियों में केवल एक ही है)। क्या वह किसी अन्य प्रीप्रोसेसिंग विधि के लिए कॉल करता है, या क्या कोई विकल्प है जो मुझे याद आ रहा है?
FTWynn

6

Colbycol नाम का एक नया पैकेज है जो आपको केवल उन चर में पढ़ने देता है, जिन्हें आप विशाल पाठ फ़ाइलों से चाहते हैं:

http://colbycol.r-forge.r-project.org/

यह read.table के साथ किसी भी तर्क को पारित करता है, इसलिए संयोजन को आपको बहुत कसकर कम करना चाहिए।


6

ffपैकेज विशाल फ़ाइलों से निपटने के लिए एक पारदर्शी तरीका है।

आप पैकेज वेबसाइट और / या इसके बारे में एक प्रस्तुति देख सकते हैं ।

आशा है कि ये आपकी मदद करेगा


5

आप SQLite डेटाबेस में डेटा आयात कर सकते हैं और फिर सबसेट का चयन करने के लिए RSQLite का उपयोग कर सकते हैं।


एक अच्छी योजना है, लेकिन चूंकि यह अनिवार्य रूप से पर्दे के पीछे स्क्वाल्ड करता है, इसलिए मैं इसे पसंद करूंगा। जब तक कि आप सीधे RSQLite का उपयोग न करें तो विकृत पंक्तियों को संभालने का एक बेहतर तरीका है?
FTWynn

5

उपयोग करने readrऔर read_*_chunkedपरिवार के बारे में क्या ?

तो आपके मामले में:

testfile.csv

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5
lol
Ada County;NC;2013;1;FIRE;Financial;Banks;82.5

वास्तविक कोड

require(readr)
f <- function(x, pos) subset(x, Year %in% c(2009, 2010))
read_csv2_chunked("testfile.csv", DataFrameCallback$new(f), chunk_size = 1)

यह fप्रत्येक चंक पर लागू होता है, कॉल-नामों को याद रखने और अंत में फ़िल्टर्ड परिणामों के संयोजन के लिए। देखें ?callbackकि इस उदाहरण का स्रोत क्या है।

इसका परिणाम यह होगा:

# A tibble: 2 × 8
      County State  Year Quarter Segment `Sub-Segment` `Sub-Sub-Segment`   GDP
*      <chr> <chr> <int>   <int>   <chr>         <chr>             <chr> <dbl>
1 Ada County    NC  2009       4    FIRE     Financial             Banks   801
2 Ada County    NC  2010       1    FIRE     Financial             Banks   825

आप बढ़ा भी सकते हैं chunk_sizeलेकिन इस उदाहरण में केवल 4 लाइनें हैं।



3

शायद आप MS Access सीमाओं से खुद को रोकने के लिए MySQL या PostgreSQL पर माइग्रेट कर सकते हैं।

R को इन सिस्टमों से DBI (CRAN पर उपलब्ध) आधारित डेटाबेस कनेक्टर से जोड़ना काफी आसान है ।


बेहतर डेटाबेस टूल का उपयोग करने के लिए टौचे, लेकिन चूंकि इसमें एक प्रशासनिक परेशानी शामिल होगी (बड़ी कंपनियों में उन प्रशासनिक नियमों से प्यार होगा), जो मेरे पास है, मैं उसके साथ रहने की कोशिश कर रहा हूं। इसके अलावा, मैं संभव के रूप में प्राप्त पाठ फ़ाइल के बीच कुछ रूपांतरण के लिए लक्ष्य कर रहा हूं।
FTWynn

3

स्कैन () में एक nlines तर्क और एक स्किप तर्क दोनों हैं। क्या कोई कारण है कि आप बस एक बार लाइनों के एक हिस्से में पढ़ने के लिए उपयोग कर सकते हैं, यह देखने के लिए कि क्या यह उचित है, तारीख की जांच कर रहा है? यदि इनपुट फ़ाइल का आदेश दिया जाता है, तो आप एक इंडेक्स स्टोर कर सकते हैं जो आपको बताता है कि आपकी स्किप और नैलाइन ऐसी होनी चाहिए जो भविष्य में प्रक्रिया को गति प्रदान करे।


मैं इसकी जाँच करूँगा, लेकिन तारीख जैसी मददगार किसी भी चीज़ के लिए फ़ाइल का आदेश नहीं दिया गया है। प्रदाताओं को लगता है कि एक काउंटी के दिए जाने से किस क्षेत्र को
छाँटना

मुझे लगता है कि आप उनके प्रस्ताव को गलत समझ रहे थे: अपनी फाइल को चंक द्वारा पढ़ें, और केवल उन पंक्तियों को निकालें जो आपको प्रत्येक चंक से चाहिए। फ़ाइलों को ऑर्डर करने की आवश्यकता नहीं है।
कार्ल फोर्नर

1

इन दिनों, 3.5GB बस वास्तव में इतना बड़ा नहीं है, मैं $ 2.80 / घंटे के लिए अमेज़न क्लाउड पर 244GB RAM (r3.8xlarge) के साथ एक मशीन तक पहुंच प्राप्त कर सकता हूं। बड़े-डेटा प्रकार के समाधान का उपयोग करके समस्या का समाधान करने में आपको कितने घंटे लगेंगे? आपका समय कितना कीमती है? हां, आपको AWS का उपयोग करने का पता लगाने में एक या दो घंटे का समय लगेगा - लेकिन आप मुफ्त टियर पर मूल बातें सीख सकते हैं, डेटा अपलोड कर सकते हैं और काम करने के लिए आर में पहली 10k लाइनों को पढ़ सकते हैं ताकि यह काम कर सके और फिर आप आग लगा सकते हैं r3.8xlarge जैसी बड़ी मेमोरी इंस्टेंस और इसे सभी में पढ़ें! बस मेरा 2 सी।


0

अब, 2017, मैं चिंगारी और स्पार्क के लिए जाने का सुझाव दूंगा।

  • वाक्यविन्यास को एक सरल नहीं बल्कि सरल तरीके से लिखा जा सकता है

  • यह छोटी मेमोरी (2017 के अर्थ में छोटा) के लिए काफी उपयुक्त है

हालाँकि, यह आरंभ करने के लिए एक डराने वाला अनुभव हो सकता है ...


-3

मैं एक DB के लिए जाऊंगा और फिर DBI के माध्यम से आवश्यक नमूनों को निकालने के लिए कुछ प्रश्न बनाऊंगा

कृपया SQLite में 3,5 GB सीएसवी फ़ाइल आयात करने से बचें। या कम से कम डबल चेक करें कि आपका बड़ा db SQLite सीमा, http://www.sqlite.org/limits.html में फिट बैठता है

यह एक बहुत बड़ा DB है जो आपके पास है। अगर आपको गति की आवश्यकता है तो मैं MySQL के लिए जाऊंगा। लेकिन आयात को खत्म करने के लिए कई घंटे इंतजार करने के लिए तैयार रहें। जब तक आपके पास कुछ अपरंपरागत हार्डवेयर नहीं है या आप भविष्य से लिख रहे हैं ...

अमेज़ॅन का EC2 R और MySQL चलाने वाले सर्वर को तुरंत चालू करने के लिए एक अच्छा समाधान हो सकता है।

मेरे दो विनम्र पैसे लायक हैं।


18
3.5Gb साइक्लाइट के लिए कितना बड़ा है? जब तक आप एक उपयुक्त फाइल सिस्टम का उपयोग कर रहे हैं तब तक कोई समस्या नहीं होनी चाहिए (मैं नियमित रूप से उपयोग कर रहा हूं> एकल उपयोगकर्ता अनुप्रयोगों के लिए 30Gb sqlite dbs)
आरोन स्टेटम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.