python panda dataframe al dizionario


111

Ho un dataframe a due colonne e intendo convertirlo nel dizionario Python: la prima colonna sarà la chiave e la seconda il valore. Grazie in anticipo.

dataframe:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4



4
@perigeo: puoi forse accettare una delle risposte (se utile) per contrassegnare la domanda come risolta? Questo aiuterà anche altri utenti.
MERose

se hai un id che corrisponde all'indice dovresti impostarlo come index.
Faris

Risposte:


152

Vedi i documenti per to_dict. Puoi usarlo in questo modo:

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

E se hai solo una colonna, per evitare il nome della colonna è anche un livello nel dict (in realtà, in questo caso usi il Series.to_dict()):

df.set_index('id')['value'].to_dict()

14
Nota che questo comando perderà i dati se ci sono valori ridondanti nelle colonne ID: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm

9
Devo dire che non c'è niente in quel link alla documentazione che mi avrebbe dato la risposta a questa domanda.
Ben Fulton

@bombayquant vedi DSM e le mie risposte di seguito. Nota che questa è una discussione vecchia di 4 anni.
dalloliogm il

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

1
Nota: nel caso in cui l'indice sia la chiave del dizionario desiderata, eseguire: dict (zip (df.index, df.value))
aLbAc

47

Se vuoi un modo semplice per conservare i duplicati, potresti usare 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]}

1
Soluzione bella ed elegante, ma su una tabella di 50k righe è circa 6 volte più lenta della mia brutta soluzione qui sotto.
dalloliogm

@dalloliogm: potresti fornire una tabella di esempio che accade per? Se è sei volte più lento di un ciclo Python, potrebbe esserci un bug di prestazioni nei panda.
DSM

23

Le risposte di joris in questo thread e di punchagan nel thread duplicato sono molto eleganti, tuttavia non daranno risultati corretti se la colonna usata per le chiavi contiene un valore duplicato.

Per esempio:

>>> 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}

Se hai voci duplicate e non vuoi perderle, puoi usare questo codice brutto ma funzionante:

>>> 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]}

2
Scusa la formattazione per la mancanza di un blocco nei commenti:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter

1
Sebbene non sia elegante come una battuta, mi è piaciuta molto di più la tua soluzione.
Peter Maguire

9

Soluzione più semplice:

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

Esempio:

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

Se hai più valori, come val1, val2, val3, ecc e li vuoi come elenchi, usa il codice seguente:

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

1
cosa recordssignifica qui?
mingchau

1
@mingchau recordsqui significa ‘records’ : list like [{column -> value}, … , {column -> value}] Vedi pandas.pydata.org/pandas-docs/stable/reference/api/…
AmuletxHeart

8

in alcune versioni il codice seguente potrebbe non funzionare

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

quindi rendilo esplicito

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

Nota che ho usato id_ perché la parola id è una parola riservata


7

Puoi usare la "comprensione dettata"

my_dict = {row[0]: row[1] for row in df.values}

Il looping con i panda non è il più efficiente in termini di utilizzo della memoria. Vedi: engineering.upside.com/…
tda

OP non ha chiesto la risposta più efficiente, quindi penso che @Dongwan Kim abbia fornito una buona soluzione alternativa.
Un economista

3

Un'altra soluzione (leggermente più breve) per non perdere voci duplicate:

>>> 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]}

1

Hai bisogno di un elenco come valore del dizionario. Questo codice farà il trucco.

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

1

Ho trovato questa domanda mentre cercavo di creare un dizionario con tre colonne di un dataframe dei panda. Nel mio caso il dataframe ha le colonne A, B e C (diciamo che A e B sono le coordinate geografiche di longitudine e latitudine e C la regione / stato / ecc del paese, che è più o meno il caso).

Volevo un dizionario con ogni coppia di valori A, B (chiave del dizionario) corrispondente al valore di C (valore del dizionario) nella riga corrispondente (ogni coppia di valori A, B è garantita come unica a causa del filtraggio precedente, ma lo è possibile avere lo stesso valore di C per diverse coppie di valori A, B in questo contesto), quindi ho fatto:

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

Usare i panda to_dict () funziona anche:

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

(nessuna delle colonne A o B è stata utilizzata come indice prima di eseguire la riga di creazione del dizionario)

Entrambi gli approcci sono veloci (meno di un secondo su un dataframe con 85.000 righe, laptop dual-core veloce di 5 anni).

I motivi per cui sto postando questo:

  1. per chi necessita di questo tipo di soluzione
  2. se qualcuno conosce una soluzione di esecuzione più veloce (ad esempio, per milioni di righe), apprezzerei una risposta.

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

questa è la mia mossa, un ciclo di base


0

Questa è la mia soluzione:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.