2017-10-02 97 views
1

각 데이터에는 위도와 경도 데이터가 포함 된 df1df2의 두 데이터 프레임이 있습니다. df1의 각 관찰에 대해 haversine 함수를 사용하여 각 점 사이의 거리를 df2에 계산하고 싶습니다. 두 가지 접근 방식을 시도했지만 성능이 더 큰 데이터 세트에서 문제가됩니다.두 데이터 프레임 간 Haversine 거리 계산

In [1]: import pandas as pd 
     import numpy as np 
     from haversine import haversine 

In [2]: df1 = pd.DataFrame({'lat_long': [(25.99550273, 179.18526021), (76.24387873, -34.21956936), (-51.43773064, -113.93795667)]}) 
     df2 = pd.DataFrame({'lat_long': [(22.89956242, 107.04009984), (-80.25375578, -92.05425401), (-0.81621289, -147.26962084), (0,0)]}) 

In [3]: # method 1: iterate through rows 
     for i in df1['lat_long']: 
      for j in df2['lat_long']: 
       print(haversine(i,j)) 

7215.01729234 
12830.1178484 
4673.37638582 
17123.1981646 
8678.49300206 
17721.004245 
10690.0998826 
8746.62635254 
15294.1258757 
3303.30690512 
6434.34272913 
11636.6462421 

In [4]: # method 2: create one dataframe and then perform calculation 
     df1_dup = df1.append([df1]*(len(df2)-1), ignore_index=True) 
     df2_dup = df2.append([df2]*(len(df1)-1), ignore_index=True) 
     df = pd.DataFrame({'lat_long_df1': df1_dup.sort_values('lat_long')['lat_long'],'lat_long_df2': df2_dup['lat_long']}) 
     print(df.apply(lambda x: haversine(x['lat_long_df1'], x['lat_long_df2']), axis=1)) 

0  7215.017292 
1  17721.004245 
2  6434.342729 
3  17123.198165 
4  8678.493002 
5  3303.306905 
6  4673.376386 
7  8746.626353 
8  15294.125876 
9  12830.117848 
10 10690.099883 
11 11636.646242 
dtype: float64 

훨씬 더 큰 데이터 프레임에서 더 잘 작동하는 대체 방법에 대한 아이디어가 있습니까?

+0

'df1'의 각 점과 'df2'의 각 점 사이의 거리를 계산 하시겠습니까? a.k.a. 'df1'의 요소와 'df2'의 요소 사이에 쌍으로 거리를 계산합니까? 거리가 정확해야합니까, 아니면 적어도 몇 가지 요소에 대한 haversine보다 간단한 공식으로 벗어날 수 있습니까? 모든 쌍을 처리해야합니까? 근본적으로, 당신이 아마 더 깨끗한 구문으로 이것을 할 수는 있지만, 나는 당신이 어떻게 든 계산의 일부를 건너 뛰지 않는 한, _performance_를 많이 향상시킬 것으로 기대하지 않을 것입니다. –

+2

다음은 관련 질문입니다. https://stackoverflow.com/questions/29545704/fast-haversine-approximation-python-pandas –

+0

@DavidZ 네, 쌍 거리가 필요합니다. 눈에 띄는 성능 향상을 가져 오면 거리의 측면에서 정밀도를 희생 할 수 있습니다. –

답변

1

좀 더 성능이 좋은 병합을 찾고 있다면, 당신은 십자가 대리 열을 가입 할 수 있습니다

temp = df1.assign(A=1).merge(df2.assign(A=1), on='A').drop('A', 1) 
temp 
         lat_long_x     lat_long_y 
0  (25.99550273, 179.18526021) (22.89956242, 107.04009984) 
1  (25.99550273, 179.18526021) (-80.25375578, -92.05425401) 
2  (25.99550273, 179.18526021) (-0.81621289, -147.26962084) 
3  (25.99550273, 179.18526021)      (0, 0) 
4  (76.24387873, -34.21956936) (22.89956242, 107.04009984) 
5  (76.24387873, -34.21956936) (-80.25375578, -92.05425401) 
6  (76.24387873, -34.21956936) (-0.81621289, -147.26962084) 
7  (76.24387873, -34.21956936)      (0, 0) 
8 (-51.43773064, -113.93795667) (22.89956242, 107.04009984) 
9 (-51.43773064, -113.93795667) (-80.25375578, -92.05425401) 
10 (-51.43773064, -113.93795667) (-0.81621289, -147.26962084) 
11 (-51.43773064, -113.93795667)      (0, 0) 

temp.apply(lambda x: haversine(x['lat_long_x'], x['lat_long_y']), 1) 
0  7215.017292 
1  12830.117848 
2  4673.376386 
3  17123.198165 
4  8678.493002 
5  17721.004245 
6  10690.099883 
7  8746.626353 
8  15294.125876 
9  3303.306905 
10  6434.342729 
11 11636.646242 
dtype: float64 

당신은 좋은 속도 향상을 위해 this question에서 답으로 확대됨에 병합을 결합 할 수 있습니다. 또한 위/긴 데이터를 별도의 열에 보관하는 것을 고려해야합니다.