จาก shapefile ซิปที่อัพโหลดไปยัง Geopandas DataFrame ใน Django Application
ฉันกำลังพยายามไปถึงจุดที่สามารถกรองจุดหลายพันจุดใน Shapefile ได้อย่างรวดเร็ว แอพลิเคชัน Django ฉันขอ shapefile ซิปไปกับการอัปโหลดที่ไฟล์ซิปมีอย่างน้อย.shp
, .shx
และ.dbf
ไฟล์ เมื่ออยู่ในมุมมอง Django ของฉันไฟล์ zip จะเป็นดังนี้:
request.FILES['file']
> <InMemoryUploadedFile: test.zip (application/x-zip-compressed)>
type(request.FILES['file'])
> <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
request.FILES['file'].file
> <_io.BytesIO object at 0x0000028E29F8FE00>
สมมติว่า Geopandas เป็นตัวเลือกที่ดีที่สุดสำหรับการกรอง / การกำบังที่มีประสิทธิภาพ (ถ้าฉันผิดฉันยินดีรับข้อเสนอแนะอย่างแน่นอน) ฉันไม่แน่ใจว่าจะเปลี่ยนจากสถานะปัจจุบันเป็น Geopandas DataFrame ได้อย่างไร พอลองใช้read_file()
วิธี
import geopandas as gpd
gpd.read_file(request.FILES['file'].file)
ฉันได้รับข้อผิดพลาดต่อไปนี้:
fiona.errors.DriverError: no driver
geopandas.read_file()
เอกสารระบุ:
เส้นทางสัมบูรณ์หรือสัมพัทธ์ไปยังไฟล์หรือ URL ที่จะเปิดหรือวัตถุใด ๆ ที่มี
read()
วิธีการ (เช่นไฟล์ที่เปิดหรือ StringIO)
ฉันไม่แน่ใจว่าจะนำสิ่งที่ฉันมีไปใช้เป็นรูปแบบที่เหมาะสมสำหรับread_file()
วิธีนี้ได้อย่างไร
หมายเหตุ:การมาสก์และการกรองที่ฉันต้องการดำเนินการนั้นอยู่บนข้อมูลแอตทริบิวต์ไม่ใช่รูปทรงเรขาคณิต
คำตอบ
คุณสามารถใช้fiona.io.ZipMemoryFile
และgpd.GeoDataFrame.from_features
.
ตัวอย่าง:
import geopandas as gpd
import io
from fiona.io import ZipMemoryFile
# Just to create a BytesIO object for the demo,
# similar to your request.FILES['file'].file
zipshp = io.BytesIO(open('test.zip', 'rb').read())
with (ZipMemoryFile(zipshp)) as memfile:
with memfile.open() as src:
crs = src.crs
gdf = gpd.GeoDataFrame.from_features(src, crs=crs)
print(gdf.head())
หมายเหตุเดิมทีฉันไม่ได้รวมสิ่งBytesCollection
ที่ผู้พัฒนา Fiona ระบุไว้ในความคิดเห็นในคำตอบก่อนหน้าของฉันว่าชั้นเรียนน่าจะเลิกใช้แล้ว ZipMemoryFile
แต่ถ้าคุณใช้มันคุณไม่ควรจำเป็น สิ่งนี้ใช้ได้กับฉัน:
import geopandas as gpd
import io
import fiona
zipshp = io.BytesIO(open('test.zip', 'rb').read())
with fiona.BytesCollection(zipshp.read()) as src:
crs = src.crs
gdf = gpd.GeoDataFrame.from_features(src, crs=crs)
print(gdf.head())
คำตอบของ @ user2856 ทำให้ฉันมีทางออกได้ครึ่งทาง ฉันคงไม่รู้เรื่องfiona.io.ZipMemoryFile
นี้และนั่นทำให้ฉันได้รับคำตอบนี้ การรวมสองวิธีแก้ปัญหาทำให้ฉัน:
with ZipMemoryFile(request.FILES['file'].file) as memfile:
with fiona.BytesCollection(memfile._initial_bytes) as f:
gdf = gpd.GeoDataFrame.from_features(f, crs='epsg:4326')
print(gdf.head())
ตอนนี้ฉันมีข้อมูล shapefile ของฉันใน GeoDataFrame
สำหรับใครที่สงสัยเหตุผลที่ฉันไปด้วยBytesCollection
แทนที่จะmemfile.open()
เป็นเพราะฉันไม่สามารถmemfile.open()
ไปทำงานได้ มันจะทำให้เกิดข้อผิดพลาดว่า.open()
เมธอดไม่มีอาร์กิวเมนต์ตำแหน่ง 'เส้นทาง'