使用Numpy和Pandas计算经纬度之间的距离

使用Numpy和Pandas计算经纬度之间的距离

在数据分析中,经纬度信息在不同的场景中都起到了关键的作用,如地理位置数据、旅游业、物流等。因此,经纬度之间的距离计算也成为了一个非常实用的功能,Numpy和Pandas是两个Python中非常流行的数据处理库,本文主要介绍使用Numpy和Pandas计算经纬度之间的距离。

阅读更多:Numpy 教程

经纬度换算公式

经纬度距离的计算是基于地球为一个近似椭圆体,我们可以利用经纬度换算公式来计算两点地理位置的距离。

  1. 海伦公式(Haversine Formula):

海伦公式用于计算大圆线上两点之间的距离,是最为经典和常用的计算方式。该公式是由16世纪的航海家约翰·海伦提出的,用于航海中计算船航行的距离。

公式如下:

d=2rarcsinsin2φ2φ12+cosφ1cosφ2sin2λ2λ12d=2r\arcsin\sqrt{\sin^2\frac{\varphi_2-\varphi_1}{2}+\cos\varphi_1\cos\varphi_2\sin^2\frac{\lambda_2-\lambda_1}{2}}

其中,rr为地球半径(单位为千米),φ1\varphi_1,λ1\lambda_1,φ2\varphi_2,λ2\lambda_2分别表示两点的经度和纬度。

Python代码实现:

import math

def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)
    """
    # 将十进制转为弧度
    lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
    # haversine公式
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
    c = 2 * math.asin(math.sqrt(a)) 
    r = 6371 # 地球平均半径,单位为公里
    return c*r
Python
  1. vicenty公式(适用于近距离):

Vicenty公式是一种更为精确的公式,适用于计算两点之间的精确距离,实际上是近似于解析方法。由于不涉及任何开方等不能被唯一解析解决的表达式,因此该公式是非常高效的。

公式如下:

d=atan(cos2b2sin2(λ2λ1)+[cosb1sinb2sinb1cosb2cos(λ2λ1)]2sinb1sinb2+cosb1cosb2cos(λ2λ1))d = a\tan \bigg(\dfrac{\sqrt{\cos ^2b_2\sin ^2(\lambda_2 – \lambda_1) + [\cos b_1\sin b_2 – \sin b_1\cos b_2 \cos (\lambda_2-\lambda_1)]^2}}{\sin b_1\sin b_2 + \cos b_1\cos b_2\cos(\lambda_2-\lambda_1)}\bigg)

其中,aa为长轴,bb为短轴,一般使用WGS-84椭球体,b1b_1,λ1\lambda_1,b2b_2,λ2\lambda_2分别表示两点的经度和纬度。

Python代码实现:

def vicenty(lon1, lat1, lon2, lat2):
    '''
    Calculate the geodesic distance (in meters)
    between any two points on the Earth's surface
    '''
    from math import atan2, cos, sin, sqrt, pi
    # WGS-84 ellipsoid parameters
    a = 6378137.0
    b = 6356752.3142
    f = (a - b) /a  # flattening
    L = abs(lon2 - lon1)
    if L > pi:
        L = 2*pi - L
    U1 = atan2(b, a*sin(lat1))
    U2 = atan2(b, a*sin(lat2))
    sinU1 = sin(U1)
    cosU1 = cos(U1)
    sinU2 = sin(U2)
    cosU2 = cos(U2)
    lamb = L
    iterlimit = 100
    while iterlimit > 0:
        sinlamb = sin(lamb)
        coslamb = cos(lamb)
        sinSigma = sqrt((cosU2*sinlamb)**2 + 
                        (cosU1*sinU2 - sinU1*cosU2*coslamb)**2)
        if sinSigma == 0:
            return 0  # co-incident points
        cosSigma = sinU1*sinU2 + cosU1*cosU2*coslamb
        sigma = atan2(sinSigma, cosSigma)
        alpha = asin(cosU1*cosU2*sinlamb / sinSigma)
        cosSqAlpha = cos(alpha)**2
        cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha
        C = f*cosSqAlpha*(4 + f*(4 - 3*cosSqAlpha))/16
        lambPrev = lamb
        lamb = L + (1 - C)*f*sin(alpha)*(sigma + 
                                          C*sinSigma*(cos2SigmaM + 
                                                      C*cosSigma*(-1 + 2*cos2SigmaM**2)))
        iterlimit -= 1
        if iterlimit == 0:
            return 0  # formula failed to converge
    uSq = cosSqAlpha*(a**2 - b**2)/b**2
    A = 1 + uSq/16384*(4096 + uSq*(-768 + uSq*(320 - 175*uSq)))
    B = uSq/1024 * (256 + uSq*(-128 + uSq*(74 - 47*uSq)))
    deltaSigma = B*sinSigma*(cos2SigmaM + B/4 * 
                            (cosSigma*(-1 + 2*cos2SigmaM**2) - B/6*cos2SigmaM*(-3 + 4*sinSigma**2)*
                             (-3 + 4*cos2SigmaM**2)))
    s = b*A*(sigma - deltaSigma)
    return s
Python

Numpy和Pandas实现

  1. Numpy实现

我们可以利用Numpy对计算海伦公式的函数进行封装,从而可以更加方便的进行实现,在进行计算前,先将经纬度转换为弧度制。

Python代码实现:

import numpy as np

def distance_numpy(lon1, lat1, lon2, lat2):
    """
        Compute the distance between successive rows using numpy
        Use the Haversine formula to compute the distance between each pair of (lat, long) points.
    """
    R = 6371 # Earth radius in km
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
    c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1-a)) 
    distance = R * c
    return distance
Python
  1. Pandas实现

Pandas是另一个非常流行的Python数据处理库,它提供了DataFrame和Series等高效的数据结构和操作,可以方便地处理大量数据。Pandas提供了apply函数,可以利用其进行距离计算。

Python代码实现:

import pandas as pd

def distance_pandas(df):
    """
    Compute the distance between successive rows using pandas
    """
    R = 6371 # Earth radius in km
    dlat = df['latitude'].shift(-1) - df['latitude']
    dlon = df['longitude'].shift(-1) - df['longitude']
    a = pd.np.sin(dlat/2)**2 + pd.np.cos(df['latitude']) * pd.np.cos(df['latitude'].shift(-1)) * pd.np.sin(dlon/2)**2
    c = 2 * pd.np.arctan2(pd.np.sqrt(a), pd.np.sqrt(1-a))
    distance = R * c
    return distance
Python

总结

本文介绍了Numpy和Pandas两个Python数据处理库的经纬度计算方法,我们可以根据需要选择相应的方法来计算两个经纬度之间的距离。在实际应用中,需要注意采用合适的地球椭球体模型进行计算。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册