it-swarm.com.de

Erstellen Sie einen leeren Pandas DataFrame und füllen Sie ihn dann aus?

Ich beginne mit den pandas DataFrame-Dokumenten hier: http://pandas.pydata.org/pandas-docs/stable/dsintro.html

Ich möchte den DataFrame in einer Zeitreihenberechnung iterativ mit Werten füllen. Grundsätzlich möchte ich den DataFrame mit den Spalten A, B und den Zeitstempelzeilen initialisieren, alle 0 oder alle NaN.

Ich würde dann Anfangswerte hinzufügen und diese Daten durchgehen und die neue Zeile aus der vorherigen Zeile berechnen, z. B. row[A][t] = row[A][t-1]+1 oder so.

Ich verwende den Code derzeit wie folgt, aber ich finde ihn irgendwie hässlich und es muss eine Möglichkeit geben, dies direkt mit einem DataFrame zu tun, oder nur eine bessere Möglichkeit im Allgemeinen. Hinweis: Ich verwende Python 2.7.

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

if __== '__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
343
Matthias Kauer

Hier sind ein paar Vorschläge:

Verwenden Sie date_range für den Index:

_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']
_

Hinweis: Wir können einen leeren DataFrame (mit NaNs) erstellen, indem wir einfach schreiben:

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

Verwenden Sie ein Numpy-Array, um diese Art von Berechnungen für die Daten durchzuführen:

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

Daher können wir den DataFrame erstellen:

_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
_
266
Andy Hayden

Wenn Sie lediglich einen leeren Datenrahmen erstellen und ihn später mit einigen eingehenden Datenrahmen füllen möchten, versuchen Sie Folgendes:

In diesem Beispiel benutze ich this pandas doc , um einen neuen Datenrahmen zu erstellen, und benutze dann append , um mit Daten aus oldDF in die newDF zu schreiben.


Schau dir das an

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 
  • wenn ich weiterhin neue Daten aus mehr als einer alten PDF-Datei an diese neue PDF-Datei anhängen muss, benutze ich einfach eine for-Schleife, um pandas.DataFrame.append () zu durchlaufen
128
geekidharsh

Wenn Sie Ihre Spaltennamen von Anfang an verwenden möchten, gehen Sie folgendermaßen vor:

import pandas as pd

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

Wenn Sie dem Datenrahmen einen Datensatz hinzufügen möchten, sollten Sie Folgendes verwenden:

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

Möglicherweise möchten Sie auch ein Wörterbuch übergeben:

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

Wenn Sie jedoch einen weiteren Datenrahmen zu my_df hinzufügen möchten, gehen Sie wie folgt vor:

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

Wenn Sie Zeilen innerhalb einer Schleife hinzufügen, berücksichtigen Sie Leistungsprobleme:
Bei ungefähr den ersten 1000 Datensätzen ist die Leistung von "my_df.loc" besser, wird jedoch allmählich langsamer, wenn die Anzahl der Datensätze in der Schleife erhöht wird.

Wenn Sie vorhaben, in einer großen Schleife eine Ausdünnung vorzunehmen (etwa 10 Millionen Datensätze):
Du bist besser dran, wenn du eine Mischung aus beiden verwendest; Füllen Sie einen Datenrahmen mit iloc, bis die Größe etwa 1000 beträgt, hängen Sie ihn dann an den ursprünglichen Datenrahmen an und leeren Sie den temporären Datenrahmen. Dies würde Ihre Leistung um das Zehnfache steigern.

97
Afshin Amiri

Der richtige Weg, um einen Datenrahmen zu erstellen

In den meisten Antworten erfahren Sie, wie Sie einen leeren DataFrame erstellen und ausfüllen, aber niemand wird Ihnen sagen, dass dies eine schlechte Sache ist.

Hier ist mein Rat: Warten Sie, bis Sie sicher sind, dass Sie alle Daten haben, mit denen Sie arbeiten müssen. Verwenden Sie eine Liste, um Ihre Daten zu sammeln, und initialisieren Sie dann a DataFrame, wenn Sie bereit sind.

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

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

Es ist immer billiger, an eine Liste anzuhängen und einen DataFrame auf einmal zu erstellen als einen leeren DataFrame (oder einen der NaNs) und immer wieder anhängen. Listen belegen auch weniger Speicher und sind eine viel einfachere Datenstruktur, mit der Sie arbeiten, anfügen und entfernen können (falls erforderlich).

Der andere Vorteil dieser Methode ist, dass dtypes automatisch abgeleitet wird (anstatt allen object zuzuweisen).

Der letzte Vorteil ist, dass automatisch ein RangeIndex für Ihre Daten erstellt wird Bei den unten aufgeführten schlechten Methoden append und loc werden in beiden Elementen Elemente angezeigt, die eine angemessene Behandlung des Index erfordern.


Dinge, die Sie NICHT tun sollten

append oder concat innerhalb einer Schleife

Hier ist der größte Fehler, den ich von Anfängern gesehen habe:

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)

Der Speicher wird für jede append oder concat Operation, die Sie ausführen, neu zugewiesen. Verbinden Sie dies mit einer Schleife und Sie haben eine quadratische Komplexitätsoperation . Von der Seite df.append doc :

Das iterative Anhängen von Zeilen an einen DataFrame kann rechenintensiver sein als eine einzelne Verkettung. Eine bessere Lösung besteht darin, diese Zeilen an eine Liste anzuhängen und die Liste dann auf einmal mit dem ursprünglichen DataFrame zu verketten.

Der andere Fehler, der mit df.append verbunden ist, besteht darin, dass Benutzer dazu neigen, das Anhängen zu vergessen . Es handelt sich nicht um eine In-Place-Funktion , daher muss das Ergebnis zurück zugewiesen werden . Sie müssen sich auch um die D-Typen kümmern:

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

Der Umgang mit Objektspalten ist niemals eine gute Sache, da pandas Operationen für diese Spalten nicht vektorisieren kann. Sie müssen dies tun, um es zu beheben:

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

loc innerhalb einer Schleife

Ich habe auch gesehen, dass loc zum Anhängen an einen DataFrame verwendet wurde, der leer erstellt wurde:

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

Wie zuvor haben Sie nicht die Menge an Speicher vorab zugewiesen, die Sie jedes Mal benötigen. Der Speicher wird jedes Mal neu vergrößert, wenn Sie eine neue Zeile erstellen. . Es ist genauso schlimm wie append und noch hässlicher.

Leerer DataFrame von NaNs

Und dann erstellen Sie einen DataFrame mit NaNs und allen damit verbundenen Einschränkungen.

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

Es erstellt einen DataFrame aus Objektspalten, wie die anderen.

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

Beim Anhängen sind immer noch alle Probleme wie oben beschrieben aufgetreten.

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

Der Beweis ist im Pudding

Das Timing dieser Methoden ist der schnellste Weg, um festzustellen, wie sehr sie sich in Bezug auf Speicher und Nutzen unterscheiden.

enter image description here

Referenzcode

24
cs95