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



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()

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

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

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

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')

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


7

Você pode usar 'compreensão de ditado'

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

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

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)

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.

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


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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.