Filtrar por caixa delimitadora em geopandas?


11

Eu tenho um quadro de dados de geopandas no EPSG: 4326 e faria um novo quadro de dados que consiste em todas as linhas que se enquadram em uma certa caixa delimitadora.

Primeiro, recebo a caixa delimitadora que me interessa (que na verdade é a caixa delimitadora de outro dataframe):

print df_sussex.total_bounds
[ -1.57239292  50.57467674   0.14528384  51.27465152]

Então eu faço um quadro de dados que consiste apenas nessa caixa delimitadora:

pts = gpd.GeoDataFrame(df_sussex.total_bounds)

E finalmente tento obter todos os recursos que se cruzam com essa caixa delimitadora:

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

Mas isso me dá AttributeError: No geometry data set yet (expected in column 'geometry'.

O que estou fazendo de errado?


O problema ocorre porque você está usando o método 'total_bounds'. Produz apenas uma tupla com pontos máximo e mínimo da caixa delimitadora. O método a ser usado é 'envelope'; anterior para criar seu respectivo GeoDataFrame .
Xunilk

Respostas:


5

O problema ocorre porque você está usando o método 'total_bounds'. Produz apenas uma tupla com pontos máximo e mínimo da caixa delimitadora. O método a ser usado é 'envelope'; anterior para criar seu respectivo 'GeoDataFrame'. Por exemplo, lendo meus shapefiles como GeoDataFrame :

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

Criando caixa delimitadora pol1 e criando seu respectivo GeoDataFrame :

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

Interseção de ambos GeoDataFrame :

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

Resultados da plotagem:

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

insira a descrição da imagem aqui

Funcionou como esperado.

Nota de edição:

Usando o método 'total_bounds' (como o método 'envelope' retorna a caixa delimitadora para cada recurso dos polígonos), pode-se usar esta abordagem:

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

e o resultado é idêntico.


21

Você pode usar o cxmétodo em um quadro de dados geográficos para selecionar linhas dentro de uma caixa delimitadora. Para seus quadros de exemplo:

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

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

Além dos métodos padrão do pandas, o GeoPandas também fornece indexação baseada em coordenadas com o indexador cx , que corta usando uma caixa delimitadora. As geometrias no GeoSeries ou GeoDataFrame que cruzam a caixa delimitadora serão retornadas.


Esta solução funcionou para mim. Obrigado. No entanto, eu queria saber se há uma maneira mais rápida de implementar. Filtrando o uso da terra e os lugares do OSM que se enquadram na caixa delimitadora de uma província.
EFL

Observe que .cxfaz algo um pouco diferente da gpd.overlaysolução: ele seleciona linhas que cruzam a caixa delimitadora, mas deixa as geometrias intactas, enquanto a gpd.overlaysolução retornará apenas as partes das geometrias na caixa delimitadora. Dependendo da situação, você pode querer um ou outro.
danvk 26/02
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.