python pandas dataframe para dicionário

111

Eu tenho um dataframe de duas colunas e pretendo convertê-lo em um dicionário python - a primeira coluna será a chave e a segunda será o valor. Agradeço antecipadamente.

Quadro de dados:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4
perigeu
fonte
possível duplicata: stackoverflow.com/questions/18012505/…
dalloliogm
você verificou isso ?: pandas.pydata.org/pandas-docs/dev/generated/…
user2290820
4
@perigee: Você pode aceitar uma das respostas (se útil) para marcar a questão como resolvida? Isso ajudará outros usuários também.
MERose
se você tiver um id que corresponda ao índice, você deve defini-lo como índice.
Faris,

Respostas:

152

Veja a documentação para to_dict. Você pode usá-lo assim:

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

E se você tiver apenas uma coluna, para evitar o nome da coluna também é um nível no dicionário (na verdade, neste caso você usa o Series.to_dict()):

df.set_index('id')['value'].to_dict()
Joris
fonte
14
Observe que este comando perderá dados se houver valores redundantes nas colunas de ID: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm
9
Devo dizer que não há nada naquele link de docs que teria me dado a resposta a essa pergunta.
Ben Fulton de
@bombayquant veja DSM's e minhas respostas abaixo. Observe que esta é uma discussão de 4 anos.
dalloliogm
66
mydict = dict(zip(df.id, df.value))
Praful Gupta
fonte
1
Observação: caso o índice seja a chave de dicionário desejada, faça: dict (zip (df.index, df.value))
aLbAc
47

Se você deseja uma maneira simples de preservar duplicatas, pode usar 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
fonte
1
Solução bonita e elegante, mas em uma tabela de 50 mil linhas, é cerca de 6 vezes mais lenta do que a minha solução feia abaixo.
dalloliogm
@dalloliogm: você poderia dar uma tabela de exemplo para o que acontece? Se for seis vezes mais lento do que um loop do Python, pode haver um bug de desempenho no pandas.
DSM de
23

As respostas de joris neste tópico e de punchagan no tópico duplicado são muito elegantes, no entanto, eles não fornecerão resultados corretos se a coluna usada para as chaves contiver algum valor duplicado.

Por exemplo:

>>> 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 você duplicou entradas e não quer perdê-las, pode usar este código feio, mas funcional:

>>> 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
fonte
2
Desculpe a formatação devido à falta de um bloco nos comentários:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter
1
Embora não seja tão elegante quanto um one-liner, gostei muito mais da sua solução.
Peter Maguire
9

Solução mais simples:

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

Exemplo:

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

Se você tiver vários valores, como val1, val2, val3, etc e você os quiser como listas, use o código a seguir:

df.set_index('id').T.to_dict('list')
Gil Baggio
fonte
1
o que recordssignifica aqui?
mingchau
1
@mingchau recordsaqui significa ‘records’ : list like [{column -> value}, … , {column -> value}] Ver pandas.pydata.org/pandas-docs/stable/reference/api/…
AmuletxHeart
8

em algumas versões, o código abaixo pode não funcionar

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

então torne-o explícito

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

Observe que usei id_ porque a palavra id é uma palavra reservada

Vincent Appiah
fonte
7

Você pode usar 'compreensão de ditado'

my_dict = {row[0]: row[1] for row in df.values}
Dongwan Kim
fonte
Loop com pandas não é o mais eficiente em termos de uso de memória. Consulte: engineering.upside.com/…
tda
OP não pediu a resposta mais eficiente, então acho que @Dongwan Kim forneceu uma boa solução alternativa.
Um economista de
3

Outra solução (um pouco mais curta) para não perder entradas duplicadas:

>>> 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
fonte
1

Você precisa de uma lista como valor de dicionário. Este código fará o truque.

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

Eu encontrei essa pergunta enquanto tentava fazer um dicionário de três colunas de um dataframe do pandas. No meu caso, o dataframe tem colunas A, B e C (digamos que A e B são as coordenadas geográficas de longitude e latitude e C a região do país / estado / etc, que é mais ou menos o caso).

Eu queria um dicionário com cada par de valores A, B (chave de dicionário) correspondendo ao valor de C (valor de dicionário) na linha correspondente (cada par de valores A, B é garantido como único devido à filtragem anterior, mas é possível ter o mesmo valor de C para diferentes pares de valores de A, B neste contexto), então eu fiz:

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

Usar pandas to_dict () também funciona:

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

(nenhuma das colunas A ou B foi usada como índice antes de executar a linha de criação do dicionário)

Ambas as abordagens são rápidas (menos de um segundo em um dataframe com 85k linhas, laptop dual-core rápido de 5 anos de idade).

Os motivos pelos quais estou postando isso:

  1. para quem precisa desse tipo de solução
  2. se alguém conhece uma solução de execução mais rápida (por exemplo, para milhões de linhas), gostaria de receber uma resposta.
Alexandre Dias
fonte
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

este é o meu sloution, um loop básico

SummersKing
fonte
0

Esta é a minha solução:

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
fonte