Повысить производительность наложения геопанады (пересечение)
У меня есть два набора шейп-файлов с полигонами. Один набор шейп-файлов - это только округа США, которые меня интересуют, и это варьируется в зависимости от фирмы и года. Другой набор шейп-файлов - это сфера деятельности фирм, и, конечно, она варьируется в зависимости от фирмы и года. Мне нужно получить пересечение этих двух слоев для каждой фирмы в каждом году. До сих пор функция 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. Вы можете добиться улучшения на порядки, применив его соответствующим образом.
Гофф Боинг написал отличный учебник.
У меня аналогичная ситуация, когда я пытаюсь подсчитать дорожки, пересекающие ячейки в большой сетке; В итоге я использовал мультипроцессор для передачи функции наложения отдельным процессорам. Что-то вроде этого должно сработать...
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() и позволить вашей системе разобраться во всем.