python - 如何有效地浏览和比较非常大的字典的值与列表的元素?

标签 python pandas performance dictionary geopandas

我有一个字典(list_image_dict)和一个列表(structures.geometry),我想将字典中的每个值与列表中的值进行比较,对其执行快速操作并替换字典中的值。
但是list_image_dict包含 300623 个键/值对,遍历所有值并将它们与 structures.geometry 的每个元素进行比较很长。几十分钟。我的问题是 如何提高执行速度?
我尝试通过简单的 16 核多处理 list_image列表。列表中的每个元素都与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 个 GeoDataFrame:main (300623 个多边形)和 structures (156 个多边形)。首先要找到交点,然后仅选择覆盖范围大于 threshold 的多边形.瓶颈是从 structures 中找到一个多边形的交点。到 main 的 300K 个多边形.
我认为更好的解决方案是使用 空间索引 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
    ...

关于python - 如何有效地浏览和比较非常大的字典的值与列表的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69508218/

相关文章:

Python - 更好地处理多个 str.replace 调用?

python - 使用 PyMongo 将 NumPy rec.array 插入 MongoDB

python - 如何在 Pandas 中遍历 DataFrame 中的行

python - 解码 CSV 文件中的 UTF8 文字

python - 是否有更快的方法来计算多列中的值,排除同一行上的重复值?

java - 如何使用 java.time.ZonedDateTime 生成 UTC 格式的原始 long 值

python - 为什么 full_like 这么慢(与其他方法相比)?

python - 页码python-docx

php - 为什么 PHP 中的转换和比较比 is_* 更快?

python - 调整子图大小后如何更改标题?