geopandas: Error writing out geopackage with Polygons and MultiPolygons

I’m running into an error when trying to write the following test GeoDataFrame into a .gpkg file:

import geopandas
db = geopandas.read_file('test.geojson')
db.to_file('test.gpkg', driver='GPKG')

Which returns:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-16-f5a4384ca577> in <module>()
      1 db = geopandas.read_file('test.geojson')
----> 2 db.to_file('test.gpkg', driver='GPKG')

~/anaconda/envs/gds/lib/python3.6/site-packages/geopandas/geodataframe.py in to_file(self, filename, driver, schema, **kwargs)
    411         """
    412         from geopandas.io.file import to_file
--> 413         to_file(self, filename, driver, schema, **kwargs)
    414
    415     def to_crs(self, crs=None, epsg=None, inplace=False):

~/anaconda/envs/gds/lib/python3.6/site-packages/geopandas/io/file.py in to_file(df, filename, driver, schema, **kwargs)
    109         with fiona.open(filename, 'w', driver=driver, crs=df.crs,
    110                         schema=schema, **kwargs) as colxn:
--> 111             colxn.writerecords(df.iterfeatures())
    112
    113

~/anaconda/envs/gds/lib/python3.6/site-packages/fiona/collection.py in writerecords(self, records)
    333         if self.mode not in ('a', 'w'):
    334             raise IOError("collection not open for writing")
--> 335         self.session.writerecs(records, self)
    336         self._len = self.session.get_length()
    337         self._bounds = self.session.get_extent()

fiona/ogrext.pyx in fiona.ogrext.WritingSession.writerecs()

ValueError: Record's geometry type does not match collection schema's geometry type: 'MultiPolygon' != 'Polygon'

This is on ‘0.4.0’ and the test file is available here. If I try the same operation in QGIS, I have no issue. Any suggestion why?

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 15 (13 by maintainers)

Most upvoted comments

Sorry, should’ve posted this when I initially commented. My code reads:

from shapely import geometry
upcast_dispatch = {geometry.Point: geometry.MultiPoint, 
                   geometry.LineString: geometry.MultiLineString, 
                   geometry.Polygon: geometry.MultiPolygon}

def maybe_cast_to_multigeometry(geom):
    caster = upcast_dispatch.get(type(geom), lambda x: x[0])
    return caster([geom])

I would do this any time we’re writing in a schema we know supports only one geometry type & we see a df.geometry.unique() with both instances of multi and single types.

I can probably manage a PR with this by end of week.