Фільтр по обмежувальній коробці в геопандах?


11

Я маю географічний кадр даних в EPSG: 4326, і я би створив новий кадр даних, що складається з усіх рядків, які потрапляють у певне обмежувальне поле.

Спочатку я дістаю обмежувальне поле, про яке мені важливо (що насправді є обмежувальним вікном іншого фрейму даних):

print df_sussex.total_bounds
[ -1.57239292  50.57467674   0.14528384  51.27465152]

Тоді я роблю фрейм даних, що складається тільки з цього обмежувального поля:

pts = gpd.GeoDataFrame(df_sussex.total_bounds)

І нарешті я намагаюся отримати всі функції, які перетинаються з цим обмежувальним полем:

sac_sussex = gpd.overlay(pts, df_sac, how='intersection')

Але це дає мені AttributeError: No geometry data set yet (expected in column 'geometry'.

Що я роблю неправильно?


Проблема полягає в тому, що ви використовуєте метод 'total_bounds'. Він створює лише кортеж із максимальними та мінімальними точками обмежувальної коробки. Метод, який слід використовувати, - «конверт»; попередній для створення відповідної GeoDataFrame .
xunilk

Відповіді:


6

Проблема полягає в тому, що ви використовуєте метод 'total_bounds'. Він створює лише кортеж із максимальними та мінімальними точками обмежувальної коробки. Метод, який слід використовувати, - «конверт»; попередній для створення відповідної "GeoDataFrame". Наприклад, читаючи мої файли форм як GeoDataFrame :

import geopandas as gpd
pol1 = gpd.GeoDataFrame.from_file("pyqgis_data/polygon1.shp")
pol8 = gpd.GeoDataFrame.from_file("pyqgis_data/polygon8.shp")

Побудова обмежувального поля з pol1 та створення відповідної GeoDataFrame :

bounding_box = pol1.envelope
df = gpd.GeoDataFrame(gpd.GeoSeries(bounding_box), columns=['geometry'])

Перетинаються обидва GeoDataFrame :

intersections = gpd.overlay(df, pol8, how='intersection')

Результати графіку:

from matplotlib import pyplot as plt
plt.ion()
intersections.plot() 

введіть тут опис зображення

Це спрацювало як очікувалося.

Примітка щодо редагування:

Використовуючи метод 'total_bounds' (оскільки метод 'конверт' повертає обмежувальне поле для кожної функції полігонів), можна використовувати такий підхід:

from matplotlib import pyplot as plt
import geopandas as gpd
from shapely.geometry import Point, Polygon

pol1 = gpd.GeoDataFrame.from_file("pyqgis_data/polygon1.shp")
pol8 = gpd.GeoDataFrame.from_file("pyqgis_data/polygon8.shp")

bbox = pol1.total_bounds

p1 = Point(bbox[0], bbox[3])
p2 = Point(bbox[2], bbox[3])
p3 = Point(bbox[2], bbox[1])
p4 = Point(bbox[0], bbox[1])

np1 = (p1.coords.xy[0][0], p1.coords.xy[1][0])
np2 = (p2.coords.xy[0][0], p2.coords.xy[1][0])
np3 = (p3.coords.xy[0][0], p3.coords.xy[1][0])
np4 = (p4.coords.xy[0][0], p4.coords.xy[1][0])

bb_polygon = Polygon([np1, np2, np3, np4])

df2 = gpd.GeoDataFrame(gpd.GeoSeries(bb_polygon), columns=['geometry'])

intersections2 = gpd.overlay(df2, pol8, how='intersection')

plt.ion()
intersections2.plot()

а результат однаковий.


21

Ви можете використовувати cxметод на геодефрамері для вибору рядків у обмежувальному полі. Для вашого прикладу кадри:

xmin, ymin, xmax, ymax = df_sussex.total_bounds
sac_sussex = df_sac.cx[xmin:xmax, ymin:ymax]

З http://geopandas.org/indexing.html :

На додаток до стандартних методів панд, GeoPandas також пропонує індексацію на основі координат з індексатором cx , який розрізає за допомогою обмежувального поля. Геометрії в GeoSeries або GeoDataFrame, які перетинають обмежувальне поле, будуть повернуті.


Це рішення спрацювало на мене. Дякую. Однак мені було цікаво, чи існує більш швидкий спосіб втілення. Фільтрування землекористування ОСМ та місць, які потрапляють у обмежувальне поле провінції.
EFL

Зауважте, що .cxце щось дещо інше, ніж gpd.overlayрішення: він вибирає рядки, які перетинають обмежувальний ящик, але залишає геометрії недоторканими, тоді як gpd.overlayрішення повертає лише частини геометрії в обмежувальний ящик. Залежно від ситуації ви можете хотіти того чи іншого.
данвк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.