पंडों का उपयोग करके डेटाफ्रेम कैसे स्टोर करें


317

अभी मैं CSVस्क्रिप्ट चलाने पर हर बार डेटाफ़्रेम के रूप में एक बहुत बड़ा आयात कर रहा हूं । क्या उस डेटाफ़्रेम को रनों के बीच लगातार उपलब्ध रखने के लिए एक अच्छा समाधान है इसलिए मुझे उस सभी समय को खर्च करने की ज़रूरत नहीं है जो स्क्रिप्ट चलाने के लिए इंतजार कर रहा है?


2
हाँ, यह पायथन का उपयोग करके मेरी प्रमुख शिकायतों में से एक है - डेटा फ़्रेम को सहेजने और पुनर्प्राप्त करने का कोई सरल तरीका नहीं है। इस संबंध में आर और एसएएस कहीं अधिक उपयोगकर्ता के अनुकूल हैं।
राबर्ट एफ

जवाबों:


481

सबसे आसान तरीका है अचार का उपयोग कर इसे to_pickle:

df.to_pickle(file_name)  # where to save it, usually as a .pkl

फिर आप इसका उपयोग करके वापस लोड कर सकते हैं:

df = pd.read_pickle(file_name)

नोट: 0.11.1 से पहले saveऔर loadऐसा करने का एकमात्र तरीका था (वे अब क्रमशः to_pickleऔर उसके पक्ष में पदावनत हो read_pickleगए हैं)।


एक अन्य लोकप्रिय विकल्प का उपयोग करने के लिए है HDF5 ( pytables ) जो प्रदान करता है बहुत तेजी से बड़े डेटा सेट के लिए अभिगम समय:

store = HDFStore('store.h5')

store['df'] = df  # save it
store['df']  # load it

कुकबुक में अधिक उन्नत रणनीतियों पर चर्चा की जाती है ।


0.13 के बाद से msgpack भी है जो JSON के तेज विकल्प के रूप में, इंटरऑपरेबिलिटी के लिए बेहतर हो सकता है, या यदि आपके पास अजगर ऑब्जेक्ट / टेक्स्ट-हैवी डेटा ( यह प्रश्न देखें )।


8
@geekazoid बचाने के लिए to_pickle (जो कि csv के बजाय अचार बनाता है, जो बहुत तेज़ / अलग वस्तु है) को अपग्रेड किया जाता है।
एंडी हेडन

9
@geekazoid यदि लोड करने के बाद डेटा को बदलने की आवश्यकता है (यानी datetime64 पर स्ट्रिंग / ऑब्जेक्ट) तो सहेजे गए सीएसवी को लोड करने के बाद इसे फिर से करने की आवश्यकता होगी, जिसके परिणामस्वरूप प्रदर्शन हानि हो सकती है। अचार डेटाफ़्रेम को वर्तमान स्थिति में सहेजता है इस प्रकार डेटा और उसका प्रारूप संरक्षित रहता है। इससे बड़े पैमाने पर प्रदर्शन बढ़ सकता है।
हरबुन

4
अचार और HDFStore दोनों ही 8GB से अधिक डेटाफ्रेम नहीं बचा सकते हैं। क्या कोई विकल्प हैं?
15:17 बजे user1700890

1
@ user1700890 यादृच्छिक डेटा (पाठ और सरणियों) से उत्पन्न करने की कोशिश करते हैं और एक नया प्रश्न पोस्ट करते हैं। मुझे नहीं लगता कि यह सही / संदिग्ध हो सकता है कि हम कुछ याद कर रहे हैं। नए प्रश्न को और अधिक आँखें मिलेंगी, लेकिन एक DataFrame को शामिल करने / उत्पन्न करने की कोशिश करेंगे जो पुन: पेश करता है :)
एंडी हेडन

1
@YixingLiu आप इस तथ्य के बाद मोड को बदल सकते हैं stackoverflow.com/a/16249655/1240268
एंडी हेडन

100

हालाँकि पहले से ही कुछ जवाब हैं, मुझे एक अच्छी तुलना मिली, जिसमें उन्होंने पंडों के डेटाफ़्रेम को क्रमबद्ध करने के कई तरीके आज़माए: कुशल रूप से पंडों के डेटाफ़्रेम स्टोर

वे तुलना करते हैं:

  • अचार: मूल ASCII डेटा प्रारूप
  • cPickle, एक सी लाइब्रेरी
  • अचार-P2: नए बाइनरी प्रारूप का उपयोग करता है
  • json: standardlib json लाइब्रेरी
  • json-no-index: जैसे json, लेकिन इंडेक्स के बिना
  • msgpack: बाइनरी JSON विकल्प
  • सीएसवी
  • HDfstore: HDF5 भंडारण प्रारूप

अपने प्रयोग में, वे अलग-अलग परीक्षण किए गए दो स्तंभों के साथ 1,000,000 पंक्तियों के डेटाफ़्रेम को क्रमबद्ध करते हैं: एक पाठ डेटा के साथ, दूसरा संख्याओं के साथ। उनका अस्वीकरण कहता है:

आपको भरोसा नहीं करना चाहिए कि आपके डेटा का सामान्यीकरण निम्नानुसार है। आपको अपना डेटा देखना चाहिए और स्वयं बेंचमार्क चलाना चाहिए

परीक्षण के लिए स्रोत कोड जिसे वे संदर्भित करते हैं ऑनलाइन उपलब्ध है । : चूंकि यह कोड सीधे काम नहीं किया मैं कुछ मामूली परिवर्तन, जिसे आप यहां प्राप्त कर सकते हैं बनाया serialize.py मैं निम्न परिणाम है:

समय तुलना परिणाम

वे यह भी उल्लेख करते हैं कि पाठ डेटा को श्रेणीबद्ध डेटा में रूपांतरित करने के साथ क्रमबद्धता बहुत तेज है। उनके परीक्षण में लगभग 10 गुना तेज (परीक्षण कोड भी देखें)।

संपादित करें : CSV की तुलना में अचार का अधिक समय उपयोग किए गए डेटा प्रारूप द्वारा समझाया जा सकता है। डिफ़ॉल्ट रूप से pickleएक मुद्रण योग्य ASCII प्रतिनिधित्व का उपयोग करता है, जो बड़े डेटा सेट उत्पन्न करता है। जैसा कि ग्राफ से देखा जा सकता है, लेकिन नए बाइनरी डेटा फॉर्मेट (संस्करण 2 pickle-p2) का उपयोग करने वाले अचार का लोड समय बहुत कम होता है।

कुछ अन्य संदर्भ:


1
मैंने आपके प्रश्न को समझाने के लिए अपना उत्तर अपडेट किया। संक्षेप में: ASCII प्रारूप में डिफ़ॉल्ट अचार भंडार डेटा द्वारा।
agold

1
आह, उस स्पष्टीकरण के लिए धन्यवाद! एक नोट के रूप में, पांडा DataFrame .to_pickle pkl.HIGHEST_PROTOCOL का उपयोग कर किया जा रहा है (होना चाहिए 2)
NTG

2
ऐसा लगता है कि ऊपर लिंक किया गया ब्लॉग ( कुशल स्टोर पंडास डेटाफ्रैम हटा दिया गया है। मैंने अपनी खुद की तुलना .to_pickle()(जिसके बारे में बाइनरी स्टोरेज का उपयोग करता है) के खिलाफ .to_hdf()(बिना संपीड़न के) किया था। लक्ष्य गति, एचडीएफ के लिए फ़ाइल का आकार 11x अचार था, और लोड करने का समय। 5x अचार था। मेरा डेटा ~ 5k फाइलें ~ 7k पंक्तियों x 6
कॉल

1
पृष्ठ अभी भी मौजूद है, आपको बस पीछे हटने
IanSR

2
@ माइक विलियम्सन, मेरे परीक्षण में, एचडीएफ की तुलना में अचार 5x तेज था और साथ ही 1/11 डिस्क स्थान लेता था (यानी एचडीएक्स डिस्क पर 11 गुना बड़ा था और अचार के रूप में डिस्क से लोड होने में 5 गुना अधिक समय लगता था)। यह सब पांडा 0.22.0 के साथ अजगर 3 पर था।
हैमक्स ०

35

अगर मैं सही तरीके से समझूं, तो आप पहले से ही उपयोग कर रहे हैं, pandas.read_csv()लेकिन विकास प्रक्रिया को गति देना चाहेंगे ताकि आपको अपनी स्क्रिप्ट को संपादित करने के लिए हर बार फ़ाइल लोड न करनी पड़े, क्या यह सही है? मेरी कुछ सिफारिशें हैं:

  1. pandas.read_csv(..., nrows=1000)जब आप विकास कर रहे हों, तो आप केवल तालिका के शीर्ष बिट को लोड करने के लिए CSV फ़ाइल के केवल भाग में लोड कर सकते हैं

  2. एक इंटरैक्टिव सत्र के लिए ipython का उपयोग करें , जैसे कि आप पंडों की तालिका को स्मृति में रखते हैं जैसा कि आप संपादित करते हैं और अपनी स्क्रिप्ट को फिर से लोड करते हैं।

  3. सीएसवी को एचडीएफ 5 टेबल में बदलें

  4. अद्यतन उपयोग DataFrame.to_feather()और pd.read_feather()आर-संगत पंख बाइनरी प्रारूप में डेटा संग्रहीत करने के लिए जो सुपर फास्ट (मेरे हाथों में, pandas.to_pickle()संख्यात्मक डेटा की तुलना में थोड़ा तेज और स्ट्रिंग डेटा पर बहुत तेज है)।

स्टैकओवरफ़्लो पर इस उत्तर में भी आपकी रुचि हो सकती है ।


क्या आप जानते हैं कि to_featherस्ट्रिंग डेटा पर अच्छा काम क्यों होगा? मैंने बेंचमार्क किया to_pickleऔर to_featureमेरे संख्यात्मक डेटाफ्रेम और अचार के बारे में 3x तेज है।
14

@zyxue अच्छा सवाल है, मैं ईमानदारी से पंख सामान के साथ ज्यादा नहीं खेला है, तो मैं एक जवाब नहीं है
नूह

20

अचार अच्छा काम करता है!

import pandas as pd
df.to_pickle('123.pkl')    #to save the dataframe, df to 123.pkl
df1 = pd.read_pickle('123.pkl') #to load 123.pkl back to the dataframe df

8
ध्यान दें कि उत्पन्न की गई फाइलें सीएसवी फाइलें नहीं हैं, हो सकता है कि एक्सटेंशन का उपयोग करना बेहतर हो .pklजैसा कि @Andy हेडेंस उत्तर में दिया गया है।
एगोल्ड


4

पंडों DataFrames to_pickleफ़ंक्शन है जो एक DataFrame को बचाने के लिए उपयोगी है:

import pandas as pd

a = pd.DataFrame({'A':[0,1,0,1,0],'B':[True, True, False, False, False]})
print a
#    A      B
# 0  0   True
# 1  1   True
# 2  0  False
# 3  1  False
# 4  0  False

a.to_pickle('my_file.pkl')

b = pd.read_pickle('my_file.pkl')
print b
#    A      B
# 0  0   True
# 1  1   True
# 2  0  False
# 3  1  False
# 4  0  False

4

जैसा कि पहले ही उल्लेख किया गया है कि डेटा फ्रेम को स्टोर करने के लिए विभिन्न विकल्प और फ़ाइल प्रारूप ( HDF5 , JSON , CSV , लकड़ी की छत , SQL ) हैं। हालाँकि, pickleप्रथम श्रेणी का नागरिक नहीं है (आपके सेटअप के आधार पर), क्योंकि:

  1. pickleएक संभावित सुरक्षा जोखिम है। फार्म अचार के लिए अजगर प्रलेखन :

चेतावनीpickle मॉड्यूल गलत या दुर्भावनापूर्ण रूप से निर्माण किया डेटा के खिलाफ सुरक्षित नहीं है। एक अविश्वसनीय या बिना स्रोत के प्राप्त डेटा को कभी भी अनपिक नहीं करें।

  1. pickleधीमा है। यहां और यहां बेंचमार्क खोजें ।

आपके सेटअप / उपयोग के आधार पर दोनों सीमाएं लागू नहीं होती हैं, लेकिन मैं pickleपांडा डेटा फ़्रेम के लिए डिफ़ॉल्ट दृढ़ता के रूप में अनुशंसा नहीं करूंगा ।


1

संख्यात्मक डेटा के लिए Numpy फ़ाइल स्वरूप बहुत तेज़ हैं

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

import numpy as np
import pandas as pd

num_dict = {'voltage': np.random.rand(1000000)}
num_df = pd.DataFrame(num_dict)

ipython के %%timeitमैजिक फंक्शन का उपयोग करना

%%timeit
with open('num.npy', 'wb') as np_file:
    np.save(np_file, num_df)

आउटपुट है

100 loops, best of 3: 5.97 ms per loop

डेटा को वापस डेटाफ्रेम में लोड करने के लिए

%%timeit
with open('num.npy', 'rb') as np_file:
    data = np.load(np_file)

data_df = pd.DataFrame(data)

आउटपुट है

100 loops, best of 3: 5.12 ms per loop

बुरा नहीं!

कान्स

यदि आप अजगर 2 का उपयोग करके सुन्न फ़ाइल को सहेजते हैं तो एक समस्या है और फिर अजगर 3 (या इसके विपरीत) का उपयोग करके खोलने का प्रयास करें।


6
ध्यान दें कि यह समाधान आपके सभी कॉलम नामों को हटा देगा और आपके सभी पूर्णांक डेटा को फ्लोट में बदल देगा :(
जोसेफ गार्विन

0

https://docs.python.org/3/library/pickle.html

अचार प्रोटोकॉल प्रारूप:

प्रोटोकॉल संस्करण 0 मूल "मानव-पठनीय" प्रोटोकॉल है और पायथन के पुराने संस्करणों के साथ पीछे की ओर संगत है।

प्रोटोकॉल संस्करण 1 एक पुराना द्विआधारी प्रारूप है जो पायथन के पुराने संस्करणों के साथ भी संगत है।

प्रोटोकॉल संस्करण 2 को पायथन 2.3 में पेश किया गया था। यह नई शैली की कक्षाओं के बहुत अधिक कुशल अचार प्रदान करता है। प्रोटोकॉल 2 द्वारा लाए गए सुधारों की जानकारी के लिए पीईपी 307 देखें।

प्रोटोकॉल संस्करण 3 पायथन 3.0 में जोड़ा गया था। इसमें बाइट्स ऑब्जेक्ट्स के लिए स्पष्ट समर्थन है और अजगर 2.x द्वारा अप्रकाशित नहीं किया जा सकता है। यह डिफ़ॉल्ट प्रोटोकॉल है, और अनुशंसित प्रोटोकॉल जब अन्य पायथन 3 संस्करणों के साथ संगतता आवश्यक है।

प्रोटोकॉल संस्करण 4 पायथन 3.4 में जोड़ा गया था। यह बहुत बड़ी वस्तुओं के लिए समर्थन जोड़ता है, और अधिक प्रकार की वस्तुओं और कुछ डेटा प्रारूप अनुकूलन का चयन करता है। प्रोटोकॉल 4 द्वारा लाए गए सुधारों की जानकारी के लिए पीईपी 3154 का संदर्भ लें।


0

संस्करणों में व्यापक संगतता

कुल मिलाकर कदम पाइरो / पंख (पैंड्स / मेसकप से पदावनति चेतावनी) का रहा है। हालाँकि , विनिर्देशन में क्षणिकता के साथ मेरे पास एक चुनौती है। Pyarrow 0.15.1 के साथ क्रमबद्ध डेटा में 0.16.0 ARROW-7961 के साथ deserialized नहीं किया जा सकता है । मैं रेडिस का उपयोग करने के लिए क्रमांकन का उपयोग कर रहा हूं ताकि एक बाइनरी एन्कोडिंग का उपयोग करना पड़े।

मैं विभिन्न विकल्पों (सेवानिवृत्त नोटबुक का उपयोग करके) को रिटायर कर चुका हूं

import sys, pickle, zlib, warnings, io
class foocls:
    def pyarrow(out): return pa.serialize(out).to_buffer().to_pybytes()
    def msgpack(out): return out.to_msgpack()
    def pickle(out): return pickle.dumps(out)
    def feather(out): return out.to_feather(io.BytesIO())
    def parquet(out): return out.to_parquet(io.BytesIO())

warnings.filterwarnings("ignore")
for c in foocls.__dict__.values():
    sbreak = True
    try:
        c(out)
        print(c.__name__, "before serialization", sys.getsizeof(out))
        print(c.__name__, sys.getsizeof(c(out)))
        %timeit -n 50 c(out)
        print(c.__name__, "zlib", sys.getsizeof(zlib.compress(c(out))))
        %timeit -n 50 zlib.compress(c(out))
    except TypeError as e:
        if "not callable" in str(e): sbreak = False
        else: raise
    except (ValueError) as e: print(c.__name__, "ERROR", e)
    finally: 
        if sbreak: print("=+=" * 30)        
warnings.filterwarnings("default")

मेरे डेटा फ़्रेम के लिए निम्न परिणामों के साथ ( outज्यूपिटर वैरिएबल में)

pyarrow before serialization 533366
pyarrow 120805
1.03 ms ± 43.9 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
pyarrow zlib 20517
2.78 ms ± 81.8 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
msgpack before serialization 533366
msgpack 109039
1.74 ms ± 72.8 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
msgpack zlib 16639
3.05 ms ± 71.7 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
pickle before serialization 533366
pickle 142121
733 µs ± 38.3 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
pickle zlib 29477
3.81 ms ± 60.4 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
feather ERROR feather does not support serializing a non-default index for the index; you can .reset_index() to make the index into column(s)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
parquet ERROR Nested column branch had multiple children: struct<x: double, y: double>
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=

पंख और लकड़ी की छत मेरे डेटा फ्रेम के लिए काम नहीं करते हैं। मैं pyarrow का उपयोग जारी रखने जा रहा हूं। हालांकि मैं अचार (कोई संपीड़न नहीं) के साथ पूरक होगा। जब कैश स्टोर पायरो और अचार क्रमबद्ध रूपों को लिखना है। जब कैश फ़ॉलबैक से अचार तक पढ़ना अगर पायरो डिसेरिएलिसेशन विफल हो जाता है।


इस सवाल का जवाब नहीं है
जेसन एस

0

प्रारूप आपके उपयोग-मामले पर निर्भर करता है

  • नोटबुक सत्र के बीच डेटाफ़्रेम सहेजें - पंख , यदि आप अचार के लिए उपयोग किए जाते हैं - तो भी ठीक है।
  • डेटा को कम से कम संभव फ़ाइल आकार में सहेजें - लकड़ी की छत या अचार। Gz (अपने डेटा के लिए बेहतर क्या है की जाँच करें)
  • एक बहुत बड़ा DataFrame (10+ लाखों पंक्तियों) को सहेजें - hdf
  • किसी अन्य प्लेटफ़ॉर्म पर डेटा को पढ़ने में सक्षम हों (पायथन नहीं) जो अन्य प्रारूपों का समर्थन नहीं करता है - csv , csv.gz , जांचें कि क्या लकड़ी की छत का समर्थन किया गया है
  • अपनी आंखों के साथ समीक्षा करने में सक्षम हो / एक्सेल / गूगल शीट्स / गिट भिन्न का उपयोग कर - सीएसवी
  • एक डेटाफ़्रेम सहेजें जो लगभग सभी रैम - सीएसवी लेता है

पांडा के फ़ाइल स्वरूपों की तुलना इस वीडियो में है

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