我希望使用Geopandas / Shapely来完成相当于ArcPy
Generate Near Table的操作.我是Geopandas和Shapely的新手,并开发了一种有效的方法,但我想知道是否有更有效的方法.
我有两个点文件数据集 – Census Block Centroids和餐馆.我希望找到每个人口普查区块中心距离它最近的餐厅的距离.对于同一个餐厅而言,对于多个街区来说,最近的餐厅没有任何限制.
这对我来说有点复杂的原因是因为Geopandas Distance function根据索引计算元素,匹配.因此,我的一般方法是将Restaurants文件转换为多点文件,然后将blocks文件的索引设置为全部相同的值.然后,所有块质心和餐馆都具有相同的索引值.
import pandas as pd import geopandas as gpd from shapely.geometry import Polygon,Point,MultiPoint
现在阅读Block Centroid和Restaurant Shapefiles:
Blocks=gpd.read_file(BlockShp) Restaurants=gpd.read_file(RestaurantShp)
由于Geopandas距离函数按元素计算距离,我将Restaurant GeoSeries转换为MultiPoint GeoSeries:
RestMulti=gpd.GeoSeries(Restaurants.unary_union) RestMulti.crs=Restaurants.crs RestMulti.reset_index(drop=True)
然后我将Blocks的索引设置为等于0(与Restaurants多点相同的值)作为元素计算的解决方法.
Blocks.index=[0]*len(Blocks)
最后,我使用Geopandas距离函数计算每个Block质心到最近餐馆的距离.
Blocks['Distance']=Blocks.distance(RestMulti)
请提供有关如何改进这方面的任何建议.我并不喜欢使用Geopandas或Shapely,但我希望学习ArcPy的替代方案.
谢谢您的帮助!
解决方法
如果我正确理解您的问题,块和餐馆的尺寸可能会有很大差异.出于这个原因,尝试通过重建索引强制转换为表格格式可能是一种糟糕的方法.
我会绕过街区并获得到餐馆的最小距离(就像@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()
现在获取点到线的距离,并且只保存每个点的最小距离(请参阅下面的适用版本)
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更好,更符合你在熊猫中的表现:
def min_distance(point,lines): return lines.distance(point).min() df_points['min_dist_to_lines'] = df_points.geometry.apply(min_distance,df_lines)