I've made an extension to GeoSeries, using Pandas api extension, that works similar to ST_Multi in PostGIS. The extension is not really needed for this problem, but it is convenient if you want to add even more functionallity to GeoSeries.
import pandas
import shapely.geometry
from geopandas import GeoSeries
Imports for the examples
from shapely.geometry import Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection
Adding a geoaccessor
For more info: https://pandas.pydata.org/docs/reference/api/pandas.api.extensions.register_series_accessor.html
@pandas.api.extensions.register_series_accessor("geom")
class GeoAccessor:
def init(self, series: GeoSeries):
self._s = series
def make_multi(self, inplace: bool = False):
geoms = []
for i, s in self._s.items():
# Getting the geometry type
tp = s.geom_type
if not tp[0:5] == 'Multi' and tp != 'GeometryCollection':
# Getting the shapely Multi* function for the geometry type
func = getattr(shapely.geometry, 'Multi' + tp)
geoms.append(func([s]))
else:
geoms.append(s)
r = GeoSeries(geoms)
if inplace:
self._s.iloc[:] = r
else:
return r
EXAMPLES
Points:
points = [Point([1, 2]), MultiPoint([[1, 2], [1, 1]])]
gs = GeoSeries(points)
gs.geom.make_multi(inplace=True) # Demonstrating inplace
print(gs)
Lines:
lines = [LineString([[1, 2], [2, 3]]), MultiLineString([[[1, 2], [2, 3]], [[2, 3], [3, 4]]])]
gs = GeoSeries(lines)
print(gs.geom.make_multi())
Polygons:
polygon = [Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]),
MultiPolygon([
[
[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]],
[[[2, 2], [3, 2], [3, 3], [2, 3], [2, 2]]]
]
])]
gs = GeoSeries(polygon)
print(gs.geom.make_multi())
GeometryCollections:
gc = [GeometryCollection([points[0], lines[0], polygon[1]]),
GeometryCollection([points[1], lines[1], polygon[0]])]
gs = GeoSeries(gc)
print(gs.geom.make_multi())
Mix:
gs = GeoSeries([points[0], lines[0], polygon[1]])
print(gs.geom.make_multi())