微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

获取两个 geopandas 数据框几何点之间的距离

如何解决获取两个 geopandas 数据框几何点之间的距离

我第一次使用空间数据。我必须比较两个具有经纬度细节的数据帧。我已将两者都转换为 GeoPandas 数据框。

import pandas as pd
from pandas import DataFrame
import geopandas as gpd
from neighbors import nearest_neighbor


df = pd.DataFrame([[1973,22.525158,88.330775],[1976,72.85136,19.10840],[898,91.78523,26.15012]],columns=['id','lat','long'])
gdf1 = gpd.GeoDataFrame(df,geometry=gpd.points_from_xy(df.long,df.lat))

df2 = pd.DataFrame([['06c979eaa59f',29.873870,76.965620],['19aedbb2e743',20.087574,76.180045],['5060a3931a43',31.289770,75.572340]],'lon']) 
gdf2 = gpd.GeoDataFrame(df2,geometry=gpd.points_from_xy(df2.lon,df2.lat))

我的 DF1 有 100 万行,而 df2 有大约 7000 行。我正在尝试为 DF1 中的每条记录从 DF2 获取最近的邻居。

我尝试了两种方法。两者都运行得非常快,结果可行。但是,它们并不准确。

方法一:

Please check this link

在此页面中,我使用了 sklearn.neighbors 中的最近邻方法。这将返回以米为单位的结果。但是,当我从两个数据帧手动检查经纬度之间的距离时,我总是发现最近的邻居返回距离的 1/4。

比如上面的方法返回的距离是125米,google map和https://www.geodatasource.com/distance-calculator都返回500米左右的距离。距离的差异一直在返回结果的4倍左右波动。

方法二:

在第二种方法中,我遵循了 gis.stackexchange.com 中给出的代码

https://gis.stackexchange.com/questions/222315/geopandas-find-nearest-point-in-other-dataframe

import itertools
from operator import itemgetter

import geopandas as gpd
import numpy as np
import pandas as pd

from scipy.spatial import cKDTree
from shapely.geometry import Point,Linestring

df = pd.DataFrame([[1973,df2.lat))

在这里,我用自己的数据框替换了 gpd1 和 gpd2。

def ckdnearest(gdfA,gdfB,gdfB_cols=['id']):
    # resetting the index of gdfA and gdfB here.
    gdfA = gdfA.reset_index(drop=True)
    gdfB = gdfB.reset_index(drop=True)
    A = np.concatenate(
        [np.array(geom.coords) for geom in gdfA.geometry.to_list()])
    B = [np.array(geom.coords) for geom in gdfB.geometry.to_list()]
    B_ix = tuple(itertools.chain.from_iterable(
        [itertools.repeat(i,x) for i,x in enumerate(list(map(len,B)))]))
    B = np.concatenate(B)
    ckd_tree = cKDTree(B)
    dist,idx = ckd_tree.query(A,k=1)
    idx = itemgetter(*idx)(B_ix)
    gdf = pd.concat(
        [gdfA,gdfB.loc[idx,gdfB_cols].reset_index(drop=True),pd.Series(dist,name='dist')],axis=1)
    return gdf

c = ckdnearest(gdf1,gdf2)

上面的运行速度非常快,并返回结果。然而,返回的距离值至少比我得到的低 100 倍。

乘数:107.655914

enter image description here

在上面的excel图片中,第一列是python返回的结果,第二列是上面给出的同一个网站返回的结果。虽然结果中的这些近似值让我开始了,但我想要准确的结果。如何比较上面给出的两个数据框并获得 DF1 中每一行最准确的最近距离。

解决方法

处理空间数据时,您应该注意点坐标是从球体投影到平面中的。经纬度点之间的墨卡托投影距离以度为单位,而不是米。并且转换取决于点的纬度,因为赤道上的 1 度将比高纬度的 1 度小。

您可以查看此讨论以了解此问题的可能解决方案: https://gis.stackexchange.com/questions/293310/how-to-use-geoseries-distance-to-get-the-right-answer

举个例子,一种可能性是您将地理数据框转换为覆盖您所在地区的 UTM 投影。例如,比利时与 UTM 区域 31N EPSG:32631 相交。 墨卡托投影有一个 epsg 代码 EPSG:4326。要转换 GeoDataFrame/GeoSeries,您需要在创建时提供 CRS:

s = gpd.GeoSeries(points,crs=4326)

其中 points 是 shapely.geometry.Point 的列表

然后转换为给定的 UTM:

s_utm = s.to_crs(epsg=32631)

现在您要计算的 s_utm 中点之间的距离将以米为单位。

但是,您需要确保您的积分落入给定的 UTM 区域,否则结果将不准确。 我链接的答案提出了其他可能也有效并且可以应用于整个点集合的方法。

您也可以尝试转换为 EPSG 32663(WGS 84 / World Equidistant Cylindrical),它应该可以保持距离。

另一种选择是使用 geopy,它允许使用 geopy.geodesic.distance 计算测地距离

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。