¿Filtrar por cuadro delimitador en geopandas?

11

Tengo un marco de datos geopandas en EPSG: 4326 y crearía un nuevo marco de datos que consta de todas las filas que se encuentran dentro de un cuadro delimitador determinado.

Primero obtengo el cuadro delimitador que me interesa (que en realidad es el cuadro delimitador de otro marco de datos):

print df_sussex.total_bounds
[ -1.57239292  50.57467674   0.14528384  51.27465152]

Luego hago un marco de datos que consta solo de ese cuadro delimitador:

pts = gpd.GeoDataFrame(df_sussex.total_bounds)

Y finalmente trato de obtener todas las características que se cruzan con ese cuadro delimitador:

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

Pero esto me da AttributeError: No geometry data set yet (expected in column 'geometry'.

¿Qué estoy haciendo mal?

Ricardo
fuente
El problema se debe a que está utilizando el método 'total_bounds'. Solo produce una tupla con puntos máximo y mínimo de cuadro delimitador. El método a utilizar es 'sobre'; anterior para construir su respectivo GeoDataFrame .
xunilk

Respuestas:

5

El problema se debe a que está utilizando el método 'total_bounds'. Solo produce una tupla con puntos máximo y mínimo de cuadro delimitador. El método a utilizar es 'sobre'; anterior para construir su respectivo 'GeoDataFrame'. Por ejemplo, leyendo mis archivos de forma como GeoDataFrame :

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

Construyendo el cuadro delimitador de pol1 y creando su respectivo GeoDataFrame :

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

Intersección de ambos GeoDataFrame :

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

Trazado de resultados:

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

ingrese la descripción de la imagen aquí

Funcionó como se esperaba.

Nota de edición:

Al usar el método 'total_bounds' (porque el método 'envolvente' devuelve el cuadro delimitador para cada característica de los polígonos), se puede usar este enfoque:

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

Y el resultado es idéntico.

xunilk
fuente
21

Puede usar el cxmétodo en un geodataframe para seleccionar filas dentro de un cuadro delimitador. Para sus marcos de ejemplo:

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

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

Además de los métodos de pandas estándar, GeoPandas también proporciona una indexación basada en coordenadas con el indexador cx , que se divide mediante un cuadro delimitador. Se devolverán las geometrías en GeoSeries o GeoDataFrame que intersecan el cuadro delimitador.

jdmcbr
fuente
Esta solución funcionó para mí. Gracias. Sin embargo, me preguntaba si hay una forma más rápida de implementar. Filtrar el uso de la tierra OSM y los lugares que se encuentran dentro del cuadro de límite de una provincia.
EFL
Tenga en cuenta que .cxhace algo ligeramente diferente a la gpd.overlaysolución: selecciona filas que se cruzan con el cuadro delimitador pero deja las geometrías intactas, mientras que la gpd.overlaysolución solo devolverá las partes de las geometrías en el cuadro delimitador. Dependiendo de la situación, es posible que desee uno u otro.
danvk