Chỉ số không gian RTree không dẫn đến tính toán giao cắt nhanh hơn


9

Tôi có một số mã mà tôi đang sử dụng để xác định Shapely Polygon / MultiPolygons giao nhau với một số Shapely LineStrings. Thông qua các câu trả lời cho câu hỏi này , mã đã đi từ đây:

import fiona
from shapely.geometry import LineString, Polygon, MultiPolygon, shape

# Open each layer
poly_layer = fiona.open('polygon_layer.shp')
line_layer = fiona.open('line_layer.shp')

# Convert to lists of shapely geometries
the_lines = [shape(line['geometry']) for line in line_layer]
the_polygons = [(poly['properties']['GEOID'], shape(poly['geometry'])) for poly in poly_layer]

# Check for Polygons/MultiPolygons that the LineString intersects with
covered_polygons = {}
for poly_id, poly in the_polygons:
    for line in the_lines:
        if poly.intersects(line):
            covered_polygons[poly_id] = covered_polygons.get(poly_id, 0) + 1

nơi mọi ngã tư có thể được kiểm tra, tới đây:

import fiona
from shapely.geometry import LineString, Polygon, MultiPolygon, shape
import rtree

# Open each layer
poly_layer = fiona.open('polygon_layer.shp')
line_layer = fiona.open('line_layer.shp')

# Convert to lists of shapely geometries
the_lines = [shape(line['geometry']) for line in line_layer]
the_polygons = [(poly['properties']['GEOID'], shape(poly['geometry'])) for poly in poly_layer]

# Create spatial index
spatial_index = rtree.index.Index()
for idx, poly_tuple in enumerate(the_polygons):
    _, poly = poly_tuple
    spatial_index.insert(idx, poly.bounds)

# Check for Polygons/MultiPolygons that the LineString intersects with
covered_polygons = {}
for line in the_lines:
    for idx in list(spatial_index.intersection(line.bounds)):
        if the_polygons[idx][1].intersects(line):
            covered_polygons[idx] = covered_polygons.get(idx, 0) + 1

trong đó chỉ số không gian được sử dụng để giảm số lần kiểm tra giao lộ.

Với các shapefile tôi có (khoảng 4000 đa giác và 4 dòng), mã ban đầu thực hiện 12936 .intersection()kiểm tra và mất khoảng 114 giây để chạy. Đoạn mã thứ hai sử dụng chỉ số không gian chỉ thực hiện 1816 .intersection()kiểm tra nhưng cũng mất khoảng 114 giây để chạy.

Mã để xây dựng chỉ mục không gian chỉ mất 1-2 giây để chạy, do đó, 1816 kiểm tra trong đoạn mã thứ hai chỉ mất khoảng thời gian tương tự để thực hiện như kiểm tra 12936 trong mã gốc (kể từ khi tải shapefiles và chuyển đổi thành hình học Shapely giống nhau trong cả hai đoạn mã).

Tôi không thể thấy bất kỳ lý do nào mà chỉ số không gian sẽ khiến việc .intersects()kiểm tra mất nhiều thời gian hơn, vì vậy tôi không biết tại sao điều này lại xảy ra.

Tôi chỉ có thể nghĩ rằng tôi đang sử dụng chỉ số không gian RTree không chính xác. Suy nghĩ?

Câu trả lời:


6

Câu trả lời của tôi về cơ bản dựa trên một câu trả lời khác của @gene tại đây:

Không gian hiệu quả hơn tham gia vào Python mà không cần QGIS, ArcGIS, PostGIS, v.v.

Ông đề xuất cùng một giải pháp sử dụng hai phương pháp khác nhau, có hoặc không có chỉ số không gian.

Ông (chính xác) tuyên bố:

Sự khác biệt là gì ?

  • Không có chỉ mục, bạn phải lặp qua tất cả các hình học (đa giác và điểm).
  • Với chỉ số không gian giới hạn ( Chỉ số không gian RTree ), bạn chỉ lặp qua các hình học có cơ hội giao với hình học hiện tại của bạn ('bộ lọc' có thể tiết kiệm một lượng tính toán và thời gian đáng kể ...)
  • nhưng Chỉ số không gian không phải là cây đũa thần. Khi một phần rất lớn của bộ dữ liệu phải được truy xuất, Chỉ mục không gian không thể mang lại bất kỳ lợi ích tốc độ nào.

Những câu này là tự giải thích, nhưng tôi thích trích dẫn @gene thay vì đề xuất kết luận giống như của tôi (vì vậy, tất cả các khoản tín dụng đều đi vào công việc tuyệt vời của nó!).

Để hiểu rõ hơn về chỉ số không gian Rtree, bạn có thể truy xuất một số thông tin hữu ích theo các liên kết sau:

Một giới thiệu tuyệt vời về việc sử dụng các chỉ số không gian có thể này bài viết bởi @ Nathan Woodrow .


Tôi hiểu rằng chỉ số không gian sẽ hoạt động tốt nhất khi nó có thể giảm bớt các hình học quan tâm đến càng ít càng tốt. Đó là lý do tại sao tôi so sánh số lượng hình học quan tâm khi sử dụng phương pháp ngây thơ (12936) với số lượng hình học khi sử dụng chỉ số không gian (1816). Các intersects()phương pháp mất nhiều thời gian khi chỉ số không gian đang được sử dụng (xem sự so sánh thời gian trên), đó là lý do tôi không chắc chắn nếu tôi đang sử dụng các chỉ số không gian không chính xác. Từ việc đọc tài liệu và các bài đăng được liên kết, tôi nghĩ là tôi, nhưng tôi đã hy vọng ai đó có thể chỉ ra nếu tôi không làm vậy.
derNincompoop

Tuyên bố cuối cùng của bạn là: "Tôi chỉ có thể nghĩ rằng tôi đang sử dụng chỉ số không gian Rtree không chính xác.", Vì vậy tôi nghĩ rằng bạn đã nhầm lẫn về việc sử dụng chỉ số không gian và tôi đã nhấn mạnh ý nghĩa của nó trong câu trả lời của tôi đề tài). Bạn đang cố gắng thực hiện một số loại phân tích thống kê, nhưng số lượng hình học và các nỗ lực liên quan sẽ không đủ để giải quyết vấn đề tốt hơn. Hành vi này có thể phụ thuộc vào số lượng hình học có liên quan (một số rất ít để đánh giá cao sức mạnh của chỉ số không gian) hoặc từ máy của bạn.
mgri

4

Chỉ cần thêm vào câu trả lời mgri.

Điều quan trọng là phải hiểu thế nào là một chỉ số không gian ( Làm thế nào để triển khai đúng cách một hộp giới hạn cho Shapely & Fiona? ). Với ví dụ của tôi trong Cách xác định hiệu quả trong số hàng ngàn đa giác giao nhau với một dòng

nhập mô tả hình ảnh ở đây

Bạn có thể tạo một chỉ mục không gian với các đa giác

idx = index.Index()
for feat in poly_layer:
    geom = shape(feat['geometry'])
    id = int(feat['id'])
    idx.insert(id, geom.bounds,feat)

Giới hạn của chỉ số không gian (giới hạn đa giác màu xanh lá cây)

nhập mô tả hình ảnh ở đây

Hoặc với LineStrings

  idx = index.Index()
  for feat in line_layer:
      geom = shape(feat['geometry'])
      id = int(feat['id'])
      idx.insert(id, geom.bounds,feat)

Giới hạn của chỉ mục không gian (LineString bị ràng buộc màu đỏ)

nhập mô tả hình ảnh ở đây

Bây giờ, bạn chỉ lặp qua các hình học có cơ hội giao với hình học hiện tại của bạn (màu vàng)

nhập mô tả hình ảnh ở đây

Tôi sử dụng ở đây chỉ số không gian LineStrings (kết quả là như nhau nhưng với ví dụ của bạn về 4000 đa giác và 4 dòng ....).

for feat1 in poly_layer:
    geom1 = shape(feat1['geometry'])
    for id in idx.intersection(geom1.bounds):
        feat2 = line_layer[id]
        geom2 = shape(feat2['geometry'])
        if geom2.intersects(geom1):
            print 'Polygon {} intersects line {}'.format(feat1['id'], feat2['id'])

  Polygon 2 intersects line 0
  Polygon 3 intersects line 0
  Polygon 6 intersects line 0
  Polygon 9 intersects line 0

Bạn cũng có thể sử dụng một trình tạo ( example.py )

def build_ind():
     with fiona.open('polygon_layer.shp') as shapes:
         for s in shapes:
             geom = shape(s['geometry'])
             id = int(s['id'])
             yield (id, geom.bounds, s)

 p= index.Property()
 tree = index.Index(build_ind(), properties=p)
 # first line of line_layer
 first = shape(line_layer.next()['geometry'])
 # intersection of first with polygons
 tuple(tree.intersection(first.bounds))
 (6, 2, 3, 9)

Bạn có thể kiểm tra tập lệnh GeoPandas sjoin.py để hiểu cách sử dụng Rtree .

Có nhiều giải pháp nhưng đừng quên rằng

  • Chỉ số không gian không phải là cây đũa thần ...

Khi tôi sử dụng phương thức ngây thơ (nơi tôi thực hiện kiểm tra giao nhau giữa mọi kết hợp Đa giác và LineString), tôi sẽ thực hiện 12936 thử nghiệm như vậy. Khi tôi sử dụng chỉ số không gian, tôi chỉ phải thực hiện 1816 bài kiểm tra. Tôi tin rằng điều này có nghĩa là chỉ số không gian cung cấp giá trị trong trường hợp sử dụng này. Tuy nhiên, khi tôi đặt mã thời gian, việc thực hiện các bài kiểm tra năm 1816 mất nhiều thời gian như thực hiện các bài kiểm tra 12936. Không phải mã với chỉ số không gian sẽ nhanh hơn vì có ít hơn 11000 thử nghiệm được thực hiện?
derNincompoop

Vì vậy, tôi đã xem xét điều này và thấy rằng ~ 11000 thử nghiệm được thực hiện chỉ bằng mã ngây thơ chỉ mất chưa đến 1 giây để thực hiện, trong khi các thử nghiệm 1816 được thực hiện bởi cả hai bộ mã mất 112 giây để thực hiện. Bây giờ tôi hiểu ý của bạn là 'Chỉ số không gian không phải là cây đũa thần' - mặc dù nó đã làm giảm số lượng bài kiểm tra cần thiết, những bài kiểm tra cần thiết là những bài đóng góp nhiều nhất vào thời gian.
derNincompoop

2

Chỉnh sửa: Để làm rõ câu trả lời này, tôi tin không chính xác rằng tất cả các bài kiểm tra giao nhau mất khoảng thời gian như nhau. Đây không phải là trường hợp. Lý do tôi không đạt được tốc độ mà tôi mong đợi từ việc sử dụng chỉ số không gian là vì việc lựa chọn các bài kiểm tra giao nhau là những bài kiểm tra mất nhiều thời gian nhất ở nơi đầu tiên.

Như gen và mgri đã nói, chỉ số không gian không phải là cây đũa thần. Mặc dù chỉ số không gian giảm xuống số lượng thử nghiệm giao nhau cần được thực hiện từ 12936 đến chỉ 1816, nhưng các thử nghiệm năm 1816 là thử nghiệm chiếm phần lớn thời gian để tính toán ở vị trí đầu tiên.

Chỉ số không gian đang được sử dụng một cách chính xác, nhưng giả định rằng mỗi bài kiểm tra giao nhau mất khoảng thời gian tương đương là không chính xác. Thời gian yêu cầu của thử nghiệm giao cắt có thể thay đổi lớn (0,05 giây so với 0,000007 giây).


1
Bạn không thể tính đến việc chỉ số không gian ảnh hưởng đến tốc độ của giao lộ tiếp theo vì nó chỉ thuộc về độ phức tạp của hình học liên quan. Đối với trường hợp của bạn, nếu hình học "A" và "B" giao nhau trong 0,05 giây, chúng vẫn sẽ giao nhau trong 0,05 giây ngay cả khi trước đó bạn đã sử dụng chỉ số không gian (đây rõ ràng là một tuyên bố lý thuyết, bởi vì tôi nghĩ rằng bạn biết rằng việc xử lý bất cứ điều gì trong bộ xử lý đều liên quan đến nhiều yếu tố khác!).
mgri
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.