Python-Pandas: Füllen Sie einen Datenrahmen Zeile für Zeile

133

Die einfache Aufgabe, einem pandas.DataFrameObjekt eine Zeile hinzuzufügen, scheint schwer zu erfüllen zu sein. Es gibt 3 Fragen zum Stapelüberlauf, von denen keine eine funktionierende Antwort gibt.

Folgendes versuche ich zu tun. Ich habe einen DataFrame, dessen Form ich bereits kenne, sowie die Namen der Zeilen und Spalten.

>>> df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'])
>>> df
     a    b    c    d
x  NaN  NaN  NaN  NaN
y  NaN  NaN  NaN  NaN
z  NaN  NaN  NaN  NaN

Jetzt habe ich eine Funktion, um die Werte der Zeilen iterativ zu berechnen. Wie kann ich eine der Zeilen mit einem Wörterbuch oder einem Wörterbuch ausfüllen pandas.Series? Hier sind verschiedene Versuche, die fehlgeschlagen sind:

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df['y'] = y
AssertionError: Length of values does not match length of index

Anscheinend wurde versucht, eine Spalte anstelle einer Zeile hinzuzufügen.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.join(y)
AttributeError: 'builtin_function_or_method' object has no attribute 'is_unique'

Sehr uninformative Fehlermeldung.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.set_value(index='y', value=y)
TypeError: set_value() takes exactly 4 arguments (3 given)

Anscheinend dient das nur zum Einstellen einzelner Werte im Datenrahmen.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.append(y)
Exception: Can only append a Series if ignore_index=True

Nun, ich möchte den Index nicht ignorieren, sonst ist hier das Ergebnis:

>>> df.append(y, ignore_index=True)
     a    b    c    d
0  NaN  NaN  NaN  NaN
1  NaN  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN
3    1    5    2    3

Die Spaltennamen wurden zwar an den Werten ausgerichtet, die Zeilenbeschriftungen gingen jedoch verloren.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.ix['y'] = y
>>> df
                                  a                                 b  \
x                               NaN                               NaN
y  {'a': 1, 'c': 2, 'b': 5, 'd': 3}  {'a': 1, 'c': 2, 'b': 5, 'd': 3}
z                               NaN                               NaN

                                  c                                 d
x                               NaN                               NaN
y  {'a': 1, 'c': 2, 'b': 5, 'd': 3}  {'a': 1, 'c': 2, 'b': 5, 'd': 3}
z                               NaN                               NaN

Das ist auch kläglich gescheitert.

Wie machst du das?

xApple
quelle

Antworten:

92

df['y'] setzt eine Spalte

Da Sie eine Zeile festlegen möchten, verwenden Sie .loc

Beachten Sie, dass .ixdies hier gleichwertig ist. Ihr Fehler ist fehlgeschlagen, weil Sie versucht haben, jedem Element der Zeile ein Wörterbuch zuzuweisen, ywahrscheinlich nicht das, was Sie möchten. Das Konvertieren in eine Serie teilt Pandas mit, dass Sie die Eingabe ausrichten möchten (zum Beispiel müssen Sie dann nicht alle Elemente angeben).

In [7]: df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'])

In [8]: df.loc['y'] = pandas.Series({'a':1, 'b':5, 'c':2, 'd':3})

In [9]: df
Out[9]: 
     a    b    c    d
x  NaN  NaN  NaN  NaN
y    1    5    2    3
z  NaN  NaN  NaN  NaN
Jeff
quelle
Aha. Das locAttribut des Datenrahmens definiert also ein Special __setitem__, das die Magie ausübt, die ich vermute.
xApple
Können Sie dies in einem Durchgang konstruieren (dh mit Spalten, Index und y)?
Andy Hayden
5
Wenn ich also jeweils eine Zeile generieren kann, wie würde ich den Datenrahmen optimal erstellen?
xApple
Hat erwartet, dass eine Variante df = pd.DataFrame({'y': pd.Series(y)}, columns=['a','b','c','d'], index=['x','y','z'])funktioniert?
Andy Hayden
@xApple wahrscheinlich am besten für Sie, um eine Liste von Diktaten (oder Liste) zu erstellen, und dann einfach an den Konstruktor übergeben, wird viel effizienter sein
Jeff
71

Mein Ansatz war, aber ich kann nicht garantieren, dass dies die schnellste Lösung ist.

df = pd.DataFrame(columns=["firstname", "lastname"])
df = df.append({
     "firstname": "John",
     "lastname":  "Johny"
      }, ignore_index=True)
fließen
quelle
4
Das hat bei mir hervorragend funktioniert und ich mag die Tatsache, dass Sie appenddie Daten explizit in den Datenrahmen übertragen.
Jonny Brooks
1
Beachten Sie, dass für diese Antwort an jede Zeile der Spaltenname angehängt werden muss. Gleiches gilt für die akzeptierte Antwort.
Pashute
Dies funktioniert auch, wenn Sie die Anzahl der Zeilen nicht im Voraus kennen.
irene
34

Dies ist eine einfachere Version

import pandas as pd
df = pd.DataFrame(columns=('col1', 'col2', 'col3'))
for i in range(5):
   df.loc[i] = ['<some value for first>','<some value for second>','<some value for third>']`
Satheesh
quelle
4
Ich möchte nur fragen, ob diese CPU und dieser Speicher effizient sind.
czxttkl
1
Woher kenne ich die letzte Zeile von df, damit ich jedes Mal an die letzte Zeile anhänge?
Pashute
24

Wenn Ihre Eingabezeilen eher Listen als Wörterbücher sind, ist Folgendes eine einfache Lösung:

import pandas as pd
list_of_lists = []
list_of_lists.append([1,2,3])
list_of_lists.append([4,5,6])

pd.DataFrame(list_of_lists, columns=['A', 'B', 'C'])
#    A  B  C
# 0  1  2  3
# 1  4  5  6
stackoverflowuser2010
quelle
aber was mache ich, wenn ich einen Multi-Index habe? df1 = pd.DataFrame (Liste_der_Listen, Spalten ['A', 'B', 'C'], Index = ['A', 'B']) funktioniert nicht. Falsche Form. Wie also?
Pashute