アップロードされたzip形式のシェープファイルからDjangoアプリケーションのGeopandasDataFrameへ
シェープファイル内の何千ものポイントをすばやくフィルタリングできるポイントに到達しようとしています。私のDjangoアプリケーションは、zipファイルが少なくとも含まれている場合は、アップロードするzip形式のシェープファイルを要求.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が効率的なフィルタリング/マスキングに最適なオプションであると仮定すると(私が間違っている場合は、間違いなく提案を受け入れます)、現在の状態からGeopandasDataFrameに移行する方法がわかりません。この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
、そしてそれは私をこの答えに導きました。2つのソリューションを組み合わせると、次のことがわかりました。
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にシェープファイルデータがあります。
好奇心旺盛な方のために、BytesCollection
代わりに一緒に行ったのmemfile.open()
は、仕事ができなかったmemfile.open()
からです。.open()
メソッドに「パス」の位置引数がないというエラーがスローされます。