पांडा के साथ विश्लेषण के लिए एक 20GB फ़ाइल खोलना


33

मैं वर्तमान में मशीन सीखने के उद्देश्यों के लिए पांडा और अजगर के साथ एक फ़ाइल खोलने की कोशिश कर रहा हूं, यह मेरे लिए एक डेटाफ़्रेम में उन सभी के लिए आदर्श होगा। अब फ़ाइल 18 जीबी बड़ी है और मेरी रैम 32 जीबी है लेकिन मुझे मेमोरी एरर मिलती रहती है।

क्या आपके अनुभव से यह संभव है? यदि आप इसके चारों ओर जाने के लिए बेहतर तरीके से नहीं जानते हैं? (हाइव टेबल। मेरी रैम का आकार 64 तक बढ़ाएं। एक डेटाबेस बनाएं और इसे अजगर से एक्सेस करें)


मेरे पास एक ही मुद्दा है, मैं आपको अपनी हार्ड ड्राइव का स्वैप, पेजिंग, आकार बढ़ाने का सुझाव देता हूं।
मीडिया

डेटा लोड करते समय अंगूठे का नियम pandas, आपके पास 5-10 गुना अधिक रैम होना चाहिए। मैं inplaceपरिचालन करने की सलाह देता हूं , स्पष्ट रूप garbage.collectorसे वस्तुओं को आबंटित करने के लिए कहता हूं ।
किरीट गक

4
अपने अंतिम लक्ष्य को बताते हुए इस प्रश्न को बेहतर बनाएं। क्या आप खोजपूर्ण डेटा विश्लेषण, डेटा सफाई, एक मॉडल का प्रशिक्षण, या क्या कर रहे हैं? किस तरह का डेटा?
पीट

1
क्या आपने डस्क का उपयोग करने पर विचार किया है ?
रपनई

जवाबों:


32

यदि यह एक सीएसवी फ़ाइल है और आपको अपने एल्गोरिथ्म को प्रशिक्षित करते समय एक बार में सभी डेटा तक पहुंचने की आवश्यकता नहीं है, तो आप इसे विखंडू में पढ़ सकते हैं। pandas.read_csvविधि आप इस तरह मात्रा में एक फ़ाइल को पढ़ने के लिए अनुमति देता है:

import pandas as pd
for chunk in pd.read_csv(<filepath>, chunksize=<your_chunksize_here>)
    do_processing()
    train_algorithm()

यहाँ विधि का प्रलेखन है


क्या यह ज़िप फ़ाइल पर भी लागू होता है?
जेम्स विर्ज़बा

यह काम करना चाहिए अगर ज़िपित फ़ाइल भी एक सीएसवी फ़ाइल है, तो आपको विधि के तर्क के रूप में संपीड़न प्रकार पास करना होगा
ओलेल डैनियल

22

दो संभावनाएं हैं: या तो आप की जरूरत है (उदाहरण के लिए अपने मशीन लर्निंग एल्गोरिथ्म एक ही बार में यह के सभी उपभोग करने के लिए चाहते हो जाएगा) के प्रसंस्करण के लिए स्मृति में अपने सभी डेटा के लिए, या आप इसे बिना कर सकते हैं (उदाहरण के लिए अपने एल्गोरिथ्म केवल पंक्तियों के नमूने की जरूरत है या कॉलम एक बार)।

पहले मामले में, आपको एक मेमोरी समस्या को हल करने की आवश्यकता होगी । अपने मेमोरी साइज़ को बढ़ाएँ, एक हाई-मेमोरी क्लाउड मशीन को किराए पर लें, इनलेट ऑपरेशंस का उपयोग करें, आपके द्वारा पढ़े जा रहे डेटा के प्रकार के बारे में जानकारी प्रदान करें, सभी अप्रयुक्त चरों को हटा दें और कचरा इकट्ठा करें, आदि।

यह बहुत संभावना है कि 32 जीबी रैम आपके डेटा को संभालने के लिए पंडों के लिए पर्याप्त नहीं होगा। ध्यान दें कि पूर्णांक "1" पाठ के रूप में संग्रहीत होने पर केवल एक बाइट है, लेकिन 8 बाइट्स के रूप में प्रतिनिधित्व किया जाता है int64(जो कि पंडों द्वारा पाठ से पढ़ने पर डिफ़ॉल्ट है)। आप एक अस्थायी बिंदु संख्या "1.0" के साथ एक ही उदाहरण बना सकते हैं जो 3-बाइट स्ट्रिंग से 8-बाइट float64डिफ़ॉल्ट रूप से फैलता है । आप पंडों को सटीक रूप से यह बताकर कुछ स्थान जीत सकते हैं कि प्रत्येक कॉलम के लिए किस प्रकार का उपयोग करना है और सबसे छोटे संभव निरूपण को मजबूर करना है, लेकिन हमने यहां पायथन के डेटा संरचना के ओवरहेड के बारे में बोलना भी शुरू नहीं किया है, जो यहां या वहां आसानी से एक अतिरिक्त सूचक या दो जोड़ सकते हैं। , और पॉइंटर्स 64-बिट मशीन पर 8 बाइट्स हैं।

संक्षेप में: नहीं, 32 जीबी रैम 20 जीबी फ़ाइल को संभालने के लिए शायद पंडों के लिए पर्याप्त नहीं है।

दूसरे मामले में (जो अधिक यथार्थवादी है और संभवतः आपके लिए लागू होता है), आपको डेटा प्रबंधन समस्या को हल करने की आवश्यकता है । वास्तव में, जब आपको वास्तव में केवल प्रसंस्करण के लिए इसके कुछ हिस्सों की आवश्यकता होती है, तो सभी डेटा लोड करना, खराब डेटा प्रबंधन का संकेत हो सकता है। यहाँ कई विकल्प हैं:

  1. SQL डेटाबेस का उपयोग करें। यदि आप कर सकते हैं, यह लगभग हमेशा पहली पसंद है और एक शालीनता से आरामदायक समाधान है। आकार की तरह 20GB लगता है कि अधिकांश SQL डेटाबेस एक (उच्च-अंत) लैपटॉप पर भी वितरित किए जाने की आवश्यकता के बिना अच्छी तरह से संभाल लेंगे। आप स्तंभों को अनुक्रमित करने में सक्षम होंगे, SQL के माध्यम से बुनियादी एकत्रीकरण करेंगे, और एक सरल का उपयोग करके अधिक जटिल प्रसंस्करण के लिए पंडों में आवश्यक उपप्रकारों को प्राप्त कर सकते हैं pd.read_sql। डेटा को डेटाबेस में ले जाना आपको अपने कॉलम के वास्तविक डेटा प्रकारों और आकारों के बारे में सोचने का अवसर प्रदान करेगा ।

  2. यदि आपका डेटा ज्यादातर संख्यात्मक (यानी सरणियाँ या दशांश) है, तो आप इसे HDF5 प्रारूप ( PyTables देखें ) में रखने पर विचार कर सकते हैं , जो आपको डिस्क से विशाल सरणियों के केवल आवश्यक स्लाइस को आसानी से पढ़ने देता है। बेसिक numpy.save और numpy.load डिस्क पर मेमोरी-मैपिंग के माध्यम से भी समान प्रभाव प्राप्त करते हैं। जीआईएस और संबंधित रैस्टर डेटा के लिए समर्पित डेटाबेस हैं , जो शायद SQL के रूप में सीधे पांडा से कनेक्ट नहीं हो सकते हैं, लेकिन आपको स्लाइस और प्रश्नों को यथोचित रूप से आसानी से करने देना चाहिए।

  3. जहां तक ​​मुझे पता है, पंडित एचडीएफ 5 या सुपीरियर सरणियों के "आंशिक" मेमोरी-मैपिंग का समर्थन नहीं करते हैं। यदि आप अभी भी एक प्रकार का "शुद्ध-पांडा" समाधान चाहते हैं, तो आप "शार्डिंग" द्वारा काम करने की कोशिश कर सकते हैं: या तो अपनी विशाल तालिका के स्तंभों को अलग-अलग संग्रहीत करें (जैसे अलग-अलग फ़ाइलों में या किसी एकल HDF5 के "अलग-अलग" तालिकाओं में)। फ़ाइल) और केवल आवश्यक ऑन-डिमांड लोड करना, या पंक्तियों के अलग-अलग भंडारण करना । फिर भी, आपको आवश्यक चंक्स को लोड करने के लिए तर्क को लागू करने की आवश्यकता होगी, इस प्रकार अधिकांश SQL डेटाबेस में पहले से ही लागू की गई साइकिलों को सुदृढ़ करना, इसलिए शायद विकल्प 1 अब भी यहां आसान होगा। यदि आपका डेटा एक CSV में आता है, हालांकि, आप chunksizeपैरामीटर को निर्दिष्ट करके इसे विखंडू में संसाधित कर सकते हैं pd.read_csv


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

9

मैं अभी कुछ दिनों पहले यह मुद्दा था! सुनिश्चित नहीं है कि यह आपके विशिष्ट मामले में मदद करता है क्योंकि आप इतने सारे विवरण प्रदान नहीं कर रहे हैं, लेकिन मेरी स्थिति एक 'बड़े' डेटासेट पर ऑफ़लाइन काम करने की थी। डेटा को ऊर्जा मीटरों से 20GB gzipped CSV फ़ाइलों के रूप में प्राप्त किया गया था, कई सेकंड के अंतराल पर समय श्रृंखला डेटा।

फ़ाइल IO:

data_root = r"/media/usr/USB STICK"
fname = r"meters001-050-timestamps.csv.gz"
this_file = os.path.join(data_root,fname)
assert os.path.exists(this_file), this_file
this_file

सीधे gzip फ़ाइल के ऊपर एक chunk पुनरावृत्ति बनाएँ (अनज़िप न करें!)

cols_to_keep = [0,1,2,3,7]
column_names = ['METERID','TSTAMP','ENERGY','POWER_ALL','ENERGY_OUT',]
parse_dates = ['TSTAMP']
dtype={'METERID': np.int32, 
       'ENERGY': np.int32,
       'POWER_ALL': np.int32,
       'ENERGY_OUT': np.int32,
      }
df_iterator = pd.read_csv(this_file, 
                        skiprows=0, 
                        compression='gzip',
                        chunksize=1000000, 
                        usecols=cols_to_keep,
                        delimiter=";",
                        header=None,
                        names = column_names,
                      dtype=dtype,
                     parse_dates=parse_dates,
                     index_col=1,
                     )

विखंडू पर Iterate

new_df = pd.DataFrame()
count = 0
for df in df_iterator:
    chunk_df_15min = df.resample('15T').first()
    #chunk_df_30min = df.resample('30T').first()
    #chunk_df_hourly = df.resample('H').first()
    this_df = chunk_df_15min
    this_df = this_df.pipe(lambda x: x[x.METERID == 1])
    #print("chunk",i)
    new_df = pd.concat([new_df,chunk_df_15min])
    print("chunk",count, len(chunk_df_15min), 'rows added')
    #print("chunk",i, len(temp_df),'rows added')
    #break
    count += 1

चंक लूप के अंदर, मैं समय पर कुछ फ़िल्टरिंग और पुनः नमूना कर रहा हूं। ऐसा करने से मैंने आकार को और अधिक ऑफ़लाइन डेटा अन्वेषण के लिए 20 जीबी से कुछ सौ एमबी एचडीएफ 5 तक कम कर दिया।


5

मेरे अनुभव में, बड़ी फ़ाइलों में पढ़ते समय read_csv()पैरामीटर low_memory=Falseके साथ इनिशियलाइज़िंग मदद करता है। मुझे नहीं लगता कि आपने उस फ़ाइल प्रकार का उल्लेख किया है जिसे आप पढ़ रहे हैं, इसलिए मुझे यकीन नहीं है कि यह आपकी स्थिति के लिए कितना लागू है।


1

अगर आपकी फ़ाइल CSV है तो आप इसे केवल Chunk by Chunk में कर सकते हैं। आप बस कर सकते हैं:

import pandas as pd
for chunk in pd.read_csv(FileName, chunksize=ChunkSizeHere)
(Do your processing and training here)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.