如何有效地浏览和比较一个非常大的字典的值与列表的元素?
How to efficiently browse and compare the values of a very large dictionary with the elements of a list?
我有一个字典(list_image_dict)和一个列表(structures.geometry),我想将字典中的每个值与列表中的值进行比较,对其进行快速操作并替换字典中的值。
但是list_image_dict
包含300623对key/value,遍历所有值并将它们与structures.geometry
的每个元素进行比较非常长。几十分钟。我的问题是如何提高执行速度?
我尝试在简单的 list_image
列表中使用 16 个内核进行多处理。 list的每个元素都和structures.geometry的元素并行比较,快了一点但还是很慢(还是几十分钟)。 structures.geometry
仅包含 156 个元素。
def make_sort(layers, structures, threshold):
def coverage(a, b): return a.area/b.area*100
def label(
polygon): return structures.loc[structures.geometry == polygon, "label"].values[0]
frames = pd.concat([*layers], ignore_index=True)
frames.crs = "epsg:3857"
frames = frames.to_crs(epsg=4326)
main = gpd.GeoDataFrame(geometry=frames.geometry)
list_image = main.geometry.tolist()
#list_image has 300623 elements.
list_image_dict = {images.wkt: images for images in list_image}
for key, value in list_image_dict.items(): #main loop on list_image_dict
liste=[]
for item in structures.geometry: #structures has 156 elements.
if value.intersects(item):
x = value.intersection(item)
#for a certain threshold coverage (in percent) present on the image
#the polygon is added to the liste.
if coverage(x, item) >= threshold:
liste.append([x, str(label(item))])
list_image_dict[key] = liste
return list_image_dict
在评论里的人的帮助下,这种方式少了几分钟,但还是很长。
def make_sort(layers, structures, threshold):
def coverage(a, b): return a.area/b.area*100
label = structures["label"].to_list()
geom = structures["geometry"].to_list()
frames = pd.concat([*layers], ignore_index=True)
frames.crs = "epsg:3857"
frames = frames.to_crs(epsg=4326)
main = gpd.GeoDataFrame(geometry=frames.geometry)
final = []
for elem in main.geometry:
liste=[]
for item in structures.geometry:
if coverage(elem.intersection(item), item) >= threshold:
liste.append([elem.intersection(item), label[geom.index(item)]])
final.append({elem.wkt: liste})
result = dict(ChainMap(*final))
return result
IIUC,现在,您有 2 个 GeoDataFrames:main
(300623 个多边形)和 structures
(156 个多边形)。首先你想找到交点,然后 select 只有覆盖范围大于 threshold
的多边形。瓶颈是找到从 structures
的一个多边形到 main
.
的 300K 多边形的交集
我认为更好的解决方案是使用 Spatial Index 和 R-Tree。为此,您需要安装 PyGeos
才能访问 main.sindex
.
要快速找出哪些多边形与另一个多边形相交:
for idx, item in structures.iterrows():
print(item['label'])
# All polygons...
indexes = main.sindex.query(item['geometry'], predicate='intersects')
# ...greater than or equal to threshold
indexes = main.iloc[indexes, main.columns.get_loc('geometry')] \
.apply(coverage, b=item['geometry']).ge(threshold) \
.loc[lambda x: x].index
# Do stuff here
...
我有一个字典(list_image_dict)和一个列表(structures.geometry),我想将字典中的每个值与列表中的值进行比较,对其进行快速操作并替换字典中的值。
但是list_image_dict
包含300623对key/value,遍历所有值并将它们与structures.geometry
的每个元素进行比较非常长。几十分钟。我的问题是如何提高执行速度?
我尝试在简单的 list_image
列表中使用 16 个内核进行多处理。 list的每个元素都和structures.geometry的元素并行比较,快了一点但还是很慢(还是几十分钟)。 structures.geometry
仅包含 156 个元素。
def make_sort(layers, structures, threshold):
def coverage(a, b): return a.area/b.area*100
def label(
polygon): return structures.loc[structures.geometry == polygon, "label"].values[0]
frames = pd.concat([*layers], ignore_index=True)
frames.crs = "epsg:3857"
frames = frames.to_crs(epsg=4326)
main = gpd.GeoDataFrame(geometry=frames.geometry)
list_image = main.geometry.tolist()
#list_image has 300623 elements.
list_image_dict = {images.wkt: images for images in list_image}
for key, value in list_image_dict.items(): #main loop on list_image_dict
liste=[]
for item in structures.geometry: #structures has 156 elements.
if value.intersects(item):
x = value.intersection(item)
#for a certain threshold coverage (in percent) present on the image
#the polygon is added to the liste.
if coverage(x, item) >= threshold:
liste.append([x, str(label(item))])
list_image_dict[key] = liste
return list_image_dict
在评论里的人的帮助下,这种方式少了几分钟,但还是很长。
def make_sort(layers, structures, threshold):
def coverage(a, b): return a.area/b.area*100
label = structures["label"].to_list()
geom = structures["geometry"].to_list()
frames = pd.concat([*layers], ignore_index=True)
frames.crs = "epsg:3857"
frames = frames.to_crs(epsg=4326)
main = gpd.GeoDataFrame(geometry=frames.geometry)
final = []
for elem in main.geometry:
liste=[]
for item in structures.geometry:
if coverage(elem.intersection(item), item) >= threshold:
liste.append([elem.intersection(item), label[geom.index(item)]])
final.append({elem.wkt: liste})
result = dict(ChainMap(*final))
return result
IIUC,现在,您有 2 个 GeoDataFrames:main
(300623 个多边形)和 structures
(156 个多边形)。首先你想找到交点,然后 select 只有覆盖范围大于 threshold
的多边形。瓶颈是找到从 structures
的一个多边形到 main
.
我认为更好的解决方案是使用 Spatial Index 和 R-Tree。为此,您需要安装 PyGeos
才能访问 main.sindex
.
要快速找出哪些多边形与另一个多边形相交:
for idx, item in structures.iterrows():
print(item['label'])
# All polygons...
indexes = main.sindex.query(item['geometry'], predicate='intersects')
# ...greater than or equal to threshold
indexes = main.iloc[indexes, main.columns.get_loc('geometry')] \
.apply(coverage, b=item['geometry']).ge(threshold) \
.loc[lambda x: x].index
# Do stuff here
...