【发布时间】:2021-07-22 05:48:02
【问题描述】:
我在 for 循环中使用 itertools.combinations() 对项目执行地理数据框修改。我检查没有重复的几何图形,在我的例子中是 LineString。如果是,我删除其中一个。
pandas drop_duplicates() 方法在这里不起作用,因为我们正在处理点坐标的空间几何,这些点坐标可能分布不同,但由相同的 LineString 表示。
import geopandas
import itertools
gdf = geopandas.read_file('example.geojson')
for a, b in itertools.combinations(gdf.geometry, 2):
if a.equals(b) == True:
try:
gdf.drop(gdf[gdf['geometry'] == b].index.values, inplace=True)
except:
continue
gdf.to_file('example.geojson', driver='GeoJSON')
此代码运行良好,但我的文件可能非常大。对于大文件,执行时间很长。有更快的方法吗?
我正在考虑通过将所有几何图形存储在矩阵中来使用 numpy。但我不确定如何在矩阵上使用带有 numpy 的 equals() 方法(来自shapely)。感谢您的帮助。
来自example.geojson 的地理数据框看起来像:
geometry
0 LINESTRING (42.70275 9.94481, 42.70030 9.94783)
1 LINESTRING (42.70030 9.94783, 42.70275 9.94481)
2 LINESTRING (42.70275 9.94481, 42.69700 9.97133)
3 LINESTRING (42.69700 9.97133, 42.70275 9.94481)
4 LINESTRING (42.60179 10.34216, 42.70030 9.94783)
...
解决方案。 这是一个完整的解决方案,灵感来自@DanielKonstantinov 解决方案和
deduplicate。我们将 GeoDataFrame 或 GeoSeries 作为输入,然后将其修改后返回。
import numpy as np
import geopandas as gpd
from shapely.geometry import LineString
def solution(frame):
linestring = frame.geometry
coordinates = [list(x.coords) for x in linestring]
matrix = np.array(coordinates)
result = deduplicate(matrix)
final_result = [list(map(tuple, pair)) for pair in result.tolist()]
lines = [LineString(pair) for pair in final_result]
return gpd.GeoSeries(lines)
【问题讨论】:
-
你能上传一个小的
example.geojson文件吗? -
gdf.geometry 是否可散列?你能用nunique吗?通过检查每个组合来消除重复项将是极其低效的,因为计算机科学,而且您正在修改您正在迭代的容器。
-
@KennyOstrom 谢谢。但是没有
nunique不起作用,因为它们是几何图形,我猜。例如,表中的前两个 LineString 对于 pandas 是不同的,但从地理空间的角度来看是相同的,因为它们具有相同的坐标。 -
你需要一个可散列类型,这样你就可以使用一个集合。我从“pip install geopandas”得到一个错误,所以我只想指出一个集合提供 O(n) 重复检测,而组合提供 O(n^2)。另外,在迭代容器时不要修改容器——让它成为生成新集合的生成器,或其他东西。