OGRとShapelyをより効率的に使用していますか?[閉まっている]


29

私は私のPythonコードをより効率的にする方法についていくつかの提案を探しています。通常、効率は重要ではありませんが、現在、150万ポイント以上の米国の場所のテキストファイルを使用しています。指定されたセットアップでは、1つのポイントで操作を実行するのに約5秒かかります。私はこの数字を下げなければなりません。

3つの異なるPython GISパッケージを使用して、ポイントに対していくつかの異なる操作を実行し、新しい区切りテキストファイルを出力しています。

  1. OGRを使用して、郡の境界シェープファイルを読み取り、境界ジオメトリにアクセスします。
  2. Shapelyは、ポイントがこれらの郡のいずれかにあるかどうかを確認します。
  3. 1つ以内の場合、Pythonシェープファイルライブラリを使用して、境界.dbfから属性情報を取得します。
  4. 次に、両方のソースからの情報をテキストファイルに書き込みます。

私は、非効率性が2〜3層のループを持っていることにあるのではないかと疑っています。これら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
あなたはこれを@コードレビューに投稿することを検討するかもしれません:codereview.stackexchange.com
RyanDalton

回答:


21

最初のステップは、シェープファイルを行ループの外側に開いて移動することです。シェープファイルを150万回開いたり閉じたりします。

正直なところ、私はたくさんのことをPostGISに詰め込み、インデックス付きテーブルでSQLを使用してそれを行います。


19

コードを簡単に確認すると、いくつかの最適化が頭に浮かびます。

  • 明らかな異常値を排除するために、まずポリゴンの境界ボックス/エンベロープに対して各ポイントをチェックします。さらに一歩進んで、ポイントが存在するbboxの数を数えることができます。正確に1つであれば、より複雑なジオメトリに対してテストする必要はありません(実際には、より多くにある場合1つ以上の場合、さらにテストする必要があります。2つのパスを実行して、複雑なケースから単純なケースを排除できます。

  • 各ポイントをループしてポリゴンに対してテストする代わりに、ポリゴンをループして各ポイントをテストします。ジオメトリの読み込み/変換は遅いため、できる限り少なくする必要があります。また、最初にCSVからポイントのリストを作成します。これも、ポイントごとに複数回行う必要がなく、その反復の終わりに結果が破棄されることを避けるためです。

  • ポイントを空間的にインデックスします。これには、シェープファイル、SpatialLiteファイル、またはPostGIS / PostgreSQLデータベースのようなもののいずれかに変換することが含まれます。これには、OGRのようなツールがほとんどの作業を実行できるという利点があります。

  • 出力を最後まで書き込まないでください:print()は、最高の状態では高価な関数です。代わりに、データをリストとして保存し、標準のPythonのpickle関数またはリストダンプ関数を使用して最後に書き出します。


5
最初の2つは大きな成果をもたらします。ShapelyやShapefileの代わりに、すべてにogrを使用することで、物事を少しスピードアップすることもできます。
sgillies

2
何でも「パイソン」と関連する「空間インデックス」については、見ていない、さらによりRTREEそれは他の形状に近い形状見つけることで非常に高速であるとして
マイク・T
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.