Pandas 如何找出哪些管道朝向错误的方向
我正在计算区域供暖系统。我从shapefile中获取信息–对于管道,我有一个带有起点和终点坐标的线串几何体。我创建了一个geopandas数据帧:Pandas 如何找出哪些管道朝向错误的方向,pandas,shapefile,geopandas,Pandas,Shapefile,Geopandas,我正在计算区域供暖系统。我从shapefile中获取信息–对于管道,我有一个带有起点和终点坐标的线串几何体。我创建了一个geopandas数据帧: +-------+----------------------------------------------------------------------------------------------------------------------+ | |
+-------+----------------------------------------------------------------------------------------------------------------------+
| | |
| ID | geometry |
+-------+----------------------------------------------------------------------------------------------------------------------+
| | |
| 0 | LINESTRING (1679896.423 5802688.586, 1679896.034 5802688.745) |
+-------+----------------------------------------------------------------------------------------------------------------------+
| | |
| 1 | LINESTRING (1679896.034 5802688.745, 1679892.419 5802689.660) |
+-------+----------------------------------------------------------------------------------------------------------------------+
| | |
| 2 | LINESTRING (1679908.185 5802692.533, 1679911.830 5802691.936, 1679927.258 5802689.562, 1679945.682 5802686.042) |
+-------+----------------------------------------------------------------------------------------------------------------------+
| | |
| 3 | LINESTRING (1679945.667 5802685.478, 1679945.653 5802685.247) |
+-------+----------------------------------------------------------------------------------------------------------------------+
| | |
| 4 | …. |
+-------+----------------------------------------------------------------------------------------------------------------------+
对于计算,我必须确定线之间的所有连接(当前管道必须定义“上一个管道”和“下一个管道”)。我这样做的方式是,我创建了一个linestring的起点和终点,并将dataframe与自身合并(将终点与起点配对)。问题是,一些线串(大约占所有线串的1/5)朝向错误的方向,所以我只得到它们的NaN结果(因为当前管道的终点不接触下一个管道的起点,而只是另一个终点)
另外一个问题是,有10个管道连续朝着错误的方向(所以在它们之间,我实际上得到了结果,但它们是错误的)——另一个问题是,有时PipeNext是NaN,因为当前行是终点线。
有没有办法确定管道朝向错误的方向?如果没有,是否可以在绘图上显示线的方向
编辑-添加当前代码:
import pandas as pd
import geopandas as gpd
import folium
import shapefile
import matplotlib.pyplot as plt
from geopandas import GeoDataFrame
import contextily as ctx
df_pipes=gpd.read_file("DO_Hrastnik_odsek.shp")
df_user=gpd.read_file("DO_Hrastnik_objekt.shp")
df_pipes.crs = {'init': 'epsg:3912'}
df_pipes=df_pipes.to_crs("EPSG:3857")
df_user.crs = {'init': 'epsg:3912'}
df_user=df_user.to_crs("EPSG:3857")
df_pipes["ID"] = df_pipes.index + 1
df_pipes['ID']=df_pipes['ID'].astype(str)
df_pipes=df_pipes[["geometry","ID","LENGTH_3D"]].copy()
from shapely.geometry import Point, LineString
df_pipes["node_ups"] = gpd.GeoSeries([Point(list(pt['geometry'].coords)[0]) for i,pt in df_pipes.iterrows()])
df_pipes["node_dws"] = gpd.GeoSeries([Point(list(pt['geometry'].coords)[-1]) for i,pt in df_pipes.iterrows()])
tmp = df_pipes[['ID', 'node_dws', 'node_ups']]
df_connections=pd.merge(tmp, tmp, left_on='node_dws', right_on='node_ups',how="outer")
df_connections=pd.merge(df_connections, tmp, left_on='node_ups_x', right_on='node_dws',how="outer")
df_connections.drop(['node_dws_y', 'node_ups_y','node_dws', 'node_ups'], axis=1, inplace=True)
df_connections = df_connections[df_connections['ID_x'].notna()]
df_connections = df_connections.rename(columns={'ID_x': 'ID_pipe', 'node_dws_x': 'node_dws','node_ups_x': 'node_ups', 'ID_y': 'pipeNext','ID': 'pipePrevious'})
tmp = df_connections[['ID_pipe', 'pipeNext', 'pipePrevious']]
df_connections=pd.merge(tmp, df_pipes, left_on='ID_pipe', right_on='ID',how="outer")
您从评论中了解到的检查端点在何处相遇的想法是一种方法,它并不像您所说的那么复杂。从网络的起始管道开始(所有水都来自于此–我假设这是一根管道),然后使用递归函数沿着网络向下移动:
from shapely.geometry import Point, LineString # You can delete your own code after this line.
# df.apply is faster than iterrows, so I rewrote the following two lines
df_pipes['node_ups'] = df_pipes.geometry.apply(lambda linestring: Point(list(linestring.coords)[0])
df_pipes['node_dws'] = df_pipes.geometry.apply(lambda linestring: Point(list(linestring.coords)[-1])
def check_downstream(pipe_id, pipes):
"""Set next and previous pipe ID for all downstream pipes"""
endpoint = pipes.loc[pipe_id, 'node_dws']
next_ids = list(pipes['node_ups' == endpoint]['ID'])
reversed_ids = list(pipes[(pipes['node_dws'] == endpoint) & (pipes['ID'] != pipe_id)]['ID'])
for rev_id in reversed_ids:
pipes.loc[rev_id, 'node_ups'], pipes.loc[rev_id, 'node_dws'] = pipes.loc[rev_id, 'node_dws'], pipes.loc[rev_id, 'node_ups']
next_ids = next_ids + reversed_ids
for nxt_id in next_ids:
pipes.loc[pipe_id, 'pipeNext'] = nxt_id
pipes.loc[nxt_id, 'pipePrevious'] = pipe_id
check_downstream(nxt_id, pipes) # This is the recursive function call.
df_connections = df_pipes.copy()
df_connections['pipePrevious'] = 'undetermined'
df_connections['pipeNext'] = 'undetermined'
first_id = 99 # or whatever it is
check_downstream(first_id, df_connections)
请注意,这不会反转线条本身,但如果需要,您也可以这样做。是否可以测试线条的一点是否与起点或终点匹配?这并不是说你的管道包含坡度什么的,它只是线条信息,所以就这样对待它。@Maartenverman问题是,在某个地方有多条连续的线条朝向错误的方向。在它们之间,我们可以看到邻居的下一个和上一个被切换(他们的方向是上游)。你能画一个小图吗?概述您的问题。@Maartenverman-以下是系统的一部分:。黄线是错误的方向线。我曾经考虑过这样做:如果内点(currentID)遇到(endpointNEXTID)、交换值(endpointNEXTID startpointNEXTID)、中断、重新启动循环,这将逐行旋转,但考虑到分支结构,这看起来非常复杂。您能给我们展示一下您的代码吗?如果我们可以看到您是如何到达第二个数据帧的,以及可以调整哪些内容来纠正它,那么我们就可以更容易地提供帮助。
from shapely.geometry import Point, LineString # You can delete your own code after this line.
# df.apply is faster than iterrows, so I rewrote the following two lines
df_pipes['node_ups'] = df_pipes.geometry.apply(lambda linestring: Point(list(linestring.coords)[0])
df_pipes['node_dws'] = df_pipes.geometry.apply(lambda linestring: Point(list(linestring.coords)[-1])
def check_downstream(pipe_id, pipes):
"""Set next and previous pipe ID for all downstream pipes"""
endpoint = pipes.loc[pipe_id, 'node_dws']
next_ids = list(pipes['node_ups' == endpoint]['ID'])
reversed_ids = list(pipes[(pipes['node_dws'] == endpoint) & (pipes['ID'] != pipe_id)]['ID'])
for rev_id in reversed_ids:
pipes.loc[rev_id, 'node_ups'], pipes.loc[rev_id, 'node_dws'] = pipes.loc[rev_id, 'node_dws'], pipes.loc[rev_id, 'node_ups']
next_ids = next_ids + reversed_ids
for nxt_id in next_ids:
pipes.loc[pipe_id, 'pipeNext'] = nxt_id
pipes.loc[nxt_id, 'pipePrevious'] = pipe_id
check_downstream(nxt_id, pipes) # This is the recursive function call.
df_connections = df_pipes.copy()
df_connections['pipePrevious'] = 'undetermined'
df_connections['pipeNext'] = 'undetermined'
first_id = 99 # or whatever it is
check_downstream(first_id, df_connections)