From uploaded zipped shapefile to Geopandas DataFrame in Django Application
You can use fiona.io.ZipMemoryFile
and gpd.GeoDataFrame.from_features
.
Example:
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())
Note, I originally didn't include the BytesCollection
as the fiona developer stated in a comment on my previous answer that the class would likely be deprecated. However, if you use it, you shouldn't need ZipMemoryFile
. This works for me:
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's answer got me half way to a solution. I would not have known about fiona.io.ZipMemoryFile
, and that led me to this answer. Combining the two solutions gave me:
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())
I now have my shapefile data in a GeoDataFrame.
For anyone who's curious, the reason I went with BytesCollection
instead of memfile.open()
is because I couldn't get memfile.open()
to work. It would throw an error saying the .open()
method was missing a 'path' positional argument.