python pandas dataframe au dictionnaire

111

J'ai un dataframe à deux colonnes et j'ai l'intention de le convertir en dictionnaire python - la première colonne sera la clé et la seconde sera la valeur. Merci d'avance.

Trame de données:

    id    value
0    0     10.2
1    1      5.7
2    2      7.4
périgée
la source
duplication possible: stackoverflow.com/questions/18012505/…
dalloliogm
avez-vous vérifié ceci?: pandas.pydata.org/pandas-docs/dev/generated/…
user2290820
4
@perigee: Pouvez-vous accepter l'une des réponses (si utile) pour marquer la question comme résolue? Cela aidera également les autres utilisateurs.
MERose
si vous avez un identifiant qui correspond à l'index, vous devez le définir comme index.
Faris le

Réponses:

152

Consultez la documentation pour to_dict. Vous pouvez l'utiliser comme ceci:

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

Et si vous n'avez qu'une seule colonne, pour éviter le nom de la colonne est également un niveau dans le dict (en fait, dans ce cas, vous utilisez le Series.to_dict()):

df.set_index('id')['value'].to_dict()
joris
la source
14
Notez que cette commande perdra des données s'il y a des valeurs redondantes dans les colonnes ID: >>> ptest = p.DataFrame([['a',1],['a',2],['b',3]], columns=['id', 'value']) >>> ptest.set_index('id')['value'].to_dict()
dalloliogm
9
Je dois dire qu'il n'y a rien dans ce lien de documentation qui m'aurait donné la réponse à cette question.
Ben Fulton
@bombayquant voir DSM et mes réponses ci-dessous. Notez qu'il s'agit d'une discussion vieille de 4 ans.
dalloliogm
66
mydict = dict(zip(df.id, df.value))
gupta praful
la source
1
Remarque: si l'index est la clé de dictionnaire souhaitée, alors faites: dict (zip (df.index, df.value))
aLbAc
47

Si vous voulez un moyen simple de conserver les doublons, vous pouvez utiliser 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
la source
1
Solution agréable et élégante, mais sur une table de 50k lignes, elle est environ 6 fois plus lente que ma solution laide ci-dessous.
dalloliogm
@dalloliogm: pourriez-vous donner un exemple de table qui se produit? Si c'est six fois plus lent qu'une boucle Python, il peut y avoir un bogue de performances dans les pandas.
DSM
23

Les réponses par joris dans ce fil et par punchagan dans le fil dupliqué sont très élégantes, cependant elles ne donneront pas de résultats corrects si la colonne utilisée pour les clés contient une valeur dupliquée.

Par exemple:

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

Si vous avez des entrées dupliquées et que vous ne voulez pas les perdre, vous pouvez utiliser ce code laid mais fonctionnel:

>>> 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
la source
2
Excusez le formatage en raison de l'absence de bloc dans les commentaires:mydict = defaultdict(list)\n for (key, val) in ptest[["id", "value"]].itertuples(index=False):\n mydict[key].append(val)
Midnighter
1
Bien qu'elle ne soit pas aussi élégante qu'un monoplace, j'ai beaucoup plus aimé votre solution.
Peter Maguire
9

Solution la plus simple:

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

Exemple:

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

Si vous avez plusieurs valeurs, comme val1, val2, val3, etc. et que vous les voulez sous forme de listes, utilisez le code ci-dessous:

df.set_index('id').T.to_dict('list')
Gil Baggio
la source
1
que veut recordsdire ici?
mingchau
1
@mingchau recordssignifie ici ‘records’ : list like [{column -> value}, … , {column -> value}] Voir pandas.pydata.org/pandas-docs/stable/reference/api/…
AmuletxHeart
8

dans certaines versions, le code ci-dessous peut ne pas fonctionner

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

alors rendez-le explicite

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

Notez que j'ai utilisé id_ parce que le mot id est un mot réservé

Vincent Appiah
la source
7

Vous pouvez utiliser 'dict comprehension'

my_dict = {row[0]: row[1] for row in df.values}
Dongwan Kim
la source
Faire une boucle avec des pandas n'est pas le plus efficace en termes d'utilisation de la mémoire. Voir: engineering.upside.com
...
OP n'a pas demandé la réponse la plus efficace, donc je pense que @Dongwan Kim a fourni une belle solution alternative.
Un économiste
3

Une autre solution (légèrement plus courte) pour ne pas perdre les entrées en double:

>>> 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
la source
1

Vous avez besoin d'une liste comme valeur de dictionnaire. Ce code fera l'affaire.

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

J'ai trouvé cette question en essayant de créer un dictionnaire à partir de trois colonnes d'un dataframe pandas. Dans mon cas, le dataframe a les colonnes A, B et C (disons que A et B sont les coordonnées géographiques de longitude et de latitude et C la région / état / etc du pays, ce qui est plus ou moins le cas).

Je voulais un dictionnaire avec chaque paire de valeurs A, B (clé de dictionnaire) correspondant à la valeur de C (valeur de dictionnaire) dans la ligne correspondante (chaque paire de valeurs A, B est garantie d'être unique en raison du filtrage précédent, mais c'est possible d'avoir la même valeur de C pour différentes paires de valeurs A, B dans ce contexte), alors j'ai fait:

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

L'utilisation de pandas to_dict () fonctionne également:

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

(aucune des colonnes A ou B n'a été utilisée comme index avant d'exécuter la ligne créant le dictionnaire)

Les deux approches sont rapides (moins d'une seconde sur une base de données de 85 000 lignes, un ordinateur portable double cœur rapide de 5 ans).

Les raisons pour lesquelles je poste ceci:

  1. pour ceux qui ont besoin de ce genre de solution
  2. si quelqu'un connaît une solution d'exécution plus rapide (par exemple, pour des millions de lignes), j'apprécierais une réponse.
Alexandre Dias
la source
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

c'est ma sloution, une boucle de base

SummersKing
la source
0

Voici ma solution:

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
la source