使用 Shapely split 函数在给定的 POINT 处拆分 LINESTRING

Posted

技术标签:

【中文标题】使用 Shapely split 函数在给定的 POINT 处拆分 LINESTRING【英文标题】:Split LINESTRING at given POINT using Shapely split function 【发布时间】:2022-01-19 12:11:29 【问题描述】:

我有一个看起来像这样的 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]

它包含两个几何图形,一个是线串(它们都是封闭的多边形,都是矩形),另一个是点(多边形的边缘)。我想要做的是在点处分割线串,从而将多边形/透镜串分割成段(即多边形的边)。

我尝试做以下事情:

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 会尝试所有组合。因此,我尝试逐行应用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)

但我仍然遇到同样的错误。

我该如何解决这个问题?任何其他方法都可以。

【问题讨论】:

【参考方案1】:

由于您似乎有重复的线几何与单个点几何,我将从非矢量化解决方案开始。

每次您调用 df.assign 时,您(尝试)一次定义整个列(即,如果没有引发错误,您的循环将被调用多次)。

所以在这种情况下,我将沿轴 = 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))
)

【讨论】:

我没有收到任何错误,但除了&lt;function get_side_of_rect at 0x000001CCA681DD30&gt;,我没有收到任何输出。我错过了什么吗? @SergedeGossondeVarennes,哦,哎呀,我忘了把函数传递给df.apply 太棒了!!!非常感谢!

以上是关于使用 Shapely split 函数在给定的 POINT 处拆分 LINESTRING的主要内容,如果未能解决你的问题,请参考以下文章

确定 Shapely 点是不是在 LineString/MultiLineString 内

记录shapely包的Polygon的self.wkt

shapely 和 matplotlib 多边形点在地理位置上不准确

oracle中使用split函数问题

如何在Python中配合Split Pearson 7函数?

在java中使用分隔符为'|'的split函数字符(或符号)[重复]