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.