업로드 된 압축 shapefile에서 Django 애플리케이션의 Geopandas DataFrame으로

Jan 05 2021

shapefile에서 수천 개의 포인트를 빠르게 필터링 할 수있는 지점에 도달하려고합니다. 내 장고 응용 프로그램은 압축 파일이 적어도 포함 업로드에 압축 Shape 파일, 요청 .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()방법에 적합한 형식으로 얻는 방법을 모르겠습니다 .

참고 : 수행하려는 마스킹 및 필터링은 지오메트리가 아닌 속성 데이터에 대한 것입니다.

답변

4 user2856 Jan 05 2021 at 06:19

당신은 사용할 수 있습니다 fiona.io.ZipMemoryFilegpd.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로 피오나 개발자가 이전 답변 에 대한 의견에서 클래스가 더 이상 사용되지 않을 것이라고 언급했듯이 원래는 포함하지 않았습니다 . 그러나 사용하는 경우 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())
1 GISUser9 Jan 06 2021 at 00:04

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

이제 GeoDataFrame에 shapefile 데이터가 있습니다.

호기심이 많은 분들에게 BytesCollection대신 같이 갔던 이유는 일을 memfile.open()할 수 없었기 때문 memfile.open()입니다. .open()메서드에 '경로'위치 인수가 없다는 오류가 발생합니다 .