Python Pandas Datenrahmen zum Wörterbuch

111

Ich habe einen Datenrahmen mit zwei Spalten und beabsichtige, ihn in ein Python-Wörterbuch zu konvertieren. Die erste Spalte ist der Schlüssel und die zweite der Wert. Vielen Dank im Voraus.

Datenrahmen:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4
Perigäum
quelle
Mögliches Duplikat: stackoverflow.com/questions/18012505/…
dalloliogm
Haben Sie dies überprüft?: pandas.pydata.org/pandas-docs/dev/generated/…
user2290820
4
@perigee: Können Sie vielleicht eine der Antworten akzeptieren (falls hilfreich), um die Frage als gelöst zu markieren? Dies wird auch anderen Benutzern helfen.
MERose
Wenn Sie eine ID haben, die mit dem Index übereinstimmt, sollten Sie sie als Index festlegen.
Faris

Antworten:

151

Siehe die Dokumente für to_dict. Sie können es so verwenden:

df.set_index('id').to_dict()

Und wenn Sie nur eine Spalte haben, ist das Vermeiden des Spaltennamens auch eine Ebene im Diktat (tatsächlich verwenden Sie in diesem Fall die Series.to_dict()):

df.set_index('id')['value'].to_dict()
Joris
quelle
14
Beachten Sie, dass dieser Befehl Daten verliert, wenn redundante Werte in den ID-Spalten vorhanden sind: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm
9
Ich muss sagen, es gibt nichts in diesem Dokument-Link, was mir die Antwort auf diese Frage gegeben hätte.
Ben Fulton
@bombayquant siehe DSMs und meine Antworten unten. Beachten Sie, dass dies eine 4 Jahre alte Diskussion ist.
Dalloliogm
65
mydict = dict(zip(df.id, df.value))
praful gupta
quelle
1
Hinweis: Wenn der Index der gewünschte Wörterbuchschlüssel ist, tun Sie: dict (zip (df.index, df.value))
aLbAc
47

Wenn Sie auf einfache Weise Duplikate aufbewahren möchten, können Sie Folgendes verwenden groupby:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3
>>> {k: g["value"].tolist() for k,g in ptest.groupby("id")}
{'a': [1, 2], 'b': [3]}
DSM
quelle
1
Schöne und elegante Lösung, aber auf einer Tabelle mit 50.000 Zeilen ist sie ungefähr sechsmal langsamer als meine hässliche Lösung unten.
Dalloliogm
@dalloliogm: Könnten Sie eine Beispieltabelle angeben, für die dies geschieht? Wenn es sechsmal langsamer als eine Python-Schleife ist, liegt möglicherweise ein Leistungsfehler bei Pandas vor.
DSM
23

Die Antworten von Joris in diesem Thread und von Punchagan im duplizierten Thread sind sehr elegant, liefern jedoch keine korrekten Ergebnisse, wenn die für die Schlüssel verwendete Spalte einen doppelten Wert enthält.

Beispielsweise:

>>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) 
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

# note that in both cases the association a->1 is lost:
>>> ptest.set_index('id')['value'].to_dict()
{'a': 2, 'b': 3}
>>> dict(zip(ptest.id, ptest.value))
{'a': 2, 'b': 3}

Wenn Sie doppelte Einträge haben und diese nicht verlieren möchten, können Sie diesen hässlichen, aber funktionierenden Code verwenden:

>>> mydict = {}
>>> for x in range(len(ptest)):
...     currentid = ptest.iloc[x,0]
...     currentvalue = ptest.iloc[x,1]
...     mydict.setdefault(currentid, [])
...     mydict[currentid].append(currentvalue)
>>> mydict
{'a': [1, 2], 'b': [3]}
dalloliogm
quelle
2
Entschuldigen Sie die Formatierung, da in den Kommentaren kein Block vorhanden ist:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter
1
Obwohl nicht so elegant wie ein Einzeiler, hat mir Ihre Lösung viel besser gefallen.
Peter Maguire
9

Einfachste Lösung:

df.set_index('id').T.to_dict('records')

Beispiel:

df= pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
df.set_index('id').T.to_dict('records')

Wenn Sie mehrere Werte wie val1, val2, val3 usw. haben und diese als Listen verwenden möchten, verwenden Sie den folgenden Code:

df.set_index('id').T.to_dict('list')
Gil Baggio
quelle
was recordsbedeutet hier
Mingchau
1
@mingchau recordshier bedeuten ‘records’ : list like [{column -> value}, … , {column -> value}] Siehe pandas.pydata.org/pandas-docs/stable/reference/api/…
AmuletxHeart
8

In einigen Versionen funktioniert der folgende Code möglicherweise nicht

mydict = dict(zip(df.id, df.value))

also mach es explizit

id_=df.id.values
value=df.value.values
mydict=dict(zip(id_,value))

Beachten Sie, dass ich id_ verwendet habe, da das Wort id ein reserviertes Wort ist

Vincent Appiah
quelle
7

Sie können "Diktatverständnis" verwenden.

my_dict = {row[0]: row[1] for row in df.values}
Dongwan Kim
quelle
Das Schleifen mit Pandas ist in Bezug auf die Speichernutzung nicht das effizienteste. Siehe: engineering.upside.com/…
tda
OP hat nicht nach der effizientesten Antwort gefragt, daher denke ich, dass @Dongwan Kim eine gute alternative Lösung bietet.
Ein Ökonom
3

Eine weitere (etwas kürzere) Lösung, um keine doppelten Einträge zu verlieren:

>>> ptest = pd.DataFrame([['a',1],['a',2],['b',3]], columns=['id','value'])
>>> ptest
  id  value
0  a      1
1  a      2
2  b      3

>>> pdict = dict()
>>> for i in ptest['id'].unique().tolist():
...     ptest_slice = ptest[ptest['id'] == i]
...     pdict[i] = ptest_slice['value'].tolist()
...

>>> pdict
{'b': [3], 'a': [1, 2]}
user1376377
quelle
1

Sie benötigen eine Liste als Wörterbuchwert. Dieser Code wird den Trick machen.

from collections import defaultdict
mydict = defaultdict(list)
for k, v in zip(df.id.values,df.value.values):
    mydict[k].append(v)
Dmitry
quelle
1

Ich habe diese Frage gefunden, als ich versucht habe, aus drei Spalten eines Pandas-Datenrahmens ein Wörterbuch zu erstellen. In meinem Fall hat der Datenrahmen die Spalten A, B und C (sagen wir, A und B sind die geografischen Koordinaten von Längen- und Breitengrad und C die Länderregion / Bundesland / usw., was mehr oder weniger der Fall ist).

Ich wollte ein Wörterbuch mit jedem Paar von A, B-Werten (Wörterbuchschlüssel), das mit dem Wert von C (Wörterbuchwert) in der entsprechenden Zeile übereinstimmt (jedes Paar von A, B-Werten ist aufgrund der vorherigen Filterung garantiert eindeutig, aber es ist möglich, in diesem Zusammenhang den gleichen Wert von C für verschiedene Paare von A-, B-Werten zu haben), also habe ich:

mydict = dict(zip(zip(df['A'],df['B']), df['C']))

Die Verwendung von pandas to_dict () funktioniert auch:

mydict = df.set_index(['A','B']).to_dict(orient='dict')['C']

(Keine der Spalten A oder B wurde als Index verwendet, bevor die Zeile ausgeführt wurde, in der das Wörterbuch erstellt wurde.)

Beide Ansätze sind schnell (weniger als eine Sekunde auf einem Datenrahmen mit 85.000 Zeilen, 5 Jahre alter schneller Dual-Core-Laptop).

Die Gründe, warum ich dies poste:

  1. für diejenigen, die diese Art von Lösung benötigen
  2. Wenn jemand eine Lösung kennt, die schneller ausgeführt werden kann (z. B. für Millionen von Zeilen), würde ich mich über eine Antwort freuen.
Alexandre Dias
quelle
0
def get_dict_from_pd(df, key_col, row_col):
    result = dict()
    for i in set(df[key_col].values):
        is_i = df[key_col] == i
        result[i] = list(df[is_i][row_col].values)
    return result

Dies ist meine Sloution, eine grundlegende Schleife

SummersKing
quelle
0

Das ist meine Lösung:

import pandas as pd
df = pd.read_excel('dic.xlsx')
df_T = df.set_index('id').T
dic = df_T.to_dict('records')
print(dic)
Hamoon
quelle