Filter dengan kotak pembatas di geopanda?

11

Saya memiliki kerangka data geopanda di EPSG: 4326 dan saya akan membuat kerangka data baru yang terdiri dari semua baris yang termasuk dalam kotak pembatas tertentu.

Pertama saya mendapatkan kotak pembatas yang saya pedulikan (yang sebenarnya adalah kotak pembatas dari kerangka data lain):

print df_sussex.total_bounds
[ -1.57239292  50.57467674   0.14528384  51.27465152]

Lalu saya membuat dataframe yang hanya terdiri dari kotak pembatas itu:

pts = gpd.GeoDataFrame(df_sussex.total_bounds)

Dan akhirnya saya mencoba untuk mendapatkan semua fitur yang bersinggungan dengan kotak pembatas itu:

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

Tapi ini memberiku AttributeError: No geometry data set yet (expected in column 'geometry'.

Apa yang saya lakukan salah?

Richard
sumber
Masalahnya adalah karena Anda menggunakan metode 'total_bounds'. Ini hanya menghasilkan sebuah tuple dengan poin max dan min dari kotak pembatas. Metode yang akan digunakan adalah 'amplop'; sebelumnya untuk membangun GeoDataFrame masing-masing .
xunilk

Jawaban:

5

Masalahnya adalah karena Anda menggunakan metode 'total_bounds'. Ini hanya menghasilkan sebuah tuple dengan poin max dan min dari kotak pembatas. Metode yang akan digunakan adalah 'amplop'; sebelumnya untuk membangun 'GeoDataFrame' masing-masing. Misalnya, membaca shapefile saya sebagai GeoDataFrame :

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

Membangun kotak pembatas pol1 dan membuat GeoDataFrame masing-masing :

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

Berpotongan kedua GeoDataFrame :

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

Merencanakan hasil:

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

masukkan deskripsi gambar di sini

Itu bekerja seperti yang diharapkan.

Catatan Pengeditan:

Dengan menggunakan metode 'total_bounds' (karena metode 'amplop' mengembalikan kotak pembatas untuk setiap fitur poligon), maka dapat digunakan pendekatan ini:

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

dan hasilnya identik.

xunilk
sumber
21

Anda bisa menggunakan cxmetode pada geodataframe untuk memilih baris dalam kotak pembatas. Untuk frame contoh Anda:

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

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

Selain metode panda standar, GeoPandas juga menyediakan pengindeksan berbasis koordinat dengan pengindeks cx , yang diiris menggunakan kotak pembatas. Geometri di GeoSeries atau GeoDataFrame yang memotong kotak pembatas akan dikembalikan.

jdmcbr
sumber
Solusi ini berhasil untuk saya. Terima kasih. Namun, saya bertanya-tanya apakah ada cara yang lebih cepat untuk diterapkan. Memfilter OSM penggunaan lahan dan tempat-tempat yang termasuk dalam kotak batas provinsi.
EFL
Perhatikan bahwa .cxmelakukan sesuatu yang sedikit berbeda dari gpd.overlaysolusinya: ia memilih baris yang memotong kotak pembatas tetapi membiarkan geometri tetap utuh, sedangkan gpd.overlaysolusi hanya akan mengembalikan bagian-bagian geometri dalam kotak pembatas. Tergantung pada situasi yang Anda inginkan satu atau yang lain.
danvk