[英]Calculate length of all segments in polygon using geopandas
我有一个我想解决的小问题,我到处寻找答案。 我找不到它似乎很奇怪,但它可能只是我。
所以,我有这个 dataframe
df=
id x_zone y_zone
0 A1 65.422080 48.147850
1 A1 46.635708 51.165745
2 A1 46.597984 47.657444
3 A1 68.477700 44.073700
4 A3 46.635708 54.108190
5 A3 46.635708 51.844770
6 A3 63.309560 48.826878
7 A3 62.215572 54.108190
我将其转换为geopandas
dataframe:
df_geometry = gpd.GeoDataFrame(geometry=df.groupby('id').apply(
lambda g: Polygon(gpd.points_from_xy(g['x_zone'], g['y_zone']))))
df_geometry = df_geometry.reset_index()
print(df_geometry)
返回:
id geometry
A1 POLYGON ((65.42208 48.14785, 46.63571 51.16575...
A3 POLYGON ((46.63571 54.10819, 46.63571 51.84477...
我可以计算面积和周长:
df_geometry["area"] = df_geometry['geometry'].area
df_geometry["perimeter"] = df_geometry['geometry'].length
这使:
id geometry area perimeter
0 A1 POLYGON ((65.42208 48.14785, 46.63571 51.16575... 72.106390 49.799695
1 A3 POLYGON ((46.63571 54.10819, 46.63571 51.84477... 60.011026 40.181476
现在,我的问题的核心是:如果可以计算长度,那么肯定正在计算多边形的每一段的长度。 我怎样才能找回这个?
我知道对于非常复杂的多边形(例如国家地图,这可能是存储问题)。 有人有想法吗?
这是可运行的代码,显示了创建包含所需段长度的 dataframe 的所有步骤。
from io import StringIO
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point, Polygon
import numpy as np
dats_str = """index id x_zone y_zone
0 A1 65.422080 48.147850
1 A1 46.635708 51.165745
2 A1 46.597984 47.657444
3 A1 68.477700 44.073700
4 A3 46.635708 54.108190
5 A3 46.635708 51.844770
6 A3 63.309560 48.826878
7 A3 62.215572 54.108190"""
# read the string, convert to dataframe
df1 = pd.read_csv(StringIO(dats_str), sep='\s+', index_col='index') #good for space/s separation
gdf = gpd.GeoDataFrame(geometry=df1.groupby('id')
.apply(lambda g: Polygon(gpd.points_from_xy(g['x_zone'], g['y_zone']))))
gdf = gdf.reset_index() #bring `id` to `column` status
# Facts about polygon outer vertices
# - first vertex is the same as the last
# - to get segments, ignore zero-th point (use it as from_point in next row)
# create basic lists for creation of new dataframe
indx = [] # for A1, A3
sequ = [] # for seg order
pxy0 = [] # from-point
pxy1 = [] # to-point
for ix,geom in zip(gdf.id, gdf.geometry):
num_pts = len(geom.exterior.xy[0])
#print(ix, "Num points:", num_pts)
old_xy = []
for inx, (x,y) in enumerate(zip(geom.exterior.xy[0],geom.exterior.xy[1])):
if (inx==0):
# first vertex is the same as the last
pass
else:
indx.append(ix)
sequ.append(inx)
pxy0.append(Point(old_xy))
pxy1.append(Point(x,y))
old_xy = (x,y)
# Create new geodataframe
pgon_segs = gpd.GeoDataFrame({"poly_id": indx,
"vertex_id": sequ,
"fr_point": pxy0,
"to_point": pxy1}, geometry="to_point")
# Compute segment lengths
# Note: seg length is Euclidean distance, ***not geographic***
pgon_segs["seg_length"] = pgon_segs.apply(lambda row: row.fr_point.distance(row.to_point), axis=1)
pgon_segs
的内容:
poly_id vertex_id fr_point to_point seg_length
0 A1 1 POINT (65.42207999999999 48.14785) POINT (46.63571 51.16575) 19.027230
1 A1 2 POINT (46.635708 51.165745) POINT (46.59798 47.65744) 3.508504
2 A1 3 POINT (46.597984 47.657444) POINT (68.47770 44.07370) 22.171270
3 A1 4 POINT (68.4777 44.0737) POINT (65.42208 48.14785) 5.092692
4 A3 1 POINT (46.635708 54.10819) POINT (46.63571 51.84477) 2.263420
5 A3 2 POINT (46.635708 51.84477) POINT (63.30956 48.82688) 16.944764
6 A3 3 POINT (63.30956 48.826878) POINT (62.21557 54.10819) 5.393428
7 A3 4 POINT (62.215572 54.10819) POINT (46.63571 54.10819) 15.579864
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.