2016-08-26 3 views
2

У меня есть два блока данных координат archivo1 и archivo2, мне нужна самая близкая точка (id) второго кадра данных в первом. До сих пор мой код не является:Как присоединиться к двум фреймам данных в пандах с использованием координат

import pandas as pd 
import numpy as np 

def getDistance(archivo1,lat,log): 
    R = 6371 
    archivo1['dLat'] =(lat-archivo1['lat']).apply(deg2rad)/2 
    archivo1['dLon'] =(log-archivo1['log']).apply(deg2rad)/2 
    archivo1['a']=(archivo1['dLat'].apply(math.sin))*(archivo1['dLat'].apply(math.sin))+(archivo1['lat'].apply(deg2rad).apply(math.cos))*(math.cos(deg2rad(lat)))*(archivo1['dLon'].apply(math.sin))*(archivo1['dLon'].apply(math.sin)) 
    archivo1['b']= archivo1['a'].apply(math.sqrt)/(1-archivo1['a'].apply(math.sqrt)) 
    archivo1['Distancia']=R*2*archivo1['b'].apply(math.atan) 

def deg2rad(deg): 
    return deg * (math.pi/180) 

for i in range(len(archivo1)): 
    getDistance(archivo1,archivo2['lat'].iloc[i],archivo2['long'].iloc[i]) 
    archivo1['id'].iloc[i]=str(archivo2[archivo2['Distancia']==archivo2['Distancia'].min()]['id'].iloc[0]) 

Кодовые бежит и дать мне ожидаемые результаты, тем не менее, первый файл имеет 7 миллионов и первый 70K файла, так что занимает 7 дней подряд. Может ли кто-нибудь помочь мне оптимизировать его?

Это образец из двух файлов:

Это файл 2, чтобы посмотреть:

File 2: 
id longitude latitude     
L10F10P1 -72.61521393 8.290479554 
L10F10P10 -72.61517542 8.290583772 
L10F10P100 -72.61481425 8.290812192 
L10F10P101 -72.61484522 8.290877898 
L10F10P102 -72.61488579 8.290968212 
L10F10P103 -72.61492075 8.291033898 
L10F10P104 -72.61495586 8.291095669 
L10F10P105 -72.61499304 8.291166076 
L10F10P106 -72.61503357 8.291235121 
L10F10P107 -72.61508271 8.291330912 
L10F10P108 -72.61516194 8.291456605 
L10F10P109 -72.61519939 8.291548893 
L10F10P11 -72.61522969 8.290676982 
L10F10P110 -72.61522794 8.291592503 
[76701 rows x 9 columns] 
File 1: 
latitude longitude 
8.318648471 -72.6132329 
8.318648678 -72.6134567 
8.318648971 -72.6133456 
8.318678421 -72.6138765 
8.319765345 -72.6137658 
[6877229 rows x 10 columns] 
+0

Может это помочь: http://stackoverflow.com/q/36843122/5276797 – IanS

+0

Спасибо, ваш код займет у меня 4 минуты на 100 записей, минуя 47 секунд. –

+0

Можете ли вы привести пример? – IanS

ответ

1

Без примера я не буду писать точный код, но предложения по улучшению построчно. Общая идея состоит в том, что apply, как правило, довольно медленный, поскольку он по существу является петлей за кулисами.


Это, конечно, медленно:

archivo1['dLat'] = (lat-archivo1['lat']).apply(deg2rad)/2 

Это будет лучше:

archivo1['dLat'] = (lat-archivo1['lat']) * math.pi/180/2 

Использование numpy функции, а не применять math функции также должны быть быстрее:

np.sin(archivo1['dLat'].values) 

вместо

archivo1['dLat'].apply(math.sin) 

values собственности дает вам доступ к нижележащему numpy массива. Аналогичным образом используйте np.sqrt.


np.multiply Затем используйте повторно на numpy массивов, рассчитанных выше, чтобы умножить их поэлементно. Вы можете назначить последний массив обратно в столбец DataFrame Distancia.


for цикла может быть улучшен путем определения функции, содержащей две строки внутри цикла, и используя apply, чтобы применить его к каждой строке в dataframe.


Наконец, используя argmin или idxmin должен быть быстрее, чем:

archivo2[archivo2['Distancia']==archivo2['Distancia'].min()] 

Поставив все вышеперечисленное вместе, вы должны увидеть довольно улучшение уже!

+0

спасибо, что это улучшает многое. –

+1

В примере 100 записей это сокращает время от 47 секунд до 21. Большое спасибо –

+0

Если вы все еще ищете улучшения, вы должны снова задать новый вопрос (с новым кодом). Он должен получать больше внимания, чем в пятницу днем, и, возможно, у кого-то будет совершенно новая идея, в отличие от постепенных улучшений, которые я предложил. Тем временем вы можете принять мой ответ, вы получите 2 репутации;) – IanS