删除 geopandas 中的相交线
Removing intersecting lines in geopandas
我有一个由 LineString 几何图形组成的大型地理数据框(可能有数百万行)。其中一些线可以相互相交,而另一些则不相交。我想以有效的方式删除所有相交的线。我有一个使用“apply”和一个 shapely 函数来查找交叉点的解决方案,但它在大型数据集上非常慢。任何帮助将不胜感激!
到目前为止,我使用一个小示例地理数据框的解决方案如下。这有效,但在放大时速度很慢。
from shapely.geometry import LineString
import geopandas as gpd
import numpy as np
def doesIntersect(line_A, line_B):
return line_A.intersects(line_B)
def check_intersections(row, lines):
# remove this row from the lines geoseries so we don't check against itself
l = lines.drop(row.name)
# return a boolean array to check if lines intersect
intersects = [ doesIntersect(row['geometry'], x) for x in l ]
# get the index of the first intersecting line
idx = np.where(intersects)[0]
# add the geometry of the intersecting line to the original geodataframe
if not (len(idx) == 0):
intersect_line = l.iloc[idx[0]]
row['intersect_line'] = intersect_line
print(intersect_line)
else:
row['intersect_line'] = 0
print("no intersection")
return row
# create an example gdf of intersecting lines
gdf = gpd.GeoDataFrame({'id': [1, 2, 3]}, geometry=[LineString([(1, 1), (4, 4)]),
LineString([(1, 4), (4, 1)]),
LineString([(6, 1), (6, 6)])])
# get the lines as a geoseries
lines = gdf['geometry']
# apply the function to the geodataframe
gdf = gdf.apply(check_intersections, axis=1, lines=lines)
# now drop intersecting lines
gdf = gdf[gdf['intersect_line'] == 0].drop(columns='intersect_line')
print(gdf)
利用内置 R 树空间索引的空间连接怎么样?
import geopandas as gpd
import pandas as pd
gdf = gpd.GeoDataFrame({'id': [1, 2, 3]}, geometry=[LineString([(1, 1), (4, 4)]),
LineString([(1, 4), (4, 1)]),
LineString([(6, 1), (6, 6)])])
# make a copy of the original gdf for spatial join
gdf_copy = gdf.copy(deep=True)
# spaital join the copy to the original gdf
gdf_sj = gpd.sjoin(gdf, gdf_copy)
gdf_sj_vc = gdf_sj['id_left'].value_counts()
# value counts for intersecting lines will be >=2
int_mask = gdf_sj_vc.ge(2)
# add the mask to gdf_sj as intersects columnn
gdf_sj['intersects'] = gdf_sj['id_left'].map(int_mask)
# drop non-intersecting lines
gdf_no_intersect = gdf_sj.loc[gdf_sj['intersects'] == False]
print(gdf_no_intersect)
id_left geometry index_right id_right intersects
2 3 LINESTRING (6.00000 1.00000, 6.00000 6.00000) 2 3 False
我有一个由 LineString 几何图形组成的大型地理数据框(可能有数百万行)。其中一些线可以相互相交,而另一些则不相交。我想以有效的方式删除所有相交的线。我有一个使用“apply”和一个 shapely 函数来查找交叉点的解决方案,但它在大型数据集上非常慢。任何帮助将不胜感激!
到目前为止,我使用一个小示例地理数据框的解决方案如下。这有效,但在放大时速度很慢。
from shapely.geometry import LineString
import geopandas as gpd
import numpy as np
def doesIntersect(line_A, line_B):
return line_A.intersects(line_B)
def check_intersections(row, lines):
# remove this row from the lines geoseries so we don't check against itself
l = lines.drop(row.name)
# return a boolean array to check if lines intersect
intersects = [ doesIntersect(row['geometry'], x) for x in l ]
# get the index of the first intersecting line
idx = np.where(intersects)[0]
# add the geometry of the intersecting line to the original geodataframe
if not (len(idx) == 0):
intersect_line = l.iloc[idx[0]]
row['intersect_line'] = intersect_line
print(intersect_line)
else:
row['intersect_line'] = 0
print("no intersection")
return row
# create an example gdf of intersecting lines
gdf = gpd.GeoDataFrame({'id': [1, 2, 3]}, geometry=[LineString([(1, 1), (4, 4)]),
LineString([(1, 4), (4, 1)]),
LineString([(6, 1), (6, 6)])])
# get the lines as a geoseries
lines = gdf['geometry']
# apply the function to the geodataframe
gdf = gdf.apply(check_intersections, axis=1, lines=lines)
# now drop intersecting lines
gdf = gdf[gdf['intersect_line'] == 0].drop(columns='intersect_line')
print(gdf)
利用内置 R 树空间索引的空间连接怎么样?
import geopandas as gpd
import pandas as pd
gdf = gpd.GeoDataFrame({'id': [1, 2, 3]}, geometry=[LineString([(1, 1), (4, 4)]),
LineString([(1, 4), (4, 1)]),
LineString([(6, 1), (6, 6)])])
# make a copy of the original gdf for spatial join
gdf_copy = gdf.copy(deep=True)
# spaital join the copy to the original gdf
gdf_sj = gpd.sjoin(gdf, gdf_copy)
gdf_sj_vc = gdf_sj['id_left'].value_counts()
# value counts for intersecting lines will be >=2
int_mask = gdf_sj_vc.ge(2)
# add the mask to gdf_sj as intersects columnn
gdf_sj['intersects'] = gdf_sj['id_left'].map(int_mask)
# drop non-intersecting lines
gdf_no_intersect = gdf_sj.loc[gdf_sj['intersects'] == False]
print(gdf_no_intersect)
id_left geometry index_right id_right intersects
2 3 LINESTRING (6.00000 1.00000, 6.00000 6.00000) 2 3 False