如何填充用 geopandas 溶解地理数据框时创建的多边形中的孔?
How to fill holes in Multi-polygons created when dissolving geodataframe with geopandas?
我的目标是绘制 MSOA(英国的连续地理单位)簇的边界,我已经从 here 下载了 MSOA 边界的 shapefile。然后我添加一列簇标签并使用 geopandas 溶解。
df.dissolve(by='label', aggfunc='sum')
当我使用 Folium 绘图时,有多个内孔,如附图所示。我如何删除这些?
#creates map
m = folium.Map([54.5,-3],zoom_start=6.8,tiles='cartodbpositron')
#makes boundaries plot
Boundaries = folium.GeoJson(
df,
name='Boundaries',
style_function = lambda x: {
'color': 'black',
'weight': 3,
'fillOpacity': 0
}).add_to(m)
m
万一有人遇到同样的问题,我找到了一个网站,您可以从该网站上载、简化和导出名为 mapshaper 的形状文件,这成功地将我的边界简化为所需的形式。
这有望帮助您仅使用 geopandas 来组织您的多边形。您可以使用以下函数覆盖几何体。额外处理用于保留或减少 MultiPolygons。我想 MapShaper 会发生非常相似的事情,但这样您就不需要进行额外的处理。
from shapely.geometry import MultiPolygon, Polygon
def remove_interiors(poly):
"""
Close polygon holes by limitation to the exterior ring.
Arguments
---------
poly: shapely.geometry.Polygon
Input shapely Polygon
Returns
---------
Polygon without any interior holes
"""
if poly.interiors:
return Polygon(list(poly.exterior.coords))
else:
return poly
def pop_largest(gs):
"""
Pop the largest polygon off of a GeoSeries
Arguments
---------
gs: geopandas.GeoSeries
Geoseries of Polygon or MultiPolygon objects
Returns
---------
Largest Polygon in a Geoseries
"""
geoms = [g.area for g in gs]
return geoms.pop(geoms.index(max(geoms)))
def close_holes(geom):
"""
Remove holes in a polygon geometry
Arguments
---------
gseries: geopandas.GeoSeries
Geoseries of Polygon or MultiPolygon objects
Returns
---------
Largest Polygon in a Geoseries
"""
if isinstance(geom, MultiPolygon):
ser = gpd.GeoSeries([remove_interiors(g) for g in geom])
big = pop_largest(ser)
outers = ser.loc[~ser.within(big)].tolist()
if outers:
return MultiPolygon([big] + outers)
return Polygon(big)
if isinstance(geom, Polygon):
return remove_interiors(geom)
df.geometry = df.geometry.apply(lambda p: close_holes(p))
我的目标是绘制 MSOA(英国的连续地理单位)簇的边界,我已经从 here 下载了 MSOA 边界的 shapefile。然后我添加一列簇标签并使用 geopandas 溶解。
df.dissolve(by='label', aggfunc='sum')
当我使用 Folium 绘图时,有多个内孔,如附图所示。我如何删除这些?
#creates map
m = folium.Map([54.5,-3],zoom_start=6.8,tiles='cartodbpositron')
#makes boundaries plot
Boundaries = folium.GeoJson(
df,
name='Boundaries',
style_function = lambda x: {
'color': 'black',
'weight': 3,
'fillOpacity': 0
}).add_to(m)
m
万一有人遇到同样的问题,我找到了一个网站,您可以从该网站上载、简化和导出名为 mapshaper 的形状文件,这成功地将我的边界简化为所需的形式。
这有望帮助您仅使用 geopandas 来组织您的多边形。您可以使用以下函数覆盖几何体。额外处理用于保留或减少 MultiPolygons。我想 MapShaper 会发生非常相似的事情,但这样您就不需要进行额外的处理。
from shapely.geometry import MultiPolygon, Polygon
def remove_interiors(poly):
"""
Close polygon holes by limitation to the exterior ring.
Arguments
---------
poly: shapely.geometry.Polygon
Input shapely Polygon
Returns
---------
Polygon without any interior holes
"""
if poly.interiors:
return Polygon(list(poly.exterior.coords))
else:
return poly
def pop_largest(gs):
"""
Pop the largest polygon off of a GeoSeries
Arguments
---------
gs: geopandas.GeoSeries
Geoseries of Polygon or MultiPolygon objects
Returns
---------
Largest Polygon in a Geoseries
"""
geoms = [g.area for g in gs]
return geoms.pop(geoms.index(max(geoms)))
def close_holes(geom):
"""
Remove holes in a polygon geometry
Arguments
---------
gseries: geopandas.GeoSeries
Geoseries of Polygon or MultiPolygon objects
Returns
---------
Largest Polygon in a Geoseries
"""
if isinstance(geom, MultiPolygon):
ser = gpd.GeoSeries([remove_interiors(g) for g in geom])
big = pop_largest(ser)
outers = ser.loc[~ser.within(big)].tolist()
if outers:
return MultiPolygon([big] + outers)
return Polygon(big)
if isinstance(geom, Polygon):
return remove_interiors(geom)
df.geometry = df.geometry.apply(lambda p: close_holes(p))