2016-10-11 2 views
4

Ich habe einen DataFrame von people. Eine der Spalten in diesem DataFrame ist eine place_id. Ich habe auch einen DataFrame von Orten, wo eine der Spalten place_id ist und ein anderer ist weather. Für jede Person versuche ich das entsprechende Wetter zu finden. Wichtig ist, viele Leute haben die gleichen place_id s. diesePandas langsam. Willst zuerst Auftreten in DataFrame

Derzeit ist mein Setup:

def place_id_to_weather(pid): 
    return place_df[place_df['place_id'] == pid]['weather'].item() 

person_df['weather'] = person_df['place_id'].map(place_id_to_weather)` 

Aber das ist unvertretbar langsam. Ich möchte das beschleunigen. Ich vermute, dass ich ein Speedup wie dies erreichen könnte:

Statt place_df[...].item() der Rückkehr, die für place_id == pid für die gesamte Spalte eine Suche macht und eine Reihe zurückgibt, und dann in dieser Serie das erste Element greifen, ich möchte wirklich nur zu kürzen Sie die Suche in place_df nach dem ersten Spiel place_df['place_id']==pid wurde gefunden. Danach muss ich nicht weiter suchen. Wie beschränke ich die Suche nur auf erste Vorkommen?

Gibt es andere Methoden, die ich verwenden könnte, um hier eine Beschleunigung zu erreichen? Eine Art Join-Type-Methode?

Antwort

2

Ich glaube, Sie brauchen drop_duplicates mit merge, wenn es nur gemeinsame Spalten ist place_id und weather in beiden DataFrames, können Sie Parameter on weglassen (es von Daten abhängt, vielleicht on='place_id' ist erforderlich):

df1 = place_df.drop_duplicates(['place_id']) 
print (df1) 

print (pd.merge(person_df, df1)) 

Probe Daten:

person_df = pd.DataFrame({'place_id':['s','d','f','s','d','f'], 
          'A':[4,5,6,7,8,9]}) 
print (person_df) 
    A place_id 
0 4  s 
1 5  d 
2 6  f 
3 7  s 
4 8  d 
5 9  f 

place_df = pd.DataFrame({'place_id':['s','d','f', 's','d','f'], 
         'weather':['y','e','r', 'h','u','i']}) 
print (place_df) 
    place_id weather 
0  s  y 
1  d  e 
2  f  r 
3  s  h 
4  d  u 
5  f  i 
def place_id_to_weather(pid): 
    #for first occurence add iloc[0] 
    return place_df[place_df['place_id'] == pid]['weather'].iloc[0] 

person_df['weather'] = person_df['place_id'].map(place_id_to_weather) 
print (person_df) 
    A place_id weather 
0 4  s  y 
1 5  d  e 
2 6  f  r 
3 7  s  y 
4 8  d  e 
5 9  f  r 

#keep='first' is by default, so can be omit 
print (place_df.drop_duplicates(['place_id'])) 
    place_id weather 
0  s  y 
1  d  e 
2  f  r 

print (pd.merge(person_df, place_df.drop_duplicates(['place_id']))) 
    A place_id weather 
0 4  s  y 
1 7  s  y 
2 5  d  e 
3 8  d  e 
4 6  f  r 
5 9  f  r 
0

Sie merge verwenden können, um den Vorgang zu tun:

people = pd.DataFrame([['bob', 1], ['alice', 2], ['john', 3], ['paul', 2]], columns=['name', 'place']) 

# name place 
#0 bob  1 
#1 alice  2 
#2 john  3 
#3 paul  2 

weather = pd.DataFrame([[1, 'sun'], [2, 'rain'], [3, 'snow'], [1, 'rain']], columns=['place', 'weather']) 

# place weather 
#0  1  sun 
#1  2 rain 
#2  3 snow 
#3  1 rain 

pd.merge(people, weather, on='place') 

# name place weather 
#0 bob  1  sun 
#1 bob  1 rain 
#2 alice  2 rain 
#3 paul  2 rain 
#4 john  3 snow 

Falls Sie für den gleichen Ort mehrere Wetter haben, können Sie drop_duplicates verwenden, dann haben Sie das folgende Ergebnis:

1

Die Kartenfunktion ist Ihre schnellste Methode, deren Zweck es ist, den Aufruf eines ganzen Datenrahmens zu vermeiden, um eine Funktion auszuführen aßen. Dies ist, was Sie in Ihrer Funktion getan haben, d. H. Einen kompletten Datenrahmen aufzurufen, der gut ist, aber nicht gut, es wiederholt zu tun. Um Ihren Code nur ein wenig zu optimieren, wird Ihr Prozess erheblich beschleunigt und nur einmal das Datenfeld place_df aufgerufen: