Використовувати OGR та Shapely ефективніше? [зачинено]


29

Я шукаю кілька пропозицій щодо того, як зробити свій пітон код більш ефективним. Зазвичай ефективність для мене не має значення, але я зараз працюю з текстовим файлом про місцезнаходження США з більш ніж 1,5 мільйона балів. З урахуванням заданої установки для виконання операцій на одній точці потрібно близько 5 секунд; Мені потрібно опустити цю цифру.

Я використовую три різні пакети GIS python, щоб зробити кілька різних операцій над точками та вивести новий розмежуваний текстовий файл.

  1. Я використовую OGR, щоб прочитати графічний графік графства округу та отримати доступ до геометрії кордону.
  2. Ретельно перевіряє, чи є точка в будь-якому з цих округів.
  3. Якщо вона знаходиться в межах одного, я використовую бібліотеку Shapefile Python, щоб витягувати інформацію про атрибути з межі .dbf.
  4. Потім я записую інформацію з обох джерел у текстовий файл.

Я підозрюю, що неефективність полягає в тому, що є 2-3 ярусна петля ... не зовсім впевнений, що з цим робити. Я особливо шукаю допомоги у когось із досвідчених у використанні будь-якого з цих 3 пакетів, оскільки вперше я використовую будь-який із них.

import os, csv
from shapely.geometry import Point
from shapely.geometry import Polygon
from shapely.wkb import loads
from osgeo import ogr
import shapefile

pointFile = "C:\\NSF_Stuff\\NLTK_Scripts\\Gazetteer_New\\NationalFile_20110404.txt"
shapeFolder = "C:\NSF_Stuff\NLTK_Scripts\Gazetteer_New"
#historicBounds = "C:\\NSF_Stuff\\NLTK_Scripts\\Gazetteer_New\\US_Counties_1860s_NAD"
historicBounds = "US_Counties_1860s_NAD"
writeFile = "C:\\NSF_Stuff\\NLTK_Scripts\\Gazetteer_New\\NewNational_Gazet.txt"

#opens the point file, reads it as a delimited file, skips the first line
openPoints = open(pointFile, "r")
reader = csv.reader(openPoints, delimiter="|")
reader.next()

#opens the write file
openWriteFile = open(writeFile, "w")

#uses Python Shapefile Library to read attributes from .dbf
sf = shapefile.Reader("C:\\NSF_Stuff\\NLTK_Scripts\\Gazetteer_New\\US_Counties_1860s_NAD.dbf")
records = sf.records()
print "Starting loop..."

#This will loop through the points in pointFile    
for row in reader:
    print row
    shpIndex = 0
    pointX = row[10]
    pointY = row[9]
    thePoint = Point(float(pointX), float(pointY))
    #This section uses OGR to read the geometry of the shapefile
    openShape = ogr.Open((str(historicBounds) + ".shp"))
    layers = openShape.GetLayerByName(historicBounds)
    #This section loops through the geometries, determines if the point is in a polygon
    for element in layers:
        geom = loads(element.GetGeometryRef().ExportToWkb())
        if geom.geom_type == "Polygon":
            if thePoint.within(geom) == True:
                print "!!!!!!!!!!!!! Found a Point Within Historic !!!!!!!!!!!!"
                print str(row[1]) + ", " + str(row[2]) + ", " + str(row[5]) + " County, " + str(row[3])
                print records[shpIndex]
                openWriteFile.write((str(row[0]) + "|" + str(row[1]) + "|" + str(row[2]) + "|" + str(row[5]) + "|" + str(row[3]) + "|" + str(row[9]) + "|" + str(row[10]) + "|" + str(records[shpIndex][3]) + "|" + str(records[shpIndex][9]) + "|\n"))
        if geom.geom_type == "MultiPolygon":
            for pol in geom:
                if thePoint.within(pol) == True:
                    print "!!!!!!!!!!!!!!!!! Found a Point Within MultiPolygon !!!!!!!!!!!!!!"
                    print str(row[1]) + ", " + str(row[2]) + ", " + str(row[5]) + " County, " + str(row[3])
                    print records[shpIndex]
                    openWriteFile.write((str(row[0]) + "|" + str(row[1]) + "|" + str(row[2]) + "|" + str(row[5]) + "|" + str(row[3]) + "|" + str(row[9]) + "|" + str(row[10]) + "|" + str(records[shpIndex][3]) + "|" + str(records[shpIndex][9]) + "|\n"))
        shpIndex = shpIndex + 1
    print "finished checking point"
    openShape = None
    layers = None


pointFile.close()
writeFile.close()
print "Done"

3
Ви можете розглянути можливість публікації цього @ Code Review: codereview.stackexchange.com
RyanDalton

Відповіді:


21

Першим кроком буде переміщення форм-формату, відкритого поза циклом рядків, ви відкриваєте та закриваєте файл форми в 1,5 мільйона разів.

Якщо чесно, я хотів би вкласти всю партію в PostGIS і зробити це за допомогою SQL на індексованих таблицях.


19

Швидкий погляд на ваш код приносить кілька оптимізацій:

  • Спершу перевірте кожну точку проти обмежувальної коробки / конверта багатокутників, щоб усунути очевидні залишки. Ви можете піти на крок далі і порахувати кількість скриньок, в яких лежить точка, якщо вона точно одна, то її не потрібно перевіряти на більш складну геометрію (ну, насправді це буде, якщо вона лежить у більше ніж один, його потрібно буде додатково перевірити. Ви можете зробити два проходи для усунення простих випадків із складних випадків).

  • Замість того, щоб прокручувати кожну точку та перевіряти її на багатокутники, проведіть її через багатокутники та протестуйте кожну точку. Завантаження / перетворення геометрії відбувається повільно, тому ви хочете робити це якомога менше. Також спочатку створіть список балів з CSV спочатку, щоб уникнути необхідності робити це кілька разів за точку, а потім не відкидати результати в кінці цієї ітерації.

  • Просторово індексуйте ваші очки, що передбачає перетворення його у файл формату, файл SpatialLite або щось на зразок бази даних PostGIS / PostgreSQL . Це має перевагу в тому, що такі інструменти, як OGR , зможуть виконати більшу частину роботи за вас.

  • Не записуйте вихід до кінця: print () - це дорога функція в найкращі часи. Замість цього зберігайте дані як список та записуйте їх у самому кінці, використовуючи стандартні функції пікіровки Python або функції демпінгу списку.


5
Перші два окупляться великими. Ви також можете трохи пришвидшити, використовуючи ogr для всього, а не Shapely та Shapefile.
sgillies

2
Нічого, що стосується "Python" та "просторового індексу", не дивіться далі, ніж Rtree, оскільки це дуже швидко в пошуку фігур поблизу інших фігур
Майк Т
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.