Повысить производительность наложения геопанады (пересечение)

У меня есть два набора шейп-файлов с полигонами. Один набор шейп-файлов - это только округа США, которые меня интересуют, и это варьируется в зависимости от фирмы и года. Другой набор шейп-файлов - это сфера деятельности фирм, и, конечно, она варьируется в зависимости от фирмы и года. Мне нужно получить пересечение этих двух слоев для каждой фирмы в каждом году. До сих пор функция overlay(df1, df2, how = 'intersection') достигла моей цели. Но это занимает около 300 с на каждый год фирмы. Учитывая, что у меня длинный список фирм и много лет, мне потребовалось бы несколько дней, чтобы закончить. Есть ли способ улучшить эту производительность?

Я замечаю, что если я делаю то же самое в ArcGIS, 300-е годы сводятся к нескольким секундам. Но я новый пользователь ArcGIS, еще не знакомый с питоном в нем.

3 ответа

Если вы посмотрите на текущий исходный код наложения геопанд, то увидите, что они фактически обновили функцию наложения, чтобы использовать пространственную индексацию Rtree! Я не думаю, что выполнение Rtree вручную будет быстрее (на самом деле, вероятно, будет медленнее) на данный момент.

См. Исходный код здесь: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/overlay.py

Надеюсь, вы уже поняли это, но решение заключается в использовании пространственного индекса R-дерева Geopanda. Вы можете добиться улучшения на порядки, применив его соответствующим образом.

Гофф Боинг написал отличный учебник.

http://geoffboeing.com/2016/10/r-tree-spatial-index-python/

У меня аналогичная ситуация, когда я пытаюсь подсчитать дорожки, пересекающие ячейки в большой сетке; В итоге я использовал мультипроцессор для передачи функции наложения отдельным процессорам. Что-то вроде этого должно сработать...

      from geopandas import read_file, overlay
from multiprocessing import Pool

def func(year):
    df1 = read_file(r'Some dir'+'df1'+str(year)+'.shp') #You will have to modify this with your file details
    df2 = read_file(r'Some dir'+'df2'+str(year)+'.shp')#You will have to modify this with your file details
    overlay(df1, df2, how='intersection').to_file('overlay'+str(year))


if __name__ == '__main__':
    years = [#A list of all the years or file prefixes\suffixes#]
    n = #Number of processors\workers you can call#
    with Pool(n) as pool:
        for results in pool.imap(func,years):
        pass
    pool.close()

Мне пришлось сделать некоторые предположения, например, что каждый шейп-файл имеет какое-то имя с префиксом года. В зависимости от ресурсов ПК вы можете ограничить количество рабочих, назначив что-то для n, или оставить Pool(n) для Pool() и позволить вашей системе разобраться во всем.

Другие вопросы по тегам