当前位置: 首页 > 知识库问答 >
问题:

使用Geopandas计算到最近地物的距离

子车煌
2023-03-14

我希望使用Geopandas/Shapely实现ArcPy Generate Near表的等效功能。我对Geopandas和Shapely非常陌生,并且已经开发出一种有效的方法,但我想知道是否有更有效的方法。

我有两个点文件数据集——人口普查街区中心和餐馆。我在寻找每个人口普查街区形心到最近餐馆的距离。同一家餐厅是多个街区最近的餐厅,没有任何限制。

对我来说,这变得有点复杂的原因是因为Geopandas距离函数根据索引计算元素匹配。因此,我的一般方法是将餐馆文件转换为多点文件,然后将块文件的索引设置为相同的值。然后所有的块中心和餐馆都有相同的索引值。

import pandas as pd
import geopandas as gpd
from shapely.geometry import Polygon, Point, MultiPoint

现在读入块质心和餐厅形状文件:

Blocks=gpd.read_file(BlockShp)
Restaurants=gpd.read_file(RestaurantShp)

由于Geopandas distance函数按元素计算距离,因此我将餐厅GeoSeries转换为多点GeoSeries:

RestMulti=gpd.GeoSeries(Restaurants.unary_union)
RestMulti.crs=Restaurants.crs
RestMulti.reset_index(drop=True)

然后,我将块的索引设置为等于0(与餐厅多点相同的值),作为元素计算的工作。

Blocks.index=[0]*len(Blocks)

最后,我使用Geopandas距离函数计算每个街区质心到最近餐厅的距离。

Blocks['Distance']=Blocks.distance(RestMulti)

请就如何改进这方面的任何方面提出任何建议。我不习惯使用Geopandas或Shapely,但我想学习ArcPy的替代品。

谢谢你的帮助!

共有3个答案

缪晋
2023-03-14

您的代码缺少详细信息,args=(df\u行)

def min_distance(point, lines):
    return lines.distance(point).min()

df_points['min_dist_to_lines'] = df_points.geometry.apply(min_distance, args=(df_lines,))# Notice the change to this line
莫兴言
2023-03-14

我将使用两个不同维度的geopandas中的样本数据集来演示。

import geopandas as gpd

# read geodata for five nyc boroughs
gdf_nyc = gpd.read_file(gpd.datasets.get_path('nybb'))
# read geodata for international cities
gdf_cities = gpd.read_file(gpd.datasets.get_path('naturalearth_cities'))

# convert to a meter projection
gdf_nyc.to_crs(epsg=3857, inplace=True)
gdf_cities.to_crs(epsg=3857, inplace=True)

我们可以简单地将lambda函数应用于GeoSeries。例如,如果我们想获得每个NYC行政区(多边形)和最近的国际城市(点)之间的最小距离。我们可以做到以下几点:

gdf_nyc.geometry.apply(lambda x: gdf_cities.distance(x).min())

这将给我们

0    384422.953323
1    416185.725507
2    412520.308816
3    419511.323677
4    440292.945096
Name: geometry, dtype: float64

同样,如果我们想要每个国际城市和最近的纽约市行政区之间的最小距离。我们可以做到以下几点:

gdf_cities.geometry.apply(lambda x: gdf_nyc.distance(x).min())

这将给我们

0      9.592104e+06
1      9.601345e+06
2      9.316354e+06
3      8.996945e+06
4      2.614927e+07
           ...     
197    1.177410e+07
198    2.377188e+07
199    8.559704e+06
200    8.902146e+06
201    2.034579e+07
Name: geometry, Length: 202, dtype: float64

笔记:

  1. 在计算距离之前,将GeoDataFrame转换为笛卡尔投影。在本例中,我使用了epsg:3857,因此距离将以米为单位。如果使用椭球体(基于lon/lat)投影,结果将为度。首先转换投影,然后再进行其他操作,例如获取多边形的质心
  2. 两点之间只有一个距离。返回的最小距离。distance()方法在您想要获取点和线之间的距离时是有意义的。换句话说,。distance()方法可以计算任意两个地理对象之间的距离
  3. 当GeoDataFrame中有多个几何图形列时,请确保将lambda函数应用于所需的GeoSeries,并调用。距所需地理序列的距离()。在本例中,我直接从GeoDataFrame调用了该方法,因为它们都只有一个GeoSeries列

彭嘉赐
2023-03-14

如果我正确理解你的问题,街区和餐厅可能有非常不同的尺寸。出于这个原因,尝试通过重新编制索引强制转换为表格式可能是一种不好的方法。

我只需绕着街区走一圈,就能找到到餐馆的最短距离(正如@shongolo所建议的)。

我将更一般一点(因为我已经写下了这段代码)并计算点到线的距离,但是相同的代码应该适用于点到点或多边形到多边形。我将从点的GeoDataFrame开始,并创建一个新列,该列与直线的距离最小。

%matplotlib inline
import matplotlib.pyplot as plt
import shapely.geometry as geom
import numpy as np
import pandas as pd
import geopandas as gpd

lines = gpd.GeoSeries(
    [geom.LineString(((1.4, 3), (0, 0))),
        geom.LineString(((1.1, 2.), (0.1, 0.4))),
        geom.LineString(((-0.1, 3.), (1, 2.)))])

# 10 points
n  = 10
points = gpd.GeoSeries([geom.Point(x, y) for x, y in np.random.uniform(0, 3, (n, 2))])

# Put the points in a dataframe, with some other random column
df_points = gpd.GeoDataFrame(np.array([points, np.random.randn(n)]).T)
df_points.columns = ['Geometry', 'Property1']

points.plot()
lines.plot()

现在获取点到线的距离,并且只保存每个点的最小距离(请参阅下面的应用版本)

min_dist = np.empty(n)
for i, point in enumerate(points):
    min_dist[i] = np.min([point.distance(line) for line in lines])
df_points['min_dist_to_lines'] = min_dist
df_points.head(3)

    Geometry                                       Property1    min_dist_to_lines
0   POINT (0.2479424516236574 2.944916965334865)    2.621823    0.193293
1   POINT (1.465768457667432 2.605673714922998)     0.6074484   0.226353
2   POINT (2.831645235202689 1.125073838462032)     0.657191    1.940127

----编辑----

(摘自github的一期)使用apply更好,更符合您在pandas中的操作方式:

def min_distance(point, lines):
    return lines.distance(point).min()

df_points['min_dist_to_lines'] = df_points.geometry.apply(min_distance, df_lines)

编辑:至少从2019-10-04起,熊猫的变化似乎需要在最后一个代码块中使用中的args参数进行不同的输入。应用()

df_points['min_dist_to_lines'] = df_points.geometry.apply(min_distance, args=(df_lines,))
 类似资料:
  • 我有一个多边形类型的几何体,我正在计算一个点的最小距离可能在多边形几何体内部(由360个点组成,作为闭合几何体)或多边形几何体外部。使用postgis的ST_distance方法,当点在几何体外部时,我得到精确的距离,但如果点在几何体内部,则得到0作为距离,我想要与多边形几何体最近点的点之间的最小距离,无论该点位于几何体内部还是外部。

  • 我正在学习CLR中的一节,它描述了使用分而治之的方法,使用两点之间的欧几里德距离来找到最近的点对。 有一个问题,要求找到最近的点对之间的manhatten距离,使用类似的方法。但是,我不能把握两者之间的区别。以下是我能想到的: 3)递归到我们的点子集<=3为止(在这种情况下使用蛮力) 4)最小距离可以是从任何一个递归调用返回的距离--称它为D。 5)找到线“L”周围2D宽度内所有点,然后对于每个这

  • 问题内容: 该问题旨在作为规范的重复目标 给定两个阵列和形状和代表的名单维坐标, 找到最快的方法是: 每个点和每个点之间的形状距离 每个点中所有点的最近邻居的索引和距离 这些指数,以及距离在每一个点的中距离每一点的在 鉴于以下几组限制: 仅使用 使用任何包装 包括特殊情况: 是 在所有情况下,距离主要是指欧几里得距离,但是请随意强调允许其他距离计算的方法。 问题答案: 仅使用 天真的方法是: 但是

  • 问题内容: 我需要根据订单的要求交货日期来安排Postgres查询中的某些项目。因此,例如,该订单在星期一(例如20120319)有一个请求的交货,并且该订单需要在前一个工作日(20120316)进行准备。 关于最直接方法的想法?我愿意添加日期表。我认为有比使用大量case语句更好的方法:SELECT EXTRACT(DOW FROM TIMESTAMP‘2001-02-16 20:38:40’)

  • 这是我的第一个地理数据帧: 城市1 还有我的第二个地理数据框:City2: 我想第三个数据帧与最近的城市从城市1到城市2的距离像: 下面是我使用geodjango和dict的实际解决方案(但太长了): 以下是我的尝试: 这里: 问候

  • 问题内容: 我在用 python 2.7.12 Django 1.10.6 PostgreSQL 9.5.6 postGIS 2.2.2 第一个问题 我需要使用GeoDjango计算两点之间的距离。当我检查了 文档它说, GeoQuerySet.distance() 已被弃用,而使用 距离() 从 django.contrib.gis.db.models.functions 。 以下代码可以正常工