通过循环将多边形内的所有点作为值添加到字典对象

时间:2019-09-17 19:08:56

标签: python geopandas shapely

我有一个连续13个多边形的shapefile,以及一个与多边形相同的普通区域中的〜33K地址的地址列表。我通过Google地理编码API对地址进行了地理编码,现在尝试查看哪些地址位于哪个多边形中,并按多边形名称分组。

我可以一次使一个多边形工作,但是我在循环中丢失了一些东西。

到目前为止,我在这里:

# Import shapefile and convert coordinates to match address file
sf = gpd.read_file(MY_SHAPEFILE)
sf_geo = sf.to_crs(epsg=4326)

# Import geocoded addresses
address_data = pd.read_csv(ADDRESS_FILE)
# Create points from lat/lon coordinate columns in address file
geometry_points = [Point(xy) for xy in zip(address_data['longitude'], 
                   address_data['latitude'])]

# Create object from one of the Polygons
p = sf_geo.iloc[0].geometry

i = 0
for point in geometry_points:
    if point.within(p):
        i += 1
        print(i)
    else:
        continue   

上面的方法在所有多边形上都可以正常工作。但是,我真正希望的是能够更新dict,其中键是多边形的实际名称,而值是该多边形内匹配的所有点。然后,我可以将多边形名称添加到地址列表中。

# Extract the names of each polygon
area_names = list(sf_geo['Name'])
# Create dict of polygon name : geometry
for r in sf_geo:
    shape_dict = dict(zip(area_names, sf['geometry']))

# Initialize empty dict to hold list of all addresses within each polygon
polygon_contains_dict = {k: [] for k in area_names}

上面在打印时创建了这种格式的字典:

{'10 ppm': <shapely.geometry.polygon.Polygon object at 0x7fea194225d0>, '20 ppm': <shapely.geometry.polygon.Polygon object at 0x7fe9f2e23590>, ETC}

以及键与shape_dict相同的dict,但值是空列表。

我正在使用以下方法尝试遍历shape_dict中的所有键以及从地址创建的所有点,并更新一个列表,该列表随后成为polygon_contains_dict中每个键的值:

for key, value in shape_dict.items():
    contains_list = []
    not_contained = []
    for point in geometry_points:
        if point.within(value):
            contains_list.append(point)
        else:
            not_contained.append(point)
    polygon_contains_dict[key] = contains_list

但是,这既不向contains_list也不添加任何多边形(显然)polygon_contains_dict中的值。所有积分都被转储到not_contained中。

由于我知道点实际上在某些多边形内,所以我知道我缺少了一些东西。 geometry_points中的所有点都是Point对象,shape_dict.values中的所有多边形都是Polygon对象。

我想念什么?感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我建议您避免完全循环,并为坐标创建第二个geopandas数据框并处理数据,然后进行空间连接:

# Import geocoded addresses
address_data = pd.read_csv(ADDRESS_FILE)
# Create points from lat/lon coordinate columns in address file
geometry_points = [Point(xy) for xy in zip(address_data['longitude'], 
               address_data['latitude'])]
address_gpd=gpd.GeoDataFrame(address_data,crs={'init': 'epsg:4326'},geometry=geometry_points) # second geopandas frame

# inner spatial join with shapefile 
df=gpd.sjoin(sf_geo,address_gpd,how='inner',op='intersects') 

df数据框现在将具有每个多边形内的所有地址,然后“更新dict,其中键是多边形的实际名称,而值是该多边形内所有匹配的点”您可以使用groupby和to_dict

df=df.groupby(['Name'])['address'].apply(list)
polygon_contains_dict=df.to_dict('index') 

我假设您的地址的列名称为address,因此请更改(如果不是这样的话)。

有关空间连接的更多信息,请参见geopandas docs on merging data