AJG*_*519 10 python pandas shapely geopandas
我希望使用Geopandas/Shapely 做相当于ArcPy Generate Near Table的工作.我是Geopandas和Shapely的新手,并开发了一种有效的方法,但我想知道是否有更有效的方法.
我有两个点文件数据集 - Census Block Centroids和餐馆.我希望找到每个人口普查区块中心距离它最近的餐厅的距离.对于同一个餐厅而言,对于多个街区来说,最近的餐厅没有任何限制.
这对我来说有点复杂的原因是因为Geopandas距离函数根据索引计算元素,匹配.因此,我的一般方法是将Restaurants文件转换为多点文件,然后将blocks文件的索引设置为全部相同的值.然后,所有块质心和餐馆都具有相同的索引值.
import pandas as pd
import geopandas as gpd
from shapely.geometry import Polygon, Point, MultiPoint
Run Code Online (Sandbox Code Playgroud)
现在阅读Block Centroid和Restaurant Shapefiles:
Blocks=gpd.read_file(BlockShp)
Restaurants=gpd.read_file(RestaurantShp)
Run Code Online (Sandbox Code Playgroud)
由于Geopandas距离函数按元素计算距离,我将Restaurant GeoSeries转换为MultiPoint GeoSeries:
RestMulti=gpd.GeoSeries(Restaurants.unary_union)
RestMulti.crs=Restaurants.crs
RestMulti.reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)
然后我将Blocks的索引设置为等于0(与Restaurants多点相同的值)作为元素计算的解决方法.
Blocks.index=[0]*len(Blocks)
Run Code Online (Sandbox Code Playgroud)
最后,我使用Geopandas距离函数计算每个Block质心到最近餐馆的距离.
Blocks['Distance']=Blocks.distance(RestMulti)
Run Code Online (Sandbox Code Playgroud)
请提供有关如何改进这方面的任何建议.我并不喜欢使用Geopandas或Shapely,但我希望学习ArcPy的替代方案.
谢谢您的帮助!
cd9*_*d98 13
如果我正确理解您的问题,块和餐馆的尺寸可能会有很大差异.出于这个原因,尝试通过重建索引强制转换为表格格式可能是一种糟糕的方法.
我会绕过街区并获得到餐馆的最小距离(就像@shongololo建议的那样).
我会稍微更通用一些(因为我已经记下了这段代码)并且在点与线之间做了一段距离,但是相同的代码应该从点到点或从多边形到多边形.我将从一个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()
Run Code Online (Sandbox Code Playgroud)
现在获取点到线的距离,并且只保存每个点的最小距离(请参阅下面的适用版本)
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)
Run Code Online (Sandbox Code Playgroud)
这使
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
Run Code Online (Sandbox Code Playgroud)
----编辑----
(取自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)
Run Code Online (Sandbox Code Playgroud)
我将使用 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)
Run Code Online (Sandbox Code Playgroud)
我们可以简单地将 lambda 函数应用于 GeoSeries。例如,如果我们想获得纽约市每个行政区(多边形)与其最近的国际城市(点)之间的最小距离。我们可以执行以下操作:
gdf_nyc.geometry.apply(lambda x: gdf_cities.distance(x).min())
Run Code Online (Sandbox Code Playgroud)
这会给我们
0 384422.953323
1 416185.725507
2 412520.308816
3 419511.323677
4 440292.945096
Name: geometry, dtype: float64
Run Code Online (Sandbox Code Playgroud)
同样,如果我们想要每个国际城市与其最近的纽约市行政区之间的最小距离。我们可以执行以下操作:
0 384422.953323
1 416185.725507
2 412520.308816
3 419511.323677
4 440292.945096
Name: geometry, dtype: float64
Run Code Online (Sandbox Code Playgroud)
这会给我们
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
Run Code Online (Sandbox Code Playgroud)
笔记:
epsg:3857,因此距离以米为单位。如果您使用椭圆体(基于经度/纬度)投影,结果将为度数。首先转换投影,然后再进行其他操作,例如获取多边形的质心。.distance()当您想要获取点和线之间的距离时,该方法返回的最小距离是有意义的。换句话说,.distance()该方法可以计算任意两个地理对象之间的距离。geometry当GeoDataFrame 中有多个列时,请确保将 lambda 函数应用于所需的 GeoSeries,并.distance()从所需的 GeoSeries 中调用该方法。在示例中,我直接从 GeoDataFrame 调用该方法,因为它们都只有一个 GeoSeries 列。| 归档时间: |
|
| 查看次数: |
11256 次 |
| 最近记录: |