पांडा में बड़े, लगातार DataFrame


91

मैं लंबे समय तक एसएएस उपयोगकर्ता के रूप में अजगर और पांडा पर स्विच कर रहा हूं।

हालांकि, जब आज कुछ परीक्षण चल रहे हैं, तो मुझे आश्चर्य हुआ कि अजगर कोशिश करते समय याददाश्त से बाहर चला गया pandas.read_csv() 128mb की सीएसवी फ़ाइल की । इसमें लगभग 200,000 पंक्तियाँ और अधिकतर संख्यात्मक डेटा के 200 स्तंभ थे।

एसएएस के साथ, मैं एसएएस डेटासेट में एक सीएसवी फ़ाइल आयात कर सकता हूं और यह मेरी हार्ड ड्राइव जितनी बड़ी हो सकती है।

क्या कुछ अनुरूप है? pandas ?

मैं नियमित रूप से बड़ी फ़ाइलों के साथ काम करता हूं और एक वितरित कंप्यूटिंग नेटवर्क तक पहुंच नहीं है।


मैं पंडों से परिचित नहीं हूँ, लेकिन आप फ़ाइल के माध्यम से पुनरावृत्ति करना चाह सकते हैं। pandas.pydata.org/pandas-docs/stable/…
monkut

जवाबों:


79

सिद्धांत रूप में यह स्मृति से बाहर नहीं चलना चाहिए, लेकिन वर्तमान read_csvमें कुछ जटिल पायथन आंतरिक मुद्दों के कारण बड़ी फ़ाइलों पर मेमोरी समस्याएं हैं (यह अस्पष्ट है लेकिन यह लंबे समय से ज्ञात है: http://github.com/pydata / पांडा / अंक / 407 )।

फिलहाल कोई सही समाधान नहीं है (यहां एक थकाऊ है: आप फ़ाइल पंक्ति-दर-पंक्ति को एक पूर्व-आवंटित NumPy सरणी या मेमोरी-मैप की गई फ़ाइल में स्थानांतरित कर सकते हैं - np.mmap), लेकिन यह एक है जो मैं काम कर रहा हूँ निकट भविष्य में। एक अन्य उपाय यह है कि फ़ाइल को छोटे टुकड़ों में उपयोग करें (उपयोग करें iterator=True, chunksize=1000) उसके बाद फिर से समतल करें pd.concat। समस्या तब आती है जब आप पूरी टेक्स्ट फ़ाइल को एक बड़े स्लरप में मेमोरी में खींचते हैं।


1
कहते हैं कि मैं फ़ाइल को पढ़ सकता हूं और उन सभी को एक साथ एक DataFrame में रख सकता हूं। क्या DataFrame को स्मृति में निवास करना है? एसएएस के साथ, मैं किसी भी आकार के डेटासेट के साथ काम कर सकता हूं जब तक मेरे पास हार्ड-ड्राइव स्पेस है। क्या DataFrames के साथ भी ऐसा ही है? मुझे लगता है कि वे राम द्वारा विवश हैं और हार्ड-ड्राइव स्थान नहीं है। नॉब प्रश्न के लिए क्षमा करें और आपकी मदद के लिए धन्यवाद। मैं तुम्हारी किताब का आनंद ले रहा हूं।
ज़ेलज़नी 7

3
ठीक है, तुम राम द्वारा विवश हो। एसएएस के पास वास्तव में "आउट-ऑफ-कोर" बिग डेटा प्रोसेसिंग के लिए बेहतर समर्थन है।
वेस मैकिनी

5
@WesMcKinney इन वर्कअराउंडों की अब कोई आवश्यकता नहीं होनी चाहिए, क्योंकि नए सीएसवी लोडर के कारण आप 0.10 में उतरे हैं, है ना?
गेब्रियल ग्रांट

79

वेस बिल्कुल सही है! मैं सिर्फ थोड़ा और पूर्ण उदाहरण कोड प्रदान करने के लिए चिंहित कर रहा हूं। मेरे पास 129 एमबी फाइल के साथ एक ही मुद्दा था, जिसे हल किया गया था:

import pandas as pd

tp = pd.read_csv('large_dataset.csv', iterator=True, chunksize=1000)  # gives TextFileReader, which is iterable with chunks of 1000 rows.
df = pd.concat(tp, ignore_index=True)  # df is DataFrame. If errors, do `list(tp)` instead of `tp`

6
मुझे लगता है कि आप बस कर सकते हैं df = concate(tp, ignore_index=True)?
एंडी हेडन

@smci ने एक ही डेटा दोहराया x4 (550 एमबी) या x8 (1.1Gb) के साथ इसे जल्दी से आज़माया। दिलचस्प है, के साथ या बिना [x के लिए x में tp], x4 ठीक से गुजरा, और x8 एक मेमोरी कार्ड में दुर्घटनाग्रस्त हो गया।
विकर्ण

3
इसका उपयोग करते समय मुझे यह त्रुटि मिलती है AssertionError: first argument must be a list-like of pandas objects, you passed an object of type "TextFileReader":। किसी भी विचार यहाँ क्या हो रहा है?
राजकुमार कुमार

3
यह बग 0.14 (जल्द रिलीज), github.com/pydata/pandas/pull/6941 में तय किया जाएगा ; <0.14.0 के लिए वर्कअराउंड करना हैpd.concat(list(tp), ignore_index=True)
जेफ

1
क्या होगा यदि मान स्ट्रिंग्स या श्रेणीबद्ध हैं - मुझे त्रुटि मिल रही है: श्रेणीबद्ध
संघात

41

यह एक पुराना धागा है, लेकिन मैं बस अपना समाधान समाधान यहां डंप करना चाहता था। मैंने शुरू में chunksizeपैरामीटर की कोशिश की (यहां तक ​​कि 10000 जैसे काफी छोटे मूल्यों के साथ), लेकिन यह बहुत मदद नहीं करता था; मेमोरी साइज़ के साथ अभी भी तकनीकी समस्याएँ थीं (मेरा CSV ~ 7.5 Gb था)।

अभी, मैं बस एक लूप अप्रोच में सीएसवी फाइलों के चंक्स को पढ़ता हूं और उन्हें उदाहरणार्थ जोड़ता हूं, जैसे SQLite डेटाबेस में:

import pandas as pd
import sqlite3
from pandas.io import sql
import subprocess

# In and output file paths
in_csv = '../data/my_large.csv'
out_sqlite = '../data/my.sqlite'

table_name = 'my_table' # name for the SQLite database table
chunksize = 100000 # number of lines to process at each iteration

# columns that should be read from the CSV file
columns = ['molecule_id','charge','db','drugsnow','hba','hbd','loc','nrb','smiles']

# Get number of lines in the CSV file
nlines = subprocess.check_output('wc -l %s' % in_csv, shell=True)
nlines = int(nlines.split()[0]) 

# connect to database
cnx = sqlite3.connect(out_sqlite)

# Iteratively read CSV and dump lines into the SQLite table
for i in range(0, nlines, chunksize):

    df = pd.read_csv(in_csv,  
            header=None,  # no header, define column header manually later
            nrows=chunksize, # number of rows to read at each iteration
            skiprows=i)   # skip rows that were already read

    # columns to read        
    df.columns = columns

    sql.to_sql(df, 
                name=table_name, 
                con=cnx, 
                index=False, # don't use CSV file index
                index_label='molecule_id', # use a unique column from DataFrame as index
                if_exists='append') 
cnx.close()    

4
सुपर उपयोगी chunked पढ़ने की सुविधा के लिए एक यथार्थवादी उपयोग-मामला देखने के लिए। धन्यवाद।
एलेक्स केस्टनर

5
बस एक छोटा सा टिप्पणी, इस पुराने विषय से: pandas.read_csvसीधे (कम से कम संस्करण मैं वर्तमान में उपयोग कर रहा हूँ पर) पुनरावर्तक अगर आप बस प्रदान करते हैं रिटर्न iterator=Trueऔर chunksize=chunksize। इसलिए, आप कॉल forपर एक लूप करेंगे pd.read_csv, बजाय इसे हर बार री-इंस्टेंट करने के। हालांकि, यह केवल कॉल ओवरहेड की लागत है, शायद कोई महत्वपूर्ण प्रभाव नहीं है।
जोएल

1
हाय, जोएल। नोट के लिए धन्यवाद! iterator=Trueऔर chunksizeमानकों को पहले से ही वापस तो अस्तित्व में अगर मैं सही ढंग से याद है। हो सकता है कि पुराने संस्करण में एक बग था जो मेमोरी ब्लो-अप का कारण बना - मैं इसे अगली बार एक और कोशिश दूंगा जब मैंने पंडों में एक बड़ा डेटाफ्रेम पढ़ा (मैं ज्यादातर ऐसे कार्यों के लिए अब ब्लेज़ का उपयोग कर रहा हूं)

6

नीचे मेरा काम प्रवाह है।

import sqlalchemy as sa
import pandas as pd
import psycopg2

count = 0
con = sa.create_engine('postgresql://postgres:pwd@localhost:00001/r')
#con = sa.create_engine('sqlite:///XXXXX.db') SQLite
chunks = pd.read_csv('..file', chunksize=10000, encoding="ISO-8859-1",
                     sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

अपने फ़ाइल आकार के आधार पर, आप बेहतर रूप से हिस्सा चुन लेंगे।

 for chunk in chunks:
        chunk.to_sql(name='Table', if_exists='append', con=con)
        count += 1
        print(count)

डेटाबेस में सभी डेटा होने के बाद, आप डेटाबेस से उन ज़रूरतों को बाहर निकाल सकते हैं।


3

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

जीथब पर डस्क से लिंक


धन्यवाद, जब से मैंने यह पोस्ट किया है मैं dask और parquet प्रारूप का उपयोग कर रहा हूं।
ज़ेलज़नी

1

आप पंडों डीएफ के बजाय पाइटेबल का उपयोग कर सकते हैं। यह बड़े डेटा सेट के लिए डिज़ाइन किया गया है और फ़ाइल प्रारूप HDf5 में है। तो प्रसंस्करण समय अपेक्षाकृत तेज है।

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