กรองตามขอบเขตใน geopandas หรือไม่


11

ฉันมี dataframe geopandas ใน EPSG: 4326 และฉันจะสร้าง dataframe ขึ้นใหม่ซึ่งประกอบด้วยแถวทั้งหมดที่อยู่ในกล่องที่ จำกัด

ก่อนอื่นฉันจะได้รับ bounding box ที่ฉันสนใจ (ซึ่งจริงๆแล้วคือ bounding box ของ dataframe อื่น):

print df_sussex.total_bounds
[ -1.57239292  50.57467674   0.14528384  51.27465152]

จากนั้นฉันสร้าง dataframe ที่ประกอบด้วยกล่อง bounding เท่านั้น:

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วิธีการกับ geodataframe เพื่อเลือกแถวภายในกล่องที่มีขอบเขต สำหรับตัวอย่างเฟรมของคุณ:

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

จากhttp://geopandas.org/indexing.html :

นอกเหนือจากวิธีการแบบมาตรฐานของแพนด้าแล้ว GeoPandas ยังมีการจัดทำดัชนีตามพิกัดร่วมกับตัวทำดัชนีcxซึ่งแบ่งส่วนโดยใช้กล่องขอบเขต Geometries ใน GeoSeries หรือ GeoDataFrame ที่ตัดกันกล่อง bounding จะถูกส่งคืน


วิธีนี้ใช้ได้ผลสำหรับฉัน ขอบคุณ. อย่างไรก็ตามฉันสงสัยว่าจะมีวิธีการนำไปใช้ที่เร็วขึ้นหรือไม่ การกรองการใช้ที่ดิน OSM และสถานที่ที่อยู่ในกล่องของจังหวัด
EFL

โปรดทราบว่า.cxทำสิ่งที่แตกต่างจากgpd.overlayโซลูชันเล็กน้อย: จะเลือกแถวที่ตัดกันกล่องขอบ แต่ปล่อยให้รูปทรงเรขาคณิตไม่บุบสลายในขณะที่gpd.overlayวิธีแก้ปัญหาจะคืนส่วนของรูปทรงเรขาคณิตในกล่องขอบเขตเท่านั้น ขึ้นอยู่กับสถานการณ์ที่คุณอาจต้องการอย่างใดอย่างหนึ่ง
danvk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.