Reputation: 397
My question kind of builds on this one Fast Haversine Approximation (Python/Pandas)
Basically, that question asks how to compute the Haversine Distance. Mine is how do I calculate the Haversine Distance between consecutive rows for each Customer.
My dataset looks something like this dummy one (let's pretend those are real coordinates):
Customer Lat Lon
A 1 2
A 1 2
B 3 2
B 4 2
So here, I would get nothing in the first row, 0 in the second row, nothing again on the third because a new customer started and whatever the distance in km is between (3,2) and (4,2) in the fourth.
This works without the constraint of the customers:
def haversine(lat1, lon1, lat2, lon2, to_radians=True):
if to_radians:
lat1, lon1, lat2, lon2 = np.radians([lat1, lon1, lat2, lon2])
a = np.sin((lat2-lat1)/2.0)**2 + \
np.cos(lat1) * np.cos(lat2) * np.sin((lon2-lon1)/2.0)**2
return 6367 * 2 * np.arcsin(np.sqrt(a))
df=data_full
df['dist'] = \
haversine(df.Lon.shift(), df.Lat.shift(),
df.loc[1:, 'Lon'], df.loc[1:, 'Lat'])
But I can't tweak it to restart with each new customer. I've tried this:
def haversine(lat1, lon1, lat2, lon2, to_radians=True):
if to_radians:
lat1, lon1, lat2, lon2 = np.radians([lat1, lon1, lat2, lon2])
a = np.sin((lat2-lat1)/2.0)**2 + \
np.cos(lat1) * np.cos(lat2) * np.sin((lon2-lon1)/2.0)**2
return 6367 * 2 * np.arcsin(np.sqrt(a))
df=data_full
df['dist'] = \
df.groupby('Customer_id')['Lat','Lon'].apply(lambda df: haversine(df.Lon.shift(), df.Lat.shift(),
df.loc[1:, 'Lon'], df.loc[1:, 'Lat']))
Upvotes: 2
Views: 586
Reputation: 93141
I'll reuse the vectorized haversine_np
function from derricw's answer:
def haversine_np(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
All args must be of equal length.
"""
lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2
c = 2 * np.arcsin(np.sqrt(a))
km = 6367 * c
return km
def distance(x):
y = x.shift()
return haversine_np(x['Lat'], x['Lon'], y['Lat'], y['Lon']).fillna(0)
df['Distance'] = df.groupby('Customer').apply(distance).reset_index(level=0, drop=True)
Result:
Customer Lat Lon Distance
0 A 1 2 0.000000
1 A 1 2 0.000000
2 B 3 2 0.000000
3 B 4 2 111.057417
Upvotes: 3