OGR ve Shapely'ı daha verimli kullanmak? [kapalı]


29

Python kodumu nasıl daha verimli hale getirebileceğim konusunda bazı öneriler arıyorum. Normalde verimlilik benim için önemli değil ama şu anda 1,5 milyondan fazla puan alan ABD'deki yerlerin bir metin dosyasıyla çalışıyorum. Verilen kurulumla, işlemleri bir noktada çalıştırmak yaklaşık 5 saniye sürüyor; Bu rakamı aşağı indirmem gerekiyor.

Noktalarda birkaç farklı işlem yapmak ve yeni bir ayrılmış metin dosyası çıkarmak için üç farklı python GIS paketi kullanıyorum.

  1. Bir ilçe sınırının form dosyasını okumak ve sınır geometrisine erişmek için OGR kullanıyorum.
  2. Bir noktanın bu ilçelerden herhangi birinin içinde olup olmadığını görmek için düzenli kontroller.
  3. İçinde ise, Python Shapefile Library'yi öznitelik bilgisini sınırdan .dbf'den çekmek için kullanıyorum.
  4. Daha sonra her iki kaynaktan da bazı bilgileri bir metin dosyasına yazıyorum.

Verimsizliğin 2-3 kademeli bir döngüye sahip olduğundan şüpheliyim ... bu konuda ne yapacağından emin değilim. Bunlardan herhangi birini ilk kez kullandığım için, bu 3 paketin herhangi birini kullanma konusunda deneyimli biriyle özellikle yardım istiyorum.

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
Bu @ Kod İnceleme göndermeyi düşünebilirsiniz: codereview.stackexchange.com
RyanDalton

Yanıtlar:


21

İlk adım, şekil dosyasını satır döngüsünün dışına doğru hareket ettirmek olacaktır, şekil dosyasını 1,5 milyon kez açıp kapatıyorsunuz.

Dürüst olmak gerekirse, hepsini çok PostGIS'e ekler ve dizine alınmış tablolarda SQL kullanarak yapardım.


19

Kodunuza hızlı bir bakış aklınıza birkaç optimizasyon getiriyor:

  • Belli aykırı değerleri ortadan kaldırmak için her noktayı önce çokgenlerin sınırlayıcı kutusuna / zarfına karşı kontrol edin. Bir adım öteye gidebilir ve bir noktanın içinde bulunduğu kutuların sayısını sayabilirsiniz, eğer tam olarak bir ise, o zaman daha karmaşık geometriye karşı test edilmesi gerekmez (peki, gerçekte daha fazla yer alıyorsa, olur. bir taneden daha fazla test edilmesi gerekecek (basit vakaları karmaşık kasalardan çıkarmak için iki geçiş yapabilirsiniz).

  • Her noktadan loop yapmak ve poligonlara karşı test etmek yerine, poligonlardan dolaştırın ve her noktayı test edin. Geometri yüklemek / dönüştürmek yavaştır, bu yüzden mümkün olduğunca az yapmak istersiniz. Ayrıca, başlangıçta CSV'den bir Puan listesi oluşturarak tekrar tekrar nokta başına birkaç kez yapmaktan kaçınmak ve sonuçları bu yinelemenin sonunda atmaktan kaçının.

  • Noktalarınızı biçimsel olarak dizine ekleyin; bu, onu bir shapefile, SpatialLite dosyasına veya PostGIS / PostgreSQL veritabanı gibi bir şeye dönüştürmeyi içerir . Bu, OGR gibi araçların işin çoğunu sizin için yapabileceği avantajına sahiptir .

  • Çıktıyı sonuna kadar yazmayın: print () çoğu zaman pahalı bir işlevdir. Bunun yerine, verileri bir liste olarak saklayın ve standart Python dekapaj fonksiyonlarını veya liste boşaltma fonksiyonlarını kullanarak en sonunda yazın.


5
İlk ikisi büyük ödeyecek. Ayrıca Shapely ve Shapefile yerine her şey için ogr kullanarak işleri biraz hızlandırabilirsiniz.
sgillies

2
"Python" ve "mekansal indeks" ile ilgili herhangi bir şey için, diğer şekillerin yakınında şekiller bulmakta çok hızlı olduğu için Rtree'den başkasına bakmayın
Mike T
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.