आप पायथन में विखंडू में बिना तालिका वाले डेटा के साथ एक बड़ी फ़ाइल कैसे पढ़ते हैं?

Dec 21 2020

मेरे पास एक बड़ी CSV फ़ाइल (> 100 GB) है जिसे मैं मेमोरी में पढ़ना और डेटा को चंक्स में प्रोसेस करना चाहता हूं। मेरे पास दो अड़चनें हैं:

  1. जाहिर है मैं पूरी की पूरी फाइल को मेमोरी में नहीं पढ़ सकता। मेरे पास केवल 8GB RAM है मेरी मशीन पर।
  2. डेटा सारणीबद्ध और अव्यवस्थित है। मुझे समूहों में डेटा पढ़ने की आवश्यकता है।
लंगर तारीख फ़ील्ड 1 फ़ील्ड 2 फ़ील्ड 3
AAPL 20201201
AAPL 20201202
AAPL 20201203
AAPL 20201204
NFLX 20201201
NFLX 20201202
NFLX 20201203
NFLX 20201204

यहां चिंता यह है कि डेटा को समूहों में पढ़ा जाना है। टिकर और तारीख द्वारा समूहीकृत। अगर मैं कहूं कि मैं प्रत्येक बैच में 10,000 रिकॉर्ड पढ़ना चाहता हूं। उस बैच की सीमा को समूहों को विभाजित नहीं करना चाहिए। यानी 2020 दिसंबर के लिए सभी AAPL डेटा को एक ही बैच में समाप्त होना चाहिए। वह डेटा दो बैचों में दिखाई नहीं देना चाहिए।

मेरे अधिकांश सहकर्मी जब इस तरह की स्थिति का सामना करते हैं, तो वे आमतौर पर एक बैश स्क्रिप्ट बनाते हैं जहां वे डेटा को समूहों में विभाजित करने और डिस्क पर कई मध्यवर्ती फ़ाइलों को लिखने के लिए awk, cut, sort, uniq का उपयोग करते हैं। फिर वे इन फ़ाइलों को संसाधित करने के लिए पायथन का उपयोग करते हैं। मैं सोच रहा था कि क्या वहाँ एक समरूप पायथन / पंडों / Numpy समाधान है।

जवाब

genodeftest Dec 21 2020 at 03:11

इस बारे में कैसा है:

  1. फ़ाइल खोलें
  2. पठन लाइनों पर लूप: प्रत्येक पंक्ति के लिए पठन:
  • टिकर को पार्स करें
  • यदि पहले से नहीं किया है:
    • उस टिकर के लिए एक फ़ाइल बनाएँ + (" टिकर फ़ाइल ")
    • कुछ डिक्टेंड में जाएं जहां की = टिकर और वैल्यू = फाइल हैंडल
  • टिकर फ़ाइल को लाइन लिखें
  1. बंद टिकर फ़ाइलों और मूल फ़ाइल
  2. प्रत्येक एकल टिकर फ़ाइल को संसाधित करें
Martin Dec 21 2020 at 03:44

मैं दो विकल्पों पर गौर करूंगा

वैक्स और मास्क

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

जहां तक ​​डैस्क का सवाल है, मैं सफलता पर भरोसा नहीं करूंगा। डस्क मुख्य रूप से वितरित संगणना पर केंद्रित है और मुझे वास्तव में यकीन नहीं है कि यह बड़ी फ़ाइलों को आलसी रूप से संसाधित कर सकता है। लेकिन आप कोशिश करके देख सकते हैं।

tgrandje Dec 23 2020 at 03:05

यह दृष्टिकोण शुद्ध पांडा है। यह दो कार्यों का उपयोग करेगा: एक अनुक्रमणिका की गणना करने के लिए, एक चंक को पढ़ने के लिए। मैं कहूंगा कि यदि आपका कोई समूह स्मृति में फिट नहीं होता है (लेकिन आपके मानदंड दिए गए हैं कि उन समूहों को एक बार में पढ़ा जाना चाहिए, तो मैं कहूंगा कि यह एक निश्चित अनुमान होगा कि यह फिट बैठता है)।

पूरे डेटाफ़्रेम को पढ़ने के लिए आपको अनुक्रमणिका की डिक्शनरी (पहले फ़ंक्शन से गणना की गई) पर लूप करने की आवश्यकता होगी।

आशा है कि मदद मिलेगी ... (अपनी आवश्यकताओं के लिए संक्षिप्त आकार को अनुकूलित करने में संकोच न करें)।

import pandas as pd

def compute_indexes(url, cols_indexes=[], chunksize=100000, **kwargs):
    """
    Returns a dictionnary
    Keys are the pseudo indexes of the dataframe 
    Values are lists of indexes corresponding to this index
    """
    iterator = pd.read_csv(
            url, 
            usecols=cols_indexes, 
            chunksize=chunksize,
            **kwargs)
    
    dict_groups = dict()
    for df in iterator:
        groups_present = df.drop_duplicates(keep="first").values.tolist()
        df.reset_index(drop=False, inplace=True)
        df.set_index(cols_indexes, inplace=True)
        for group in groups_present:
            group = tuple(group)
            if group not in dict_groups:
                dict_groups[group] = []
            try:
                dict_groups[group] += df.loc[group]['index'].tolist()
            except TypeError:
                #only one row
                dict_groups[group] += [df.loc[group]['index']]
                
    return dict_groups

def read_csv_group(url, dict_groups, which_group, **kwargs):
    if isinstance(which_group, list):
        which_group = tuple(which_group)
    rows = dict_groups[which_group]
    def skip_rows(x):
        if x == 0:
            return False
        elif x in {x+1 for x in rows}:
            return False
        else:
            return True
    df = pd.read_csv(url, skiprows=skip_rows, **kwargs)
    return df
    
URL = "./dummy.csv"
indexes = ['Ticker', 'Date']
kwargs = {'dtype':{'Ticker':str, 'Date':int})
dict_groups = compute_indexes(URL, indexes, chunksize=100000, **kwargs)
df_one_group = read_csv_group(URL, dict_groups, ('AAPL', 20201201), **kwargs)