使用 Shapely split 函数在给定 POINT 处拆分 LINESTRING
Split LINESTRING at given POINT using Shapely split function
我有一个 geopandas 数据框,看起来像这样:
level_0 id \
0 0 028f342a-b26f-4e36-b5d1-25d3428cac2f
1 1 028f342a-b26f-4e36-b5d1-25d3428cac2f
2 2 028f342a-b26f-4e36-b5d1-25d3428cac2f
3 3 028f342a-b26f-4e36-b5d1-25d3428cac2f
4 4 028f342a-b26f-4e36-b5d1-25d3428cac2f
... ... ...
2959 2959 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2960 2960 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2961 2961 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2962 2962 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2963 2963 fef00a1e-a823-47fc-b6e4-4e5885cc587b
edges.id \
0 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
1 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
2 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
3 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
4 2cb0816e-de32-47ef-9695-eeb1f15e5771
... ...
2959 e0f9373d-0943-4eda-9ab2-0390eb0035a3
2960 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
2961 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
2962 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
2963 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
geometry_obstacle index x_polygon \
0 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 32.47
1 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 33.78
2 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 33.78
3 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 32.47
4 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 32.47
... ... ... ...
2959 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 4.77
2960 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 4.77
2961 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 8.12
2962 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 8.12
2963 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 4.77
y_polygon geometry
0 3.51 POINT (32.46686 3.50903)
1 3.51 POINT (33.78148 3.50903)
2 6.16 POINT (33.78148 6.16054)
3 6.16 POINT (32.46686 6.16054)
4 3.51 POINT (32.46686 3.50903)
... ... ...
2959 37.10 POINT (4.77078 37.10083)
2960 36.10 POINT (4.77078 36.10261)
2961 36.10 POINT (8.12194 36.10261)
2962 37.10 POINT (8.12194 37.10083)
2963 37.10 POINT (4.77078 37.10083)
[2964 rows x 8 columns]
它包含两个几何图形,一个是线串(都是闭合的多边形,都是矩形),另一个是点(多边形的边)。我想要做的是在点处分割线串,从而将 polygons/lenstrings 分割成线段(即多边形的边)。
我试图做以下事情:
from shapely.ops import split
df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
但出现以下错误:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-30-77a268925585> in <module>
2 for lev in lev:
3 df = geostore_obstacles_geometry_new[geostore_obstacles_geometry_new['level_0']==lev]
----> 4 df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
5 New.append(df)
~\Anaconda3\envs\conda-qgis\lib\site-packages\pandas\core\frame.py in assign(self, **kwargs)
3828
3829 for k, v in kwargs.items():
-> 3830 data[k] = com.apply_if_callable(v, data)
3831 return data
3832
~\Anaconda3\envs\conda-qgis\lib\site-packages\pandas\core\common.py in apply_if_callable(maybe_callable, obj, **kwargs)
327 """
328 if callable(maybe_callable):
--> 329 return maybe_callable(obj, **kwargs)
330
331 return maybe_callable
<ipython-input-30-77a268925585> in <lambda>(x)
2 for lev in lev:
3 df = geostore_obstacles_geometry_new[geostore_obstacles_geometry_new['level_0']==lev]
----> 4 df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
5 New.append(df)
~\Anaconda3\envs\conda-qgis\lib\site-packages\shapely\ops.py in split(geom, splitter)
468 """
469
--> 470 if geom.type in ('MultiLineString', 'MultiPolygon'):
471 return GeometryCollection([i for part in geom.geoms for i in SplitOp.split(part, splitter).geoms])
472
~\Anaconda3\envs\conda-qgis\lib\site-packages\pandas\core\generic.py in __nonzero__(self)
1440 @final
1441 def __nonzero__(self):
-> 1442 raise ValueError(
1443 f"The truth value of a {type(self).__name__} is ambiguous. "
1444 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
我怀疑(我很可能是错的)split
尝试了所有 combinations.Therefore,我试图逐行应用 split
:
lev = list(geostore_obstacles_geometry_new.level_0)
New = []
for lev in lev:
df = geostore_obstacles_geometry_new[geostore_obstacles_geometry_new['level_0']==lev]
df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
New.append(df)
但我仍然得到同样的错误。
我该如何解决这个问题?任何其他方法都可以。
由于您似乎有重复的线几何与单个点几何,我将从非矢量化解决方案开始。
每次您调用 df.assign
时,您(试图)一次定义整个列(即,如果循环没有引发错误,则循环将被调用多少次)。
所以在这种情况下,我会沿 axis = 1 使用 df.apply
。我还将 split
包装到一个函数中,该函数接受数据帧的各个行,这样我们就不需要嵌套lambda 函数
from shapely.ops import split
def get_side_of_rect(row, linecol="geometry_obstacle", pointcol="geometry"):
return split(row[linecol], row[pointcol])
gdf = (
gdf.assign(sides=lambda df: df.apply(get_side_of_rect, axis=1))
)
我有一个 geopandas 数据框,看起来像这样:
level_0 id \
0 0 028f342a-b26f-4e36-b5d1-25d3428cac2f
1 1 028f342a-b26f-4e36-b5d1-25d3428cac2f
2 2 028f342a-b26f-4e36-b5d1-25d3428cac2f
3 3 028f342a-b26f-4e36-b5d1-25d3428cac2f
4 4 028f342a-b26f-4e36-b5d1-25d3428cac2f
... ... ...
2959 2959 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2960 2960 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2961 2961 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2962 2962 fef00a1e-a823-47fc-b6e4-4e5885cc587b
2963 2963 fef00a1e-a823-47fc-b6e4-4e5885cc587b
edges.id \
0 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
1 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
2 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
3 28cd1b27-dda1-4ba8-a79c-042e8af6a1d3
4 2cb0816e-de32-47ef-9695-eeb1f15e5771
... ...
2959 e0f9373d-0943-4eda-9ab2-0390eb0035a3
2960 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
2961 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
2962 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
2963 e3eba3f8-0a1a-45a0-b3b1-cd9edcf50128
geometry_obstacle index x_polygon \
0 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 32.47
1 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 33.78
2 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 33.78
3 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 32.47
4 LINESTRING (32.46686 3.50903, 33.78148 3.50903... 106 32.47
... ... ... ...
2959 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 4.77
2960 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 4.77
2961 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 8.12
2962 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 8.12
2963 LINESTRING (4.77078 36.10261, 8.12194 36.10261... 48 4.77
y_polygon geometry
0 3.51 POINT (32.46686 3.50903)
1 3.51 POINT (33.78148 3.50903)
2 6.16 POINT (33.78148 6.16054)
3 6.16 POINT (32.46686 6.16054)
4 3.51 POINT (32.46686 3.50903)
... ... ...
2959 37.10 POINT (4.77078 37.10083)
2960 36.10 POINT (4.77078 36.10261)
2961 36.10 POINT (8.12194 36.10261)
2962 37.10 POINT (8.12194 37.10083)
2963 37.10 POINT (4.77078 37.10083)
[2964 rows x 8 columns]
它包含两个几何图形,一个是线串(都是闭合的多边形,都是矩形),另一个是点(多边形的边)。我想要做的是在点处分割线串,从而将 polygons/lenstrings 分割成线段(即多边形的边)。
我试图做以下事情:
from shapely.ops import split
df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
但出现以下错误:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-30-77a268925585> in <module>
2 for lev in lev:
3 df = geostore_obstacles_geometry_new[geostore_obstacles_geometry_new['level_0']==lev]
----> 4 df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
5 New.append(df)
~\Anaconda3\envs\conda-qgis\lib\site-packages\pandas\core\frame.py in assign(self, **kwargs)
3828
3829 for k, v in kwargs.items():
-> 3830 data[k] = com.apply_if_callable(v, data)
3831 return data
3832
~\Anaconda3\envs\conda-qgis\lib\site-packages\pandas\core\common.py in apply_if_callable(maybe_callable, obj, **kwargs)
327 """
328 if callable(maybe_callable):
--> 329 return maybe_callable(obj, **kwargs)
330
331 return maybe_callable
<ipython-input-30-77a268925585> in <lambda>(x)
2 for lev in lev:
3 df = geostore_obstacles_geometry_new[geostore_obstacles_geometry_new['level_0']==lev]
----> 4 df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
5 New.append(df)
~\Anaconda3\envs\conda-qgis\lib\site-packages\shapely\ops.py in split(geom, splitter)
468 """
469
--> 470 if geom.type in ('MultiLineString', 'MultiPolygon'):
471 return GeometryCollection([i for part in geom.geoms for i in SplitOp.split(part, splitter).geoms])
472
~\Anaconda3\envs\conda-qgis\lib\site-packages\pandas\core\generic.py in __nonzero__(self)
1440 @final
1441 def __nonzero__(self):
-> 1442 raise ValueError(
1443 f"The truth value of a {type(self).__name__} is ambiguous. "
1444 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
我怀疑(我很可能是错的)split
尝试了所有 combinations.Therefore,我试图逐行应用 split
:
lev = list(geostore_obstacles_geometry_new.level_0)
New = []
for lev in lev:
df = geostore_obstacles_geometry_new[geostore_obstacles_geometry_new['level_0']==lev]
df = df.assign(New = lambda x: sp(x['geometry_obstacle'],x['geometry']))
New.append(df)
但我仍然得到同样的错误。
我该如何解决这个问题?任何其他方法都可以。
由于您似乎有重复的线几何与单个点几何,我将从非矢量化解决方案开始。
每次您调用 df.assign
时,您(试图)一次定义整个列(即,如果循环没有引发错误,则循环将被调用多少次)。
所以在这种情况下,我会沿 axis = 1 使用 df.apply
。我还将 split
包装到一个函数中,该函数接受数据帧的各个行,这样我们就不需要嵌套lambda 函数
from shapely.ops import split
def get_side_of_rect(row, linecol="geometry_obstacle", pointcol="geometry"):
return split(row[linecol], row[pointcol])
gdf = (
gdf.assign(sides=lambda df: df.apply(get_side_of_rect, axis=1))
)