Was ist der effizienteste Weg, um ein Wörterbuch mit zwei Pandas-Dataframe-Spalten zu erstellen?

135

Was ist der effizienteste Weg, um die folgenden Pandas Dataframe zu organisieren:

Daten =

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

in ein Wörterbuch wie alphabet[1 : 'a', 2 : 'b', 3 : 'c', 4 : 'd', 5 : 'e']?

user1083734
quelle

Antworten:

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

Geschwindigkeitsvergleich (nach 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
Jeff
quelle
20
Ohne zuerst eine Serie zu erstellen ... diktieren (zip (df.Position, df.Letter))
Wouter Overmeire
1
Zu Ihrer Information ..... meine Methode ist sehr nah an der Haube, was Wouter tut. Der Unterschied besteht darin izip, dass sie eher mit als implementiert wird zip. Generator macht den Unterschied, denke ich
Jeff
1
@WouterOvermeire das funktioniert in meiner Anwendung perfekt, danke für Ihren Beitrag
user1083734
3
@ Jeff Dikt (zip ...) schnellster
Wouter Overmeire
3
Auf einem DataFrame mit shape = (100,2) war Wouters Methode mit dict (zip ...) dreimal schneller als die von Jeff - ich habe% timeit verwendet
Quetzalcoatl
79

Ich habe einen schnelleren Weg gefunden, um das Problem zu lösen, zumindest bei realistisch großen Datenmengen mit: df.set_index(KEY).to_dict()[VALUE]

Beweis auf 50.000 Zeilen:

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

Ausgabe:

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)
Kirell
quelle
18
Scrollen Sie immer nach unten, um schnellere Antworten zu erhalten!
Nour Wolf
5

In Python 3.6 ist der schnellste Weg immer noch der WouterOvermeire. Kikohs Vorschlag ist langsamer als die beiden anderen Optionen.

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)

Ergebnisse:

1.1214002349999777 s  # WouterOvermeire
1.1922008498571748 s  # Jeff
1.7034366211428602 s  # Kikohs
pakobill
quelle
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)])

In Long

Erklärende Lösung: dict(sorted(df.values.tolist()))

Gegeben:

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

[aus]:

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

Versuchen:

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

[aus]:

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

Dann optional:

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

Oder:

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

[aus]:

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

Zuletzt wandeln Sie die Liste der 2 Elemente in ein Diktat um.

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

[aus]:

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

verbunden

Antwort auf @sbradbio Kommentar:

Wenn es für einen bestimmten Schlüssel mehrere Werte gibt und Sie alle behalten möchten, ist dies nicht der effizienteste, aber der intuitivste Weg:

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

[aus]:

>>> print(multivalue_dict)
defaultdict(list, {1: ['a'], 2: ['b'], 4: ['d', 'e', 'f']})
Alvas
quelle
Gibt es eine Möglichkeit, mehr als eine Spalte als Wert {'key': [value1, value2]}
hinzuzufügen
1
Überprüfen Sie die angehängte Antwort
Alvas
Ich denke, Wert1 und Wert2 sind zwei separate Spalten. Könnten Sie ein Wörterbuch mit {'id': ['long', 'lat]} erstellen? long und lat stehen in getrennten Spalten.
km