Sử dụng OGR và Shapely hiệu quả hơn? [đóng cửa]


29

Tôi đang tìm kiếm một số gợi ý về cách làm cho mã python của tôi hiệu quả hơn. Thông thường hiệu quả không quan trọng đối với tôi nhưng tôi hiện đang làm việc với một tệp văn bản của các địa điểm ở Hoa Kỳ với hơn 1,5 triệu điểm. Với thiết lập đã cho, sẽ mất khoảng 5 giây để chạy các hoạt động trên một điểm; Tôi cần phải giảm con số này xuống.

Tôi đang sử dụng ba gói GIS python khác nhau để thực hiện một vài thao tác khác nhau trên các điểm và xuất ra tệp văn bản được phân tách mới.

  1. Tôi sử dụng OGR để đọc một shapefile ranh giới quận và có quyền truy cập vào hình dạng ranh giới.
  2. Hình dạng kiểm tra để xem nếu một điểm nằm trong bất kỳ quận nào.
  3. Nếu nó nằm trong một, tôi sử dụng Thư viện Shapefile của Python để lấy thông tin thuộc tính từ ranh giới .dbf.
  4. Sau đó tôi viết một số thông tin từ cả hai nguồn vào một tệp văn bản.

Tôi nghi ngờ rằng sự kém hiệu quả nằm ở việc có một vòng lặp 2-3 tầng ... không hoàn toàn chắc chắn phải làm gì về nó. Tôi đặc biệt tìm kiếm sự giúp đỡ với người có kinh nghiệm sử dụng bất kỳ gói nào trong số 3 gói này, vì đây là lần đầu tiên tôi sử dụng bất kỳ gói nào trong số đó.

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
Bạn có thể xem xét đăng bài này @ Đánh giá mã: codereview.stackexchange.com
RyanDalton

Câu trả lời:


21

Bước đầu tiên sẽ là di chuyển shapefile mở bên ngoài vòng lặp hàng, bạn đang mở và đóng shapefile 1,5 triệu lần.

Thành thật mà nói, tôi sẽ nhét toàn bộ vào PostGIS và thực hiện bằng SQL trên các bảng được lập chỉ mục.


19

Nhìn nhanh vào mã của bạn mang đến một vài điều tối ưu:

  • Trước tiên, kiểm tra từng điểm so với hộp giới hạn / đường bao của đa giác, để loại bỏ các ngoại lệ rõ ràng. Bạn có thể tiến thêm một bước và đếm số lượng bbox mà một điểm nằm trong, nếu nó chính xác là một, thì nó không cần phải được kiểm tra đối với hình học phức tạp hơn (thực sự, nó sẽ thực sự nếu nó nằm trong nhiều hơn hơn một, nó sẽ cần phải được kiểm tra thêm. Bạn có thể thực hiện hai lần để loại bỏ các trường hợp đơn giản khỏi các trường hợp phức tạp).

  • Thay vì lặp qua từng điểm và kiểm tra nó với đa giác, hãy lặp qua đa giác và kiểm tra từng điểm. Tải / chuyển đổi hình học là chậm, vì vậy bạn muốn làm điều đó ít nhất có thể. Ngoài ra, hãy tạo danh sách Điểm từ CSV ban đầu, một lần nữa để tránh phải thực hiện nhiều lần cho mỗi điểm sau đó loại bỏ kết quả ở cuối lần lặp đó.

  • Không gian chỉ số điểm của bạn, trong đó bao gồm chuyển đổi nó hoặc là một shapefile, file SpatialLite, hoặc một cái gì đó giống như một PostGIS / PostgreSQL cơ sở dữ liệu. Điều này có lợi thế là các công cụ như OGR sẽ có thể thực hiện hầu hết các công việc cho bạn.

  • Đừng viết đầu ra cho đến khi kết thúc: print () là một hàm đắt tiền vào thời điểm tốt nhất. Thay vào đó, lưu trữ dữ liệu dưới dạng một danh sách và viết nó ra ở cuối bằng cách sử dụng các hàm tẩy Python tiêu chuẩn hoặc các hàm hủy danh sách.


5
Hai người đầu tiên sẽ trả hết. Bạn cũng có thể tăng tốc mọi thứ lên một chút bằng cách sử dụng ogr cho mọi thứ thay vì Shapely và Shapefile.
sgillies

2
Đối với bất cứ điều gì liên quan đến "Python" và "chỉ số không gian", đừng tìm đâu xa ngoài Rtree vì nó rất nhanh trong việc tìm kiếm các hình dạng gần các hình dạng khác
Mike T
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.