Konvertieren Sie die Liste der Wörterbücher in einen Pandas DataFrame

650

Ich habe eine Liste solcher Wörterbücher:

[{'points': 50, 'time': '5:00', 'year': 2010}, 
{'points': 25, 'time': '6:00', 'month': "february"}, 
{'points':90, 'time': '9:00', 'month': 'january'}, 
{'points_h1':20, 'month': 'june'}]

Und ich möchte daraus Pandas machen DataFrame:

      month  points  points_h1  time  year
0       NaN      50        NaN  5:00  2010
1  february      25        NaN  6:00   NaN
2   january      90        NaN  9:00   NaN
3      june     NaN         20   NaN   NaN

Hinweis: Die Reihenfolge der Spalten spielt keine Rolle.

Wie kann ich die Liste der Wörterbücher wie oben gezeigt in einen Pandas DataFrame verwandeln?

AppleLover
quelle

Antworten:

945

Angenommen, es dist Ihre Liste von Diktaten, einfach:

pd.DataFrame(d)
Joris
quelle
3
Wie könnte man eines der Schlüssel / Wert-Paare als Index verwenden (z. B. Zeit)?
CatsLoveJazz
6
@CatsLoveJazz Sie können nur df = df.set_index('time')danach tun
joris
1
@CatsLoveJazz Nein, das ist beim Konvertieren von einem Diktat nicht möglich.
Joris
5
Ab Pandas 0.19.2 wird dies in der Dokumentation nicht erwähnt, zumindest nicht in den Dokumenten fürpandas.DataFrame
Leo Alekseyev,
1
'{"":{"...Beachten Sie, dass Sie für ein verschachteltes Wörterbuch den Ansatz json_normalize verwenden, siehe die ausführliche Antwort von @ cs95
Lorenz
136

Wie konvertiere ich eine Liste von Wörterbüchern in einen Pandas DataFrame?

Die anderen Antworten sind richtig, aber es wurde nicht viel über die Vor- und Nachteile dieser Methoden erklärt. Das Ziel dieses Beitrags ist es, Beispiele für diese Methoden in verschiedenen Situationen zu zeigen, zu diskutieren, wann sie verwendet werden sollen (und wann nicht) und Alternativen vorzuschlagen.


DataFrame(), DataFrame.from_records()Und.from_dict()

Abhängig von der Struktur und dem Format Ihrer Daten gibt es Situationen, in denen entweder alle drei Methoden funktionieren oder einige besser funktionieren als andere oder einige überhaupt nicht funktionieren.

Betrachten Sie ein sehr ausgeklügeltes Beispiel.

np.random.seed(0)
data = pd.DataFrame(
    np.random.choice(10, (3, 4)), columns=list('ABCD')).to_dict('r')

print(data)
[{'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]

Diese Liste besteht aus "Datensätzen" mit allen vorhandenen Schlüsseln. Dies ist der einfachste Fall, dem Sie begegnen könnten.

# The following methods all produce the same output.
pd.DataFrame(data)
pd.DataFrame.from_dict(data)
pd.DataFrame.from_records(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

Wort zur Wörterbuchorientierung: orient='index'/'columns'

Bevor Sie fortfahren, ist es wichtig, zwischen den verschiedenen Arten von Wörterbuchorientierungen und der Unterstützung durch Pandas zu unterscheiden. Es gibt zwei Haupttypen: "Spalten" und "Index".

orient='columns'
Bei Wörterbüchern mit der Ausrichtung "Spalten" entsprechen die Schlüssel den Spalten im entsprechenden DataFrame.

Zum Beispiel ist dataoben in der "Spalten" Orientierung.

data_c = [
 {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]

pd.DataFrame.from_dict(data_c, orient='columns')

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

Hinweis: Wenn Sie verwenden pd.DataFrame.from_records, wird angenommen, dass die Ausrichtung "Spalten" ist (Sie können nichts anderes angeben), und die Wörterbücher werden entsprechend geladen.

orient='index'
Bei dieser Ausrichtung wird angenommen, dass Schlüssel Indexwerten entsprechen. Diese Art von Daten ist am besten geeignet für pd.DataFrame.from_dict.

data_i ={
 0: {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 1: {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 2: {'A': 2, 'B': 4, 'C': 7, 'D': 6}}

pd.DataFrame.from_dict(data_i, orient='index')

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

Dieser Fall wird im OP nicht berücksichtigt, ist aber dennoch nützlich zu wissen.

Benutzerdefinierten Index festlegen

Wenn Sie einen benutzerdefinierten Index für den resultierenden DataFrame benötigen, können Sie ihn mithilfe des index=...Arguments festlegen .

pd.DataFrame(data, index=['a', 'b', 'c'])
# pd.DataFrame.from_records(data, index=['a', 'b', 'c'])

   A  B  C  D
a  5  0  3  3
b  7  9  3  5
c  2  4  7  6

Dies wird von nicht unterstützt pd.DataFrame.from_dict.

Umgang mit fehlenden Schlüsseln / Spalten

Alle Methoden funktionieren sofort, wenn Wörterbücher mit fehlenden Schlüssel- / Spaltenwerten verarbeitet werden. Zum Beispiel,

data2 = [
     {'A': 5, 'C': 3, 'D': 3},
     {'A': 7, 'B': 9, 'F': 5},
     {'B': 4, 'C': 7, 'E': 6}]

# The methods below all produce the same output.
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)

     A    B    C    D    E    F
0  5.0  NaN  3.0  3.0  NaN  NaN
1  7.0  9.0  NaN  NaN  NaN  5.0
2  NaN  4.0  7.0  NaN  6.0  NaN

Teilmenge der Spalten lesen

"Was ist, wenn ich nicht in jeder einzelnen Spalte lesen möchte?" Sie können dies einfach mit dem columns=...Parameter angeben .

Wenn Sie beispielsweise aus dem data2obigen Beispielwörterbuch nur die Spalten "A", "D" und "F" lesen möchten, können Sie dies tun, indem Sie eine Liste übergeben:

pd.DataFrame(data2, columns=['A', 'D', 'F'])
# pd.DataFrame.from_records(data2, columns=['A', 'D', 'F'])

     A    D    F
0  5.0  3.0  NaN
1  7.0  NaN  5.0
2  NaN  NaN  NaN

Dies wird von pd.DataFrame.from_dictden Standardausrichtungsspalten nicht unterstützt .

pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])

ValueError: cannot use columns parameter with orient='columns'

Teilmenge der Zeilen lesen

Wird von keiner dieser Methoden direkt unterstützt . Sie müssen Ihre Daten durchlaufen und beim Iterieren an Ort und Stelle einen umgekehrten Löschvorgang durchführen . Zum Beispiel extrahieren nur die 0 - ten und 2 nd Reihen von data2oben, können Sie:

rows_to_select = {0, 2}
for i in reversed(range(len(data2))):
    if i not in rows_to_select:
        del data2[i]

pd.DataFrame(data2)
# pd.DataFrame.from_dict(data2)
# pd.DataFrame.from_records(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

Das Allheilmittel: json_normalizefür verschachtelte Daten

Eine starke, robuste Alternative zu den oben beschriebenen Methoden ist die json_normalizeFunktion, die mit Listen von Wörterbüchern (Datensätzen) arbeitet und darüber hinaus auch verschachtelte Wörterbücher verarbeiten kann.

pd.io.json.json_normalize(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

pd.io.json.json_normalize(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

Beachten Sie auch hier, dass die an übergebenen Daten json_normalizeim Format der Liste der Wörterbücher (Datensätze) vorliegen müssen.

Wie bereits erwähnt, json_normalizekönnen auch verschachtelte Wörterbücher verarbeitet werden. Hier ist ein Beispiel aus der Dokumentation.

data_nested = [
  {'counties': [{'name': 'Dade', 'population': 12345},
                {'name': 'Broward', 'population': 40000},
                {'name': 'Palm Beach', 'population': 60000}],
   'info': {'governor': 'Rick Scott'},
   'shortname': 'FL',
   'state': 'Florida'},
  {'counties': [{'name': 'Summit', 'population': 1234},
                {'name': 'Cuyahoga', 'population': 1337}],
   'info': {'governor': 'John Kasich'},
   'shortname': 'OH',
   'state': 'Ohio'}
]

pd.io.json.json_normalize(data_nested, 
                          record_path='counties', 
                          meta=['state', 'shortname', ['info', 'governor']])

         name  population    state shortname info.governor
0        Dade       12345  Florida        FL    Rick Scott
1     Broward       40000  Florida        FL    Rick Scott
2  Palm Beach       60000  Florida        FL    Rick Scott
3      Summit        1234     Ohio        OH   John Kasich
4    Cuyahoga        1337     Ohio        OH   John Kasich

Weitere Informationen zu metaund record_pathArgumenten finden Sie in der Dokumentation.


Zusammenfassen

Hier finden Sie eine Tabelle aller oben beschriebenen Methoden sowie die unterstützten Features / Funktionen.

Geben Sie hier die Bildbeschreibung ein

* Verwenden Sie orient='columns'und transponieren Sie, um den gleichen Effekt wie zu erzielen orient='index'.

cs95
quelle
8
Woah! Okay, dies gehört zusammen mit dem Zusammenführen von SO-Posts zur API. Sie sollten zu den Pandas-Dokumentationen beitragen, falls Sie dies noch nicht getan haben. Ted Petrou hat gerade einen LinkedIn-Artikel über die Beliebtheit von Pandas auf Stack Overflow veröffentlicht und erwähnt, dass der Mangel an guter Dokumentation zum Umfang der Fragen hier beiträgt.
Scott Boston
2
@ScottBoston Du hast absolut Recht, ich habe das schon oft genug gehört, jetzt wo ich weiß, dass es etwas ist, über das ich ernsthafter nachdenken sollte. Ich denke, die Dokumentation kann eine großartige Möglichkeit sein, Benutzern zu helfen, anstatt Fragen zu stellen, die nur einen Bruchteil derselben Zielgruppe erreichen würden.
CS95
1
Es ist eine schöne Antwort. Ich denke, es ist Zeit für uns, diese häufig gestellte Frage unter der aktuellsten Pandas-Version erneut zu
beantworten
3
@ely: das ist sowieso nie ein grund, hier keine antworten zu schreiben . Jede Antwort kann veraltet sein, dafür haben wir gestimmt, und hier gibt es unterschiedliche Perspektiven und Ziele, und es ist immer wertvoll, unterschiedliche Erklärungsmöglichkeiten für dasselbe zu haben.
Martijn Pieters
1
@MartijnPieters Ich frage und stimme Ihrer letzten Behauptung nicht zu, aber insgesamt stimme ich Ihnen zu. Es ist nicht immer wertschöpfend, verschiedene Antworten auf dieselbe Frage zusammenzustellen, insbesondere wenn einige der Antworten Aktualisierungen oder bedingte Unterschiede sind, die auf anderen Antworten basieren. Im schlimmsten Fall können diese Antworten beim Zusammenstellen wertzerstörend sein (im Gegensatz zur Verwendung der aktualisierten Antwort, um die ältere Antwort einfach in einen korrekteren Zustand zu bringen). Aber auch hier stimme ich Ihnen weitgehend zu.
ely
83

In Pandas 16.2 musste ich tun pd.DataFrame.from_records(d), um dies zum Laufen zu bringen.

szeitlin
quelle
1
Das Gute an diesem Ansatz ist, dass er auch mitdeque
MBZ
3
funktioniert gut mit Pandas 0.17.1mit @ joris Lösung
Anton Protopopov
2
Usinig 0.14.1 und @joris 'Lösung funktionierten nicht, aber dies tat
mchen
13
In 0.18.1muss verwendet werden, from_recordswenn die Wörterbücher nicht alle die gleichen Schlüssel haben.
Fredcallaway
23

Sie können auch verwenden pd.DataFrame.from_dict(d)als:

In [8]: d = [{'points': 50, 'time': '5:00', 'year': 2010}, 
   ...: {'points': 25, 'time': '6:00', 'month': "february"}, 
   ...: {'points':90, 'time': '9:00', 'month': 'january'}, 
   ...: {'points_h1':20, 'month': 'june'}]

In [12]: pd.DataFrame.from_dict(d)
Out[12]: 
      month  points  points_h1  time    year
0       NaN    50.0        NaN  5:00  2010.0
1  february    25.0        NaN  6:00     NaN
2   january    90.0        NaN  9:00     NaN
3      june     NaN       20.0   NaN     NaN
shivsn
quelle
Bei der Frage geht es darum, einen Datenrahmen aus einer Liste von dicts zu erstellen , nicht aus einem einzelnen, dictwie Sie in Ihrer Antwort angenommen haben.
a_guest
@a_guest Überprüfen Sie die aktualisierte Antwort. Ich gehe nicht davon aus.
Shivsn
2

Ich weiß, dass ein paar Leute darauf stoßen werden und nichts hier hilft. Der einfachste Weg, den ich gefunden habe, ist folgender:

dict_count = len(dict_list)
df = pd.DataFrame(dict_list[0], index=[0])
for i in range(1,dict_count-1):
    df = df.append(dict_list[i], ignore_index=True)

Hoffe das hilft jemandem!

Scottapotamus
quelle
1
list=[{'points': 50, 'time': '5:00', 'year': 2010}, 
{'points': 25, 'time': '6:00', 'month': "february"}, 
{'points':90, 'time': '9:00', 'month': 'january'}, 
{'points_h1':20, 'month': 'june'}]

und einfacher Anruf:

pd=DataFrame.from_dict(list, orient='columns', dtype=None)

print(pd)
Günel
quelle
0

Pyhton3: Die meisten der zuvor aufgeführten Lösungen funktionieren. Es gibt jedoch Fälle, in denen die Zeilennummer des Datenrahmens nicht erforderlich ist und jede Zeile (jeder Datensatz) einzeln geschrieben werden muss.

Die folgende Methode ist in diesem Fall nützlich.

import csv

my file= 'C:\Users\John\Desktop\export_dataframe.csv'

records_to_save = data2 #used as in the thread. 


colnames = list[records_to_save[0].keys()] 
# remember colnames is a list of all keys. All values are written corresponding
# to the keys and "None" is specified in case of missing value 

with open(myfile, 'w', newline="",encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(colnames)
    for d in records_to_save:
        writer.writerow([d.get(r, "None") for r in colnames])
Soum
quelle
0

Zum Konvertieren einer Liste von Wörterbüchern in einen Pandas-DataFrame können Sie "Anhängen" verwenden:

Wir haben ein Wörterbuch genannt dicund dic hat 30 Listenelemente ( list1, list2..., list30)

  1. Schritt 1: Definieren Sie eine Variable, um Ihr Ergebnis zu speichern (Beispiel: total_df )
  2. Schritt 2: Initialisieren total_df mitlist1
  3. Schritt 3: Verwenden Sie "for loop", um alle Listen an anzuhängen total_df
total_df=list1
nums=Series(np.arange(start=2, stop=31))
for num in nums:
    total_df=total_df.append(dic['list'+str(num)])
Armin Ahmadi Nasab
quelle
Was ist der Vorteil dieses Ansatzes gegenüber der von @ CS95 in ihrer detaillierten zwei Jahre alte Antwort in Bezug auf skizzierten Ansätze DataFrame(), DataFrame.from_records()und .from_dict()?
Jeremy Caney
Ich habe alle oben genannten Methoden für ein Wörterbuch mit 30 Listen getestet. Die Antwort habe ich nur mit der Funktion Anhängen erhalten.
Armin Ahmadi Nasab