खाली पंडों का डाटाफ्रेम बनाना, फिर भरना?


461

मैं यहाँ पंडों से शुरू कर रहा हूँ DataFrame डॉक्स: http://pandas.pydata.org/pandas-docs/stable/dsintro.html

मैं समय-समय की गणना में डेटाफ़्रेम को मानों के साथ भरना चाहता हूं। तो मूल रूप से, मैं स्तंभ A, B और टाइमस्टैम्प पंक्तियों के साथ DataFrame को प्रारंभ करना चाहूंगा, सभी 0 या सभी NaN।

फिर मैं प्रारंभिक मूल्य जोड़ूंगा और इस डेटा पर पंक्ति से नई पंक्ति की गणना करने से पहले, row[A][t] = row[A][t-1]+1या तो कहूँगा ।

मैं वर्तमान में नीचे के रूप में कोड का उपयोग कर रहा हूं, लेकिन मुझे लगता है कि यह एक तरह से बदसूरत है और सीधे डेटाफ़्रेम के साथ ऐसा करने का एक तरीका होना चाहिए, या बस सामान्य रूप से बेहतर तरीका होना चाहिए। नोट: मैं पायथन 2.7 का उपयोग कर रहा हूं।

import datetime as dt
import pandas as pd
import scipy as s

if __name__ == '__main__':
    base = dt.datetime.today().date()
    dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
    dates.sort()

    valdict = {}
    symbols = ['A','B', 'C']
    for symb in symbols:
        valdict[symb] = pd.Series( s.zeros( len(dates)), dates )

    for thedate in dates:
        if thedate > dates[0]:
            for symb in valdict:
                valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]

    print valdict

5
कभी भी एक DataFrame न बढ़ें! यह हमेशा एक अजगर सूची में शामिल होने के लिए सस्ता होता है और फिर इसे मेमोरी और प्रदर्शन दोनों के संदर्भ में एक DataFrame में बदल देता है।
CS95 12:59

@ सीएस 95 .appendएक सूची में पीडी और एप्लाइड के बीच कार्यात्मक रूप से भिन्न क्या है ? मुझे पता है .appendकि पांडा एक नई वस्तु के लिए पूरे डेटासेट को कॉपी करता है as, क्या अजगर अलग तरीके से काम करता है?
लामा

@ लामा कृपया नीचे मेरे उत्तर में विवरण पाएं। डीएफ में आवेदन करते समय, मौजूदा के उपयोग के बजाय मेमोरी में हर बार एक नया डेटाफ्रेम बनाया जाता है, जो कि स्पष्ट रूप से एक बेकार है।
cs95

जवाबों:


330

यहाँ कुछ सुझाव दिए गए हैं:

date_rangeसूचकांक के लिए उपयोग करें :

import datetime
import pandas as pd
import numpy as np

todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')

columns = ['A','B', 'C']

नोट: हम एक खाली डाटाफ्रेम बना सकते हैं ( NaNएस के साथ ) बस लिख कर:

df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs

डेटा के लिए इस प्रकार की गणना करने के लिए, एक सुस्पष्ट सरणी का उपयोग करें:

data = np.array([np.arange(10)]*3).T

इसलिए हम DataFrame बना सकते हैं:

In [10]: df = pd.DataFrame(data, index=index, columns=columns)

In [11]: df
Out[11]: 
            A  B  C
2012-11-29  0  0  0
2012-11-30  1  1  1
2012-12-01  2  2  2
2012-12-02  3  3  3
2012-12-03  4  4  4
2012-12-04  5  5  5
2012-12-05  6  6  6
2012-12-06  7  7  7
2012-12-07  8  8  8
2012-12-08  9  9  9

2
pd.date_range () मेरे लिए काम नहीं करता है। मैंने DateRange (ग्रहण के स्वत: पूर्णता से) के साथ प्रयास किया, लेकिन यह तारीख प्रारूप के रूप में तार के साथ काम करता है, है ना? समग्र दृष्टिकोण हालांकि काम करता है (मैंने इंडेक्स को कुछ और बदल दिया)।
मथायस कौएर

2
डेट_ अरेंज डेटटाइम इंडेक्स बनाने के लिए एक फैक्ट्री फ़ंक्शन है और 0.8.0 में एक नई सुविधा थी , मैं निश्चित रूप से नवीनतम स्थिर रिलीज (0.9.1) में अपग्रेड करने की सिफारिश करूंगा जिसमें कई बग फिक्स और नई विशेषताएं हैं। :)
एंडी हेडन

26
मेरे अनुभवों में, NaNs से भरे आवश्यक आकार का एक डेटा फ्रेम बनाना, और फिर मानों को भरना indexx 0आयामों ( columns = []) के साथ डेटा फ़्रेम बनाने और लूप के प्रत्येक मोड़ में एक कॉलम संलग्न करने की तुलना में बहुत धीमा है । मेरा मतलब df[col_name] = pandas.Series([...])है कि कॉलम नामों के माध्यम से चलने वाले लूप में। पूर्व मामले में, न केवल मेमोरी आवंटन में समय लगता है, बल्कि नए मानों के साथ NaN की जगह बेहद धीमी लगती है।
deeenes

5
@ दीनीयाँ जरूर। इस उत्तर को संभवतः स्पष्ट कर देना चाहिए - आप बहुत कम ही (यदि कभी) खाली डेटफ़्रेम (NaNs का) बनाना चाहते हैं।
एंडी हेडन

1
इस उत्तर के अनुसार stackoverflow.com/a/30267881/2302569 आपको भरण-पोषण का परिणाम निर्दिष्ट करना है, या परीक्षा में पास होना = सत्य
जयजय

169

यदि आप केवल एक खाली डेटा फ़्रेम बनाना चाहते हैं और बाद में आने वाले कुछ डेटा फ़्रेमों से इसे भरना चाहते हैं, तो यह प्रयास करें:

newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional 

इस उदाहरण में मैं उपयोग कर रहा हूँ इस पांडा डॉक एक नया डेटा फ्रेम बनाने के लिए और उसके बाद का उपयोग कर संलग्न oldDF से डेटा के साथ newDF को लिखने के लिए।

अगर मुझे एक से अधिक पुराने डीएफएफ से इस नए डीएफ में नए डेटा को जोड़ते रहना है, तो मैं सिर्फ पंडों के लिए इसे टाइप करने के लिए लूप का उपयोग करता हूं। DataFrame.append ()


14
कृपया ध्यान दें कि append(इसी तरह concat) पूरे डेटासेट को हर बार एक नई वस्तु में कॉपी करता है, इसलिए, यह एक बड़ी प्रदर्शन हिट का कारण बन सकता है। अधिक जानकारी के लिए देखें: pandas.pydata.org/pandas-docs/stable/merging.html
MoustafaAAtta

4
@MoustafaAAtta डेटाफ्रेम में डेटा पुनरावृत्त करने के लिए विकल्प क्या हैं?
मिस्ट्रीग्यू

2
@MoustafaAAtta इस पोस्ट में फ्रेड का जवाब है: stackoverflow.com/questions/10715965/ ... इस दृष्टिकोण पर बेहतर है?
मिस्ट्रीग्यू

@MoustafaAAtta आप शायद एक डेटाफ्रेम में सिर्फ पंक्तियों को जोड़ सकते हैं, यह अभी भी एक नई वस्तु बनाएगा लेकिन छोटे डेटासेट के लिए, उपयोगी हो सकता है। pandas.pydata.org/pandas-docs/stable/user_guide/…
geekidharsh

135

एक DataFrame बनाने का सही तरीका ™ है

TLDR; (सिर्फ बोल्ड टेक्स्ट पढ़ें)

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

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

data = []
for a, b, c in some_function_that_yields_data():
    data.append([a, b, c])

df = pd.DataFrame(data, columns=['A', 'B', 'C'])

यह हमेशा एक सूची में संलग्न करने के लिए और एक बार में एक से एक DataFrame बनाने की तुलना में सस्ता है , यह एक खाली DataFrame (या NaNs में से एक) बनाने के लिए और बार-बार इसे करने के लिए अपील है। सूचियाँ भी कम मेमोरी लेती हैं और साथ काम करने , जोड़ने और हटाने (यदि आवश्यक हो) के लिए एक बहुत हल्का डेटा संरचना हैं

इस पद्धति का अन्य लाभ dtypesस्वचालित रूप से अनुमानित हैं ( objectउन सभी को निर्दिष्ट करने के बजाय )।

पिछले लाभ यह है कि है एक RangeIndexस्वचालित रूप से आपके डेटा के लिए बनाया जाता है, तो यह के बारे में चिंता करने के लिए एक कम बात (गरीब पर एक नज़र है, appendऔर locनीचे दिए गए तरीकों, आप दोनों कि उचित रूप से सूचकांक से निपटने की आवश्यकता होती है में तत्वों देखेंगे)।


चीजें जो आपको नहीं करनी चाहिए

appendया concatएक लूप के अंदर

यहाँ सबसे बड़ी गलती है जो मैंने शुरुआती लोगों से देखी है:

df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # yuck
    # or similarly,
    # df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)

आपके द्वारा किए गए प्रत्येक appendया concatऑपरेशन के लिए मेमोरी फिर से आवंटित की जाती है। इसे एक लूप के साथ युगल करें और आपके पास एक द्विघात जटिलता ऑपरेशन है । से df.appendडॉक पेज :

किसी डेटाफ़्रेम में समान रूप से जोड़ देने वाली पंक्तियाँ एकल संगति से अधिक कम्प्यूटेशनल रूप से गहन हो सकती हैं। एक बेहतर उपाय यह है कि उन पंक्तियों को एक सूची में जोड़ दिया जाए और फिर सूची को मूल DataFrame के साथ एक ही बार में पूरा किया जाए।

इससे जुड़ी दूसरी गलती df.appendयह है कि उपयोगकर्ता भूल जाते हैं कि एपेंड एक इन-प्लेस फ़ंक्शन नहीं है , इसलिए परिणाम को वापस सौंपा जाना चाहिए। तुम भी dtypes के बारे में चिंता करने की ज़रूरत है:

df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)

df.dtypes
A     object   # yuck!
B    float64
C     object
dtype: object

ऑब्जेक्ट कॉलम से निपटना कभी भी अच्छी बात नहीं है, क्योंकि पांडा उन कॉलमों पर परिचालन को वेक्टर नहीं कर सकते हैं। इसे ठीक करने के लिए आपको यह करने की आवश्यकता होगी:

df.infer_objects().dtypes
A      int64
B    float64
C     object
dtype: object

loc एक लूप के अंदर

मैंने locएक DataFrame को खाली करने के लिए उपयोग करने के लिए भी देखा है जो खाली बनाया गया था:

df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df.loc[len(df)] = [a, b, c]

पहले की तरह, आपको प्रत्येक बार आवश्यक मेमोरी की मात्रा पूर्व-आबंटित नहीं की गई है, इसलिए हर बार जब आप एक नई पंक्ति बनाते हैं , तो मेमोरी फिर से बढ़ जाती है । यह उतना ही बुरा है append, और इससे भी ज्यादा बदसूरत।

NaNs का खाली डेटाफ़्रेम

और फिर, NaNs का एक DataFrame बना रहा है, और इसके साथ सभी कैविएट जुड़े हुए हैं।

df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
     A    B    C
0  NaN  NaN  NaN
1  NaN  NaN  NaN
2  NaN  NaN  NaN
3  NaN  NaN  NaN
4  NaN  NaN  NaN

यह अन्य की तरह ऑब्जेक्ट कॉलम का एक डेटाफ़्रेम बनाता है।

df.dtypes
A    object  # you DON'T want this
B    object
C    object
dtype: object

लागू करने के अभी भी ऊपर के तरीकों के रूप में सभी मुद्दे हैं।

for i, (a, b, c) in enumerate(some_function_that_yields_data()):
    df.iloc[i] = [a, b, c]

खुद के मरने से स्वर्ग मिलता है

इन तरीकों को समय पर देखने का सबसे तेज़ तरीका है कि वे अपनी स्मृति और उपयोगिता के मामले में कितना भिन्न हैं।

यहाँ छवि विवरण दर्ज करें

संदर्भ के लिए बेंचमार्किंग कोड।


6
इस प्रकार के प्रश्न के लिए सूची परिशिष्ट सबसे अच्छा तरीका होना चाहिए
YOBEN_S

9
इसके लिए एक लाख गुना अधिक राशि की आवश्यकता है। कभी भी डेटाफ्रेम नहीं बढ़ाएं!
बग्गी

3
@ user3293236 आपको किसी पुराने प्रश्न का उत्तर देने के लिए हर बार नीचे से शुरू करना होगा;)
CS95

2
यह उन चीजों में से एक है जिनसे मैं सबसे ज्यादा नफरत करता हूं। उन कई बार आप 𝒓𝒆𝒂𝒍 the just को देखते हैं कि बस कुछ वोटों के साथ कहीं नीचे रहता है और कभी स्वीकार नहीं किया जाता है। मुझे खाली पंडों के डेटाफ्रेम बनाने के लिए 𝚙𝚍 = 𝚙𝚍.𝙳𝚊𝚝𝚊𝙵𝚛𝚊𝚖𝚎 ([]) कोड याद आता है। इस उत्तर का उत्कर्ष। उत्कृष्ट स्पष्टीकरण, @ cs95!
जोनाथन

1
यह वस्तुतः प्रलेखन में है। "एक DataFrame में वैकल्पिक रूप से पंक्तियों को जोड़ना एक संगोष्ठी की तुलना में अधिक कम्प्यूटेशनल रूप से गहन हो सकता है। एक बेहतर समाधान उन पंक्तियों को एक सूची में जोड़ना और फिर एक ही बार में सभी DataFrame के साथ सूची को संक्षिप्त करना है।" pandas.pydata.org/pandas-docs/version/0.21/generated/…
endolith

132

कॉलम नामों के साथ खाली फ्रेम शुरू करें

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df

एक फ्रेम में एक नया रिकॉर्ड जोड़ें

my_df.loc[len(my_df)] = [2, 4, 5]

आप एक शब्दकोष भी पारित करना चाह सकते हैं:

my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic 

अपने मौजूदा फ्रेम में एक और फ्रेम लगाएं

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)

प्रदर्शन के विचार

यदि आप लूप के अंदर पंक्तियों को जोड़ रहे हैं, तो प्रदर्शन समस्याओं पर विचार करें। पहले 1000 रिकॉर्ड के लिए "my_df.loc" प्रदर्शन बेहतर है, लेकिन यह धीरे-धीरे लूप में रिकॉर्ड की संख्या बढ़ाकर धीमा हो जाता है।

यदि आप एक बड़े लूप के अंदर थिनर करने की योजना बनाते हैं (जैसे 10M रिकॉर्ड या तो), तो आप इन दोनों के मिश्रण का उपयोग करने से बेहतर हैं; iloc के साथ एक डेटाफ्रेम भरें जब तक कि आकार 1000 के आसपास न हो जाए, तब इसे मूल डेटाफ्रेम में जोड़ें, और अस्थायी डेटाफ्रेम खाली करें। यह आपके प्रदर्शन को लगभग 10 गुना बढ़ा देगा।


my_df = my_df.append(my_df2)जब तक मैं निर्दिष्ट नहीं करता, मेरे लिए काम नहीं करता है ignore_index=True
नसीफ इम्तियाज ओही

0

19 पंक्तियों के साथ एक डेटाफ्रेम मान लें

index=range(0,19)
index

columns=['A']
test = pd.DataFrame(index=index, columns=columns)

एक स्थिर के रूप में कॉलम ए रखते हुए

test['A']=10

कॉलम बी को लूप द्वारा दिए गए वेरिएबल के रूप में रखें

for x in range(0,19):
    test.loc[[x], 'b'] = pd.Series([x], index = [x])

आप पहले x pd.Series([x], index = [x])को किसी भी मान से बदल सकते हैं

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