python pandas dataframe do słownika

111

Mam dwie kolumny dataframe i zamierzam przekonwertować ją na słownik Pythona - pierwsza kolumna będzie kluczem, a druga będzie wartością. Z góry dziękuję.

Ramka danych:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4
perygeum
źródło
możliwy duplikat: stackoverflow.com/questions/18012505/ ...
dalloliogm
sprawdziłeś to ?: pandas.pydata.org/pandas-docs/dev/generated/…
user2290820
4
@perigee: Czy możesz zaakceptować jedną z odpowiedzi (jeśli byłaby pomocna), aby oznaczyć pytanie jako rozwiązane? Pomoże to również innym użytkownikom.
MERose,
jeśli masz identyfikator, który pasuje do indeksu, powinieneś ustawić go jako indeks.
Faris

Odpowiedzi:

152

Zobacz dokumentację dla to_dict. Możesz go używać w ten sposób:

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

A jeśli masz tylko jedną kolumnę, aby uniknąć nazwy kolumny, jest to również poziom w dyktcie (w rzeczywistości w tym przypadku używasz Series.to_dict()):

df.set_index('id')['value'].to_dict()
joris
źródło
14
Zauważ, że to polecenie spowoduje utratę danych, jeśli w kolumnach ID znajdują się zbędne wartości: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm
9
Muszę powiedzieć, że w tym linku do dokumentów nie ma nic, co dałoby mi odpowiedź na to pytanie.
Ben Fulton
@bombayquant zobacz poniżej DSM i moje odpowiedzi. Zwróć uwagę, że jest to dyskusja sprzed 4 lat.
dalloliogm
66
mydict = dict(zip(df.id, df.value))
praful gupta
źródło
1
Uwaga: w przypadku, gdy indeks jest żądanym kluczem słownika, wykonaj: dict (zip (df.index, df.value))
aLbAc
48

Jeśli chcesz w prosty sposób zachować duplikaty, możesz użyć 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
źródło
1
Ładne i eleganckie rozwiązanie, ale na stole 50 tys. Rzędów jest około 6 razy wolniejsze niż moje brzydkie rozwiązanie poniżej.
dalloliogm
@dalloliogm: czy możesz podać przykładową tabelę, która ma miejsce? Jeśli jest sześć razy wolniejszy niż pętla Pythona, może wystąpić błąd wydajności w pandach.
DSM,
23

Odpowiedzi jorisa w tym wątku i punchagana w zduplikowanym wątku są bardzo eleganckie, jednak nie dadzą poprawnych wyników, jeśli kolumna użyta na klucze zawiera zduplikowaną wartość.

Na przykład:

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

Jeśli masz zduplikowane wpisy i nie chcesz ich zgubić, możesz użyć tego brzydkiego, ale działającego kodu:

>>> 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
źródło
2
Przepraszam formatowanie z powodu braku bloku w komentarzach:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter
1
Chociaż nie jest tak elegancka jak jednolinijka, bardziej spodobało mi się Twoje rozwiązanie.
Peter Maguire
9

Najprostsze rozwiązanie:

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

Przykład:

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

Jeśli masz wiele wartości, takich jak val1, val2, val3 itp. I chcesz je mieć jako listy, użyj poniższego kodu:

df.set_index('id').T.to_dict('list')
Gil Baggio
źródło
1
co to recordsznaczy?
mingchau
1
@mingchau recordstutaj znaczy ‘records’ : list like [{column -> value}, … , {column -> value}] Zobacz pandas.pydata.org/pandas-docs/stable/reference/api/…
AmuletxHeart
8

w niektórych wersjach poniższy kod może nie działać

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

więc wyraź to

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

Zauważ, że użyłem id_, ponieważ słowo id jest słowem zastrzeżonym

Vincent Appiah
źródło
7

Możesz użyć `` dyktowania ze zrozumieniem ''

my_dict = {row[0]: row[1] for row in df.values}
Dongwan Kim
źródło
Pętle z pandami nie są najbardziej wydajne pod względem wykorzystania pamięci. Zobacz: engineering.upside.com/…
tda
OP nie zapytał o najbardziej efektywną odpowiedź, więc myślę, że @Dongwan Kim zapewnił fajne alternatywne rozwiązanie.
Ekonomista
3

Kolejne (nieco krótsze) rozwiązanie pozwalające uniknąć utraty zduplikowanych wpisów:

>>> 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
źródło
1

Potrzebujesz listy jako wartości słownikowej. Ten kod załatwi sprawę.

from collections import defaultdict
mydict = defaultdict(list)
for k, v in zip(df.id.values,df.value.values):
    mydict[k].append(v)
Dmitrij
źródło
1

Znalazłem to pytanie, próbując utworzyć słownik z trzech kolumn ramki danych pandy. W moim przypadku ramka danych ma kolumny A, B i C (powiedzmy, że A i B to współrzędne geograficzne długości i szerokości geograficznej, a C to region kraju / stan / itp., Co mniej więcej tak jest).

Chciałem mieć słownik z każdą parą wartości A, B (klucz słownika) pasującą do wartości C (wartość słownika) w odpowiednim wierszu (każda para wartości A, B jest unikalna ze względu na poprzednie filtrowanie, ale tak jest można mieć taką samą wartość C dla różnych par wartości A, B w tym kontekście), więc zrobiłem:

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

Używanie pand to_dict () działa również:

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

(żadna z kolumn A ani B nie była używana jako indeks przed wykonaniem wiersza tworzącego słownik)

Oba podejścia są szybkie (mniej niż jedna sekunda w ramce danych z 85 tys. Rzędami, 5-letnim szybkim dwurdzeniowym laptopem).

Powody, dla których to publikuję:

  1. dla tych, którzy potrzebują takiego rozwiązania
  2. jeśli ktoś zna szybsze rozwiązanie (np. dla milionów wierszy), byłbym wdzięczny za odpowiedź.
Alexandre Dias
źródło
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

to jest mój sloution, podstawowa pętla

SummersKing
źródło
0

To jest moje rozwiązanie:

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
źródło