Фильтровать по ограничивающему прямоугольнику в геопандах?

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 (поскольку метод envelope возвращает ограничивающую рамку для каждого объекта полигонов), можно использовать этот подход:

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()

и результат идентичен.

xunilk
источник
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, которые пересекают ограничивающую рамку.

jdmcbr
источник
Это решение сработало для меня. Спасибо. Однако мне было интересно, есть ли более быстрый способ реализации. Фильтрация землепользования OSM и мест, которые находятся в пределах границ провинции.
EFL
Обратите внимание, что .cxэто немного отличается от gpd.overlayрешения: оно выбирает строки, которые пересекают ограничивающую рамку, но оставляет геометрии нетронутыми, тогда как gpd.overlayрешение будет возвращать только части геометрии в ограничительной рамке. В зависимости от ситуации вы можете захотеть одно или другое.
danvk