2017-07-12 2 views
2

ich Pandas Datenrahmen my_df mit den folgenden Spalten:Von Pandas Datenrahmen zu Tupeln (für Haversine Modul)

id lat1 lon1 lat2 lon2 
1 45 0 41 3 
2 40 1 42 4 
3 42 2 37 1 

Grundsätzlich würde Ich mag folgendes tun:

import haversine 

haversine.haversine((45, 0), (41, 3)) # just to show syntax of haversine() 
> 507.20410687342115 

# what I'd like to do 
my_df["dist"] = haversine.haversine((my_df["lat1"], my_df["lon1"]),(my_df["lat2"], my_df["lon2"])) 

TypeError: cannot convert the series to < class 'float' >

Mit this habe ich Folgendes versucht:

my_df['dist'] = haversine.haversine(
     list(zip(*[my_df[['lat1','lon1']][c].values.tolist() for c in my_df[['lat1','lon1']]])) 
     , 
     list(zip(*[my_df[['lat2','lon2']][c].values.tolist() for c in my_df[['lat2','lon2']]])) 
     ) 

File "blabla\lib\site-packages\haversine__init__.py", line 20, in haversine lat1, lng1 = point1

ValueError: too many values to unpack (expected 2)

Irgendeine Idee von dem, was ich falsch mache/wie ich erreichen kann, was ich will?

+0

möglich dupe: https://stackoverflow.com/questions/25767596/vectorised-haversine-formula-with-a-pandas-dataframe – EdChum

Antwort

2

Verwenden apply mit axis=1:

my_df["dist"] = my_df.apply(lambda row : haversine.haversine((row["lat1"], row["lon1"]),(row["lat2"], row["lon2"])), axis=1) 

in jeder Zeile die Haversine Funktion aufzurufen, versteht die Funktion Skalarwerte, nicht Array wie Werte daher der Fehler. Indem Sie apply mit axis=1 aufrufen, iterieren Sie zeilenweise, sodass wir dann auf jeden Spaltenwert zugreifen und diese in der von der Methode erwarteten Form übergeben können.

Auch weiß ich nicht, was der Unterschied ist, aber es gibt eine vektorisiert version der Haversine Formel

2

Was ist ein vektorisiert Ansatz:

import pandas as pd 

# vectorized haversine function 
def haversine(lat1, lon1, lat2, lon2, to_radians=True, earth_radius=6371): 
    """ 
    slightly modified version: of http://stackoverflow.com/a/29546836/2901002 

    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees or in radians) 

    All (lat, lon) coordinates must have numeric dtypes and be of equal length. 

    """ 
    if to_radians: 
     lat1, lon1, lat2, lon2 = pd.np.radians([lat1, lon1, lat2, lon2]) 

    a = pd.np.sin((lat2-lat1)/2.0)**2 + \ 
     pd.np.cos(lat1) * pd.np.cos(lat2) * pd.np.sin((lon2-lon1)/2.0)**2 

    return earth_radius * 2 * pd.np.arcsin(np.sqrt(a)) 

Demo:

In [38]: df 
Out[38]: 
    id lat1 lon1 lat2 lon2 
0 1 45  0 41  3 
1 2 40  1 42  4 
2 3 42  2 37  1 

In [39]: df['dist'] = haversine(df.lat1, df.lon1, df.lat2, df.lon2) 

In [40]: df 
Out[40]: 
    id lat1 lon1 lat2 lon2  dist 
0 1 45  0 41  3 507.204107 
1 2 40  1 42  4 335.876312 
2 3 42  2 37  1 562.543582 
+0

'AttributeError: 'numpy.float64' Objekt hat kein Attribut 'radians' :( –

+0

@fmalaussena, vergewissere dich, dass du' np' nicht überschrieben hast - Alias ​​für 'numpy' mit einem' float64' Variablennamen. Wenn Sie nicht den "klassischen" numpy alias 'np' verwenden, können Sie' numpy.radians' oder 'pd.np.radians' verwenden – MaxU