ใช้ OGR และหุ่นดีขึ้นอย่างมีประสิทธิภาพหรือไม่ [ปิด]


29

ฉันกำลังมองหาคำแนะนำบางอย่างเกี่ยวกับวิธีทำให้โค้ดไพ ธ อนของฉันมีประสิทธิภาพมากขึ้น ปกติแล้วประสิทธิภาพไม่สำคัญสำหรับฉัน แต่ตอนนี้ฉันกำลังทำงานกับไฟล์ข้อความของสถานที่ในสหรัฐอเมริกาที่มีมากกว่า 1.5 ล้านคะแนน ด้วยการตั้งค่าที่กำหนดจะใช้เวลาประมาณ 5 วินาทีในการรันการทำงานในจุดเดียว ฉันต้องทำให้ตัวเลขนี้ลง

ฉันใช้ python GIS สามแพ็คเกจในการดำเนินการที่แตกต่างกันเล็กน้อยในจุดและส่งออกไฟล์ข้อความที่คั่นด้วยใหม่

  1. ฉันใช้ OGR เพื่ออ่านรูปร่างเขตแดนของเคาน์ตีและเข้าถึงเรขาคณิตของขอบเขต
  2. หุ่นดีตรวจสอบเพื่อดูว่ามีจุดอยู่ในมณฑลใด ๆ เหล่านี้
  3. ถ้ามันอยู่ภายในเดียวฉันใช้ Python Shapefile Library เพื่อดึงข้อมูลแอ็ตทริบิวต์จาก. dbf ขอบเขต
  4. ฉันจะเขียนข้อมูลบางอย่างจากทั้งสองแหล่งลงในไฟล์ข้อความ

ฉันสงสัยว่าการไร้ประสิทธิภาพอยู่ในการวนรอบ 2-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
คุณอาจลองโพสต์รีวิวโค้ด @ นี้: codereview.stackexchange.com
RyanDalton

คำตอบ:


21

ขั้นตอนแรกคือการย้าย Shapefile ที่เปิดอยู่นอกลูปแถวคุณกำลังเปิดและปิด Shapefile 1.5 ล้านครั้ง

พูดตามตรงนะว่าฉันจะทำอะไรมากมายใน PostGIS และใช้ SQL กับตารางที่จัดทำดัชนี


19

การดูรหัสของคุณอย่างรวดเร็วนำมาซึ่งการเพิ่มประสิทธิภาพสองสามประการ:

  • ตรวจสอบแต่ละจุดเทียบกับกล่อง / ซองจดหมายของรูปหลายเหลี่ยมก่อนเพื่อกำจัดค่าผิดปกติที่เห็นได้ชัด คุณสามารถไปอีกขั้นหนึ่งและนับจำนวนของกล่องที่เป็นจุดถ้ามันเป็นอย่างนั้นมันก็ไม่จำเป็นต้องทดสอบกับเรขาคณิตที่ซับซ้อนมากขึ้น (จริง ๆ แล้วมันจะเป็นถ้ามันอยู่ในอีก จะต้องมีการทดสอบมากกว่าหนึ่งครั้งคุณสามารถทำสองรอบเพื่อกำจัดเคสธรรมดาจากเคสที่ซับซ้อน)

  • แทนที่จะวนลูปผ่านแต่ละจุดและทดสอบกับรูปหลายเหลี่ยมให้วนผ่านรูปหลายเหลี่ยมและทดสอบแต่ละจุด การโหลด / การแปลงรูปทรงเรขาคณิตนั้นช้าดังนั้นคุณต้องการทำมันให้น้อยที่สุดเท่าที่จะทำได้ นอกจากนี้ให้สร้างรายการคะแนนจาก CSV ในขั้นต้นอีกครั้งเพื่อหลีกเลี่ยงการทำหลายครั้งต่อจุดจากนั้นยกเลิกผลลัพธ์เมื่อสิ้นสุดการทำซ้ำ

  • จัดทำดัชนีคะแนนของคุณซึ่งเกี่ยวข้องกับการแปลงเป็นไฟล์ shapefile, SpatialLite หรือสิ่งอื่น ๆ เช่นฐานข้อมูลPostGIS / PostgreSQL นี่เป็นข้อได้เปรียบที่เครื่องมือเช่นOGRจะสามารถทำงานให้คุณได้มากที่สุด

  • อย่าเขียนเอาต์พุตจนกว่าจะสิ้นสุด: print () เป็นฟังก์ชันที่มีราคาแพงในเวลาที่ดีที่สุด แทนการเก็บข้อมูลเป็นรายการและเขียนมันออกมาในตอนท้ายโดยใช้ฟังก์ชั่น Python มาตรฐานหรือฟังก์ชั่นการถ่ายโอนข้อมูลรายการ


5
สองคนแรกจะชำระใหญ่ คุณยังสามารถเร่งความเร็วของสิ่งต่าง ๆ ได้โดยใช้ ogr สำหรับทุกสิ่งแทน Shapely และ Shapefile
sgillies

2
สำหรับสิ่งที่เกี่ยวข้องกับ "Python" และ "spatial index" อย่ามองไกลไปกว่าRtreeเพราะมันรวดเร็วในการค้นหารูปร่างที่อยู่ใกล้กับรูปร่างอื่น ๆ
Mike T
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.