Skip to content

Haversine Distance

Great-circle (haversine) distance between two lat/lon column pairs.

Spherical-Earth approximation: a straight-line distance, not a driving distance. The backend must support trigonometric functions.

haversine_distance(lat_col, lon_col, target_lat_col, target_lon_col, radius=6371.0)

Compute the Haversine distance between two sets of latitude and longitude columns.

Parameters:

Name Type Description Default
lat_col Column

Source latitudes in degrees.

required
lon_col Column

Source longitudes in degrees.

required
target_lat_col Column

Target latitudes in degrees.

required
target_lon_col Column

Target longitudes in degrees.

required
radius float

Earth's radius in the desired output units; defaults to 6371.0 km.

6371.0

Returns:

Type Description
Column

ibis.Column: Lazy expression for each source/target pair's distance, in radius units.

Source code in openretailscience/analysis/haversine.py
def haversine_distance(
    lat_col: ibis.Column,
    lon_col: ibis.Column,
    target_lat_col: ibis.Column,
    target_lon_col: ibis.Column,
    radius: float = 6371.0,
) -> ibis.Column:
    """Compute the Haversine distance between two sets of latitude and longitude columns.

    Args:
        lat_col (ibis.Column): Source latitudes in degrees.
        lon_col (ibis.Column): Source longitudes in degrees.
        target_lat_col (ibis.Column): Target latitudes in degrees.
        target_lon_col (ibis.Column): Target longitudes in degrees.
        radius (float): Earth's radius in the desired output units; defaults to 6371.0 km.

    Returns:
        ibis.Column: Lazy expression for each source/target pair's distance, in ``radius`` units.
    """
    lat1_rad = lat_col.radians()
    lat2_rad = target_lat_col.radians()
    delta_lat = (target_lat_col - lat_col).radians()
    delta_lon = (target_lon_col - lon_col).radians()

    a = (delta_lat / 2).sin().pow(2) + lat1_rad.cos() * lat2_rad.cos() * (delta_lon / 2).sin().pow(2)
    c = 2 * a.sqrt().asin()

    return radius * c