Quelle est la manière la plus efficace de créer un dictionnaire de deux colonnes pandas Dataframe?


136

Quelle est la manière la plus efficace d'organiser les pandas Dataframe suivants:

données =

Position    Letter
1           a
2           b
3           c
4           d
5           e

dans un dictionnaire comme alphabet[1 : 'a', 2 : 'b', 3 : 'c', 4 : 'd', 5 : 'e']?

Réponses:


183
In [9]: pd.Series(df.Letter.values,index=df.Position).to_dict()
Out[9]: {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

Comparaison de vitesse (en utilisant la méthode de Wouter)

In [6]: df = pd.DataFrame(randint(0,10,10000).reshape(5000,2),columns=list('AB'))

In [7]: %timeit dict(zip(df.A,df.B))
1000 loops, best of 3: 1.27 ms per loop

In [8]: %timeit pd.Series(df.A.values,index=df.B).to_dict()
1000 loops, best of 3: 987 us per loop

20
Sans créer d'abord une série ... dict (zip (df.Position, df.Letter))
Wouter Overmeire

1
FYI ..... ma méthode est très proche de ce que fait Wouter, la différence est son implémentation en utilisant izip, plutôt que zip; générateur fait la différence je suppose
Jeff

1
@WouterOvermeire cela fonctionne parfaitement dans mon application, merci pour votre contribution
user1083734

3
@Jeff dict (zip ...) le plus rapide
Wouter Overmeire

3
Sur un DataFrame avec shape = (100,2), la méthode de Wouter avec dict (zip ...) était 3x plus rapide que celle de Jeff - j'ai utilisé% timeit
Quetzalcoatl

79

J'ai trouvé un moyen plus rapide de résoudre le problème, au moins sur des ensembles de données réalistes en utilisant: df.set_index(KEY).to_dict()[VALUE]

Preuve sur 50000 lignes:

df = pd.DataFrame(np.random.randint(32, 120, 100000).reshape(50000,2),columns=list('AB'))
df['A'] = df['A'].apply(chr)

%timeit dict(zip(df.A,df.B))
%timeit pd.Series(df.A.values,index=df.B).to_dict()
%timeit df.set_index('A').to_dict()['B']

Production:

100 loops, best of 3: 7.04 ms per loop  # WouterOvermeire
100 loops, best of 3: 9.83 ms per loop  # Jeff
100 loops, best of 3: 4.28 ms per loop  # Kikohs (me)

18
Faites toujours défiler vers le bas pour des réponses plus rapides possibles!
Nour Wolf

5

Dans Python 3.6, le moyen le plus rapide est toujours celui de WouterOvermeire. La proposition de Kikohs est plus lente que les deux autres options.

import timeit

setup = '''
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(32, 120, 100000).reshape(50000,2),columns=list('AB'))
df['A'] = df['A'].apply(chr)
'''

timeit.Timer('dict(zip(df.A,df.B))', setup=setup).repeat(7,500)
timeit.Timer('pd.Series(df.A.values,index=df.B).to_dict()', setup=setup).repeat(7,500)
timeit.Timer('df.set_index("A").to_dict()["B"]', setup=setup).repeat(7,500)

Résultats:

1.1214002349999777 s  # WouterOvermeire
1.1922008498571748 s  # Jeff
1.7034366211428602 s  # Kikohs

4

TL; DR

>>> import pandas as pd
>>> df = pd.DataFrame({'Position':[1,2,3,4,5], 'Letter':['a', 'b', 'c', 'd', 'e']})
>>> dict(sorted(df.values.tolist())) # Sort of sorted... 
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> from collections import OrderedDict
>>> OrderedDict(df.values.tolist())
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)])

En long

Solution explicative: dict(sorted(df.values.tolist()))

Donné:

df = pd.DataFrame({'Position':[1,2,3,4,5], 'Letter':['a', 'b', 'c', 'd', 'e']})

[en dehors]:

 Letter Position
0   a   1
1   b   2
2   c   3
3   d   4
4   e   5

Essayer:

# Get the values out to a 2-D numpy array, 
df.values

[en dehors]:

array([['a', 1],
       ['b', 2],
       ['c', 3],
       ['d', 4],
       ['e', 5]], dtype=object)

Puis éventuellement:

# Dump it into a list so that you can sort it using `sorted()`
sorted(df.values.tolist()) # Sort by key

Ou:

# Sort by value:
from operator import itemgetter
sorted(df.values.tolist(), key=itemgetter(1))

[en dehors]:

[['a', 1], ['b', 2], ['c', 3], ['d', 4], ['e', 5]]

Enfin, convertissez la liste de la liste de 2 éléments dans un dict.

dict(sorted(df.values.tolist())) 

[en dehors]:

{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

en relation

Répondre au commentaire de @sbradbio:

S'il existe plusieurs valeurs pour une clé spécifique et que vous souhaitez les conserver toutes, ce n'est pas le moyen le plus efficace mais le plus intuitif:

from collections import defaultdict
import pandas as pd

multivalue_dict = defaultdict(list)

df = pd.DataFrame({'Position':[1,2,4,4,4], 'Letter':['a', 'b', 'd', 'e', 'f']})

for idx,row in df.iterrows():
    multivalue_dict[row['Position']].append(row['Letter'])

[en dehors]:

>>> print(multivalue_dict)
defaultdict(list, {1: ['a'], 2: ['b'], 4: ['d', 'e', 'f']})

Existe-t-il un moyen d'ajouter plus d'une colonne comme valeur{'key': [value1, value2]}
sbradbio

1
Vérifier la réponse en annexe
alvas

Je pense que value1 et value2 sont deux colonnes distinctes. Pourriez-vous créer un dictionnaire avec {'id': ['long', 'lat]}? long et lat sont dans des colonnes séparées.
kms
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.