Einen leeren Pandas DataFrame erstellen und ihn dann füllen

Lesezeit: 12 Minuten

Benutzeravatar von Matthias Kauer
Mathias Kauer

Ich gehe hier von der Pandas DataFrame-Dokumentation aus: Einführung in Datenstrukturen

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

Ich würde dann Anfangswerte hinzufügen und diese Daten durchgehen, um beispielsweise die neue Zeile aus der vorherigen Zeile zu berechnen row[A]

Ich verwende derzeit den folgenden Code, aber ich finde ihn irgendwie hässlich und es muss eine Möglichkeit geben, dies direkt mit einem DataFrame zu tun, oder einfach allgemein besser.

Hinweis: Ich verwende Python 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

  • Erweitern Sie niemals einen DataFrame! Es ist immer billiger, an eine Python-Liste anzuhängen und sie dann am Ende in einen DataFrame zu konvertieren, sowohl in Bezug auf Speicher als auch auf Leistung.

    – cs95

    29. Februar 2020 um 12:04 Uhr

  • @ cs95 Was ist funktional unterschiedlich zwischen .append in pd und Anhängen einer Liste? Ich weiss .appendin Pandas kopiert den gesamten Datensatz in ein neues Objekt ´, funktioniert Pythons Append anders?

    – Lama

    3. April 2020 um 9:16 Uhr

  • @Lamma Einzelheiten finden Sie in meiner Antwort unten. Beim Anhängen an df wird jedes Mal ein neuer DataFrame im Speicher erstellt, anstatt den vorhandenen zu verwenden, was ehrlich gesagt eine Verschwendung ist.

    – cs95

    5. Juni 2020 um 2:38 Uhr


  • append ist jetzt offiziell veraltet pandas.pydata.org/docs/reference/api/…

    – rubengavidia0x

    8. März um 20:10 Uhr

Benutzeravatar von cs95
cs95

Erweitern Sie NIEMALS einen DataFrame zeilenweise!

TLDR; (Lesen Sie einfach den fett gedruckten Text)

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

Hier ist mein Rat: Sammeln Sie Daten in einer Liste, nicht in einem DataFrame.

Verwenden Sie eine Liste, um Ihre Daten zu sammeln, und initialisieren Sie dann einen DataFrame, wenn Sie bereit sind. Es funktioniert entweder ein List-of-Lists- oder ein List-of-Dicts-Format, pd.DataFrame akzeptiert beides.

data = []
for row in some_function_that_yields_data():
    data.append(row)

df = pd.DataFrame(data)

pd.DataFrame konvertiert die Liste der Zeilen (wobei jede Zeile ein Skalarwert ist) in einen DataFrame. Wenn Ihre Funktion stattdessen DataFrames liefert, rufen Sie auf pd.concat.

Vorteile dieses Ansatzes:

  1. Es ist immer billiger, an eine Liste anzuhängen und einen DataFrame in einem Rutsch zu erstellen als einen leeren DataFrame (oder einen von NaNs) zu erstellen und ihn immer wieder anzuhängen.

  2. Listen nehmen auch weniger Speicherplatz in Anspruch und sind eine viel leichtere Datenstruktur, mit der man arbeiten kannanhängen und entfernen (falls erforderlich).

  3. dtypes werden automatisch abgeleitet (anstatt zuzuweisen object an alle).

  4. EIN RangeIndex wird automatisch für Ihre Daten erstelltanstatt darauf achten zu müssen, der Zeile, die Sie bei jeder Iteration anhängen, den richtigen Index zuzuweisen.

Wenn Sie noch nicht überzeugt sind, wird dies auch in der erwähnt Dokumentation:

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.

*** Update für Pandas >= 1.4: append ist jetzt ABGESAGT! ***

Ab Pandas 1.4, append wurde jetzt verworfen! Verwenden pd.concat stattdessen. Siehe die Versionshinweise



Diese Optionen sind schrecklich

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 alle neu zugewiesen append oder concat Betrieb Sie haben. Verbinden Sie dies mit einer Schleife und Sie haben eine Quadratische Komplexitätsoperation.

Der andere Fehler im Zusammenhang mit df.append ist, dass Benutzer dazu neigen, zu vergessen append ist keine In-Place-Funktion, also muss das Ergebnis zurück zugewiesen werden. Sie müssen sich auch um die dtypes 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 nie eine gute Sache, da Pandas Operationen auf diesen Spalten nicht vektorisieren können. 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

habe ich auch gesehen loc Wird verwendet, um an einen DataFrame anzuhängen, 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 die Menge an Speicher, die Sie jedes Mal benötigen, nicht vorab zugewiesen Der Speicher wird jedes Mal neu gewachsen, wenn Sie eine neue Zeile erstellen. Es ist genauso schlimm wie appendund noch hässlicher.

Leerer DataFrame von NaNs

Und dann entsteht ein DataFrame von NaNs und alle damit verbundenen Vorbehalte.

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 wie die anderen einen DataFrame von Objektspalten.

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

Das Anhängen hat immer noch alle Probleme wie die oben genannten Methoden.

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


Der Beweis liegt im Pudding

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

Geben Sie hier die Bildbeschreibung ein

Benchmarking-Code als Referenz.

  • Das steht buchstäblich in der Dokumentation. „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.“ pandas.pydata.org/pandas-docs/version/0.21/generated/…

    – Endolith

    11. August 2019 um 0:06 Uhr

  • Auch "Hinweis Es ist erwähnenswert, dass concat() (und daher append()) eine vollständige Kopie der Daten erstellt und dass die ständige Wiederverwendung dieser Funktion zu erheblichen Leistungseinbußen führen kann. Wenn Sie die Operation für mehrere Datensätze verwenden müssen, Verwenden Sie ein Listenverständnis." pandas.pydata.org/pandas-docs/stable/user_guide/…

    – Endolith

    11. August 2019 um 0:07 Uhr

  • Was mache ich also, wenn meine Daten als 1d-Listen nacheinander "eingehen", wobei jede eine Spalte in einem Datenrahmen darstellt? Wie füge ich sie zusammen, bevor ich sie in einen Datenrahmen umwandele? Es scheint, dass list1.apped(list2) fügt eine Liste in eine andere Liste ein, anstatt eine Spalte hinzuzufügen. Vielen Dank

    – Verwirrt

    11. März 2020 um 19:59 Uhr

  • @Confounded Das ist ein anderes Problem als das hier gefragte, aber es sollte in Ordnung sein, einem leeren Datenrahmen jeweils eine Spalte zuzuweisen. Das Problem tritt beim sukzessiven Anhängen von Zeilen auf.

    – cs95

    16. Januar 2021 um 7:34 Uhr

  • @micstr a, b und c sind individuelle, atomare Skalarwerte und keine Listen. Wenn Sie die Datenlisten bereits vorliegen haben, rufen Sie einfach an pd.DataFrame([a_list, b_list, c_list])

    – cs95

    19. November 2021 um 9:45 Uhr

Benutzeravatar von Andy Hayden
Andy Hayden

Hier sind ein paar Vorschläge:

Verwenden 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önnten einen leeren DataFrame (mit NaNs) einfach durch Schreiben:

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

Um diese Art von Berechnungen für die Daten durchzuführen, verwenden Sie a NumPy Array:

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

  • pd.date_range() funktioniert bei mir nicht. Ich habe es mit DateRange (aus der Autovervollständigung von Eclipse) versucht, aber das funktioniert mit Zeichenfolgen als Datumsformat, oder? Der Gesamtansatz funktioniert jedoch (ich habe den Index in etwas anderes geändert).

    – Matthias Kauer

    15. Dezember 2012 um 8:42 Uhr


  • date_range ist eine Factory-Funktion zum Erstellen von datetime-Indizes und was eine neue Funktion in 0.8.0, ich würde auf jeden Fall ein Upgrade auf die neueste stabile Version (0.9.1) empfehlen, es gibt viele Fehlerbehebungen und neue Funktionen. 🙂

    – Andy Hayden

    15. Dezember 2012 um 9:52 Uhr


  • Mir ist aufgefallen, dass das Beispiel in der Importanweisung einen Tippfehler enthält. Es sagt aus: import datatime Es sollte sagen: import datetime Das kann der Grund für deine Schwierigkeiten sein.

    Benutzer2899462

    20. Oktober 2013 um 6:17 Uhr


  • Meiner Erfahrung nach ist das Erstellen eines Datenrahmens der erforderlichen Größe, der mit NaNs gefüllt ist, und das anschließende Auffüllen mit Werten viel, viel langsamer als das Erstellen eines Datenrahmens mit index x 0 Maße (columns = []) und Anbringen einer Spalte in jeder Windung einer Schleife. Ich meine df[col_name] = pandas.Series([...]) in einer Schleife, die Spaltennamen durchläuft. Im ersten Fall braucht nicht nur die Speicherzuweisung Zeit, sondern das Ersetzen von NaNs durch neue Werte scheint extrem langsam zu sein.

    – vertieft

    3. März 2015 um 16:33 Uhr


  • @deeenes auf jeden Fall. Diese Antwort sollte das wahrscheinlich klarer machen - Sie möchten sehr selten (wenn überhaupt) einen leeren Datenrahmen (von NaNs) erstellen.

    – Andy Hayden

    3. März 2015 um 17:33 Uhr

Benutzeravatar von geekidharsh
geekidhart

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

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 

In diesem Beispiel verwende ich dieses pandas doc um einen neuen Datenrahmen zu erstellen und dann zu verwenden anhängen um mit Daten aus oldDF in die newDF zu schreiben.

Wenn ich ständig neue Daten von mehr als einem alten DF an dieses newDF anhängen muss, verwende ich einfach eine for-Schleife, um darüber zu iterieren
pandas.DataFrame.append()

Hinweis: append() ist seit Version 1.4.0 veraltet. Verwende concat()

  • Bitte beachte, dass append (und ähnlich concat) kopiert jedes Mal den vollständigen Datensatz in ein neues Objekt, daher kann und wird das Iterieren und Anhängen einen erheblichen Leistungseinbruch verursachen. Weitere Informationen finden Sie unter: pandas.pydata.org/pandas-docs/stable/merging.html

    – MoustafaAAtta

    18. September 2017 um 12:21 Uhr

  • @MoustafaAAtta Was sind die Alternativen, um iterativ Daten an den Datenrahmen anzuhängen?

    – MysteryGuy

    13. August 2018 um 11:24 Uhr

  • @MoustafaAAtta Antwortet Fred in diesem Beitrag: stackoverflow.com/questions/10715965/… in dieser Hinsicht besser?

    – MysteryGuy

    13. August 2018 um 11:29 Uhr

  • @MoustafaAAtta Sie können vielleicht nur Zeilen an einen Datenrahmen anhängen, es wird immer noch ein neues Objekt erstellt, aber für kleinere Datensätze könnte es nützlich sein. pandas.pydata.org/pandas-docs/stable/user_guide/…

    – geekidharsh

    28. Januar 2020 um 21:28 Uhr

  • Beachten Sie, dass die Append-Methode offiziell veraltet ist. Überprüfen Sie die Dokumentation: pandas.pydata.org/docs/reference/api/…

    – rubengavidia0x

    8. März um 20:08 Uhr

Benutzeravatar von Afshin Amiri
Afshin Amiri

Leeren Rahmen mit Spaltennamen initialisieren

import pandas as pd

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

Hinzufügen eines neuen Datensatzes zu einem Rahmen

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

Vielleicht möchten Sie auch ein Wörterbuch weitergeben:

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

Fügen Sie Ihrem bestehenden Rahmen einen weiteren Rahmen hinzu

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

Leistungsüberlegungen

Wenn Sie Zeilen innerhalb einer Schleife hinzufügen, sollten Sie Leistungsprobleme berücksichtigen. Für etwa die ersten 1000 Datensätze ist die Leistung von „my_df.loc“ besser, wird aber allmählich langsamer, wenn die Anzahl der Datensätze in der Schleife erhöht wird.

Wenn Sie vorhaben, innerhalb einer großen Schleife (z. B. 10 Mio. Schallplatten oder so) dünner zu werden, ist es besser, eine Mischung aus diesen beiden zu verwenden. 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 10-fache steigern.

Einfach:

import numpy as np
import pandas as pd

df=pd.DataFrame(np.zeros([rows,columns])

Dann füllen Sie es.

Benutzeravatar von Sociopath
Soziopath

Nehmen Sie einen Datenrahmen mit 19 Zeilen an

index=range(0,19)
index

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

Spalte A konstant halten

test['A']=10

Spalte b als Variable beibehalten, die durch eine Schleife gegeben wird

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

Sie können das erste x in ersetzen pd.Series([x], index = [x]) mit beliebigem Wert

Benutzeravatar von Wojciech Moszczyński
Wojciech Moszczyński

Dies ist meine Art, einen dynamischen Datenrahmen aus mehreren Listen mit einer Schleife zu erstellen

x = [1,2,3,4,5,6,7,8]
y = [22,12,34,22,65,24,12,11]
z = ['as','ss','wa', 'ss','er','fd','ga','mf']
names = ['Bob', 'Liz', 'chop']

eine Schleife

def dataF(x,y,z,names):
    res = []

    for t in zip(x,y,z):
        res.append

    return pd.DataFrame(res,columns=names)

Ergebnis

dataF(x,y,z,names)

Geben Sie hier die Bildbeschreibung ein

1400080cookie-checkEinen leeren Pandas DataFrame erstellen und ihn dann füllen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy