ENH: Add warning if keep_geom_type drops geometries during overlay (#1554)

* Add warning if keep_geom_type drops geometries during overlay

* Expand keep_geom_type warning message

* Add test for keep_geom_type dropping geoms

* Set keep_geom_type=None by default

With True, no warning raised. With None, will drop geoms of other types,
but warn the user.

* Update geopandas/tests/test_overlay.py

Co-authored-by: Martin Fleischmann <martin@martinfleischmann.net>

Co-authored-by: Joris Van den Bossche <jorisvandenbossche@gmail.com>
Co-authored-by: Martin Fleischmann <martin@martinfleischmann.net>
This commit is contained in:
James McBride
2021-02-18 20:36:56 +00:00
committed by GitHub
co-authored by Martin Fleischmann Joris Van den Bossche
parent 01943827b0
commit 4a650af202
2 changed files with 44 additions and 8 deletions
+17 -1
View File
@@ -382,10 +382,26 @@ def test_correct_index(dfs):
expected = GeoDataFrame(
[[1, 1, i1], [3, 2, i2]], columns=["col3", "col2", "geometry"]
)
result = overlay(df3, df2)
result = overlay(df3, df2, keep_geom_type=True)
assert_geodataframe_equal(result, expected)
def test_warn_on_keep_geom_type(dfs):
df1, df2 = dfs
polys3 = GeoSeries(
[
Polygon([(1, 1), (3, 1), (3, 3), (1, 3)]),
Polygon([(-1, 1), (1, 1), (1, 3), (-1, 3)]),
Polygon([(3, 3), (5, 3), (5, 5), (3, 5)]),
]
)
df3 = GeoDataFrame({"geometry": polys3})
with pytest.warns(UserWarning, match="`keep_geom_type=True` in overlay"):
overlay(df2, df3, keep_geom_type=None)
@pytest.mark.parametrize(
"geom_types", ["polys", "poly_line", "poly_point", "line_poly", "point_poly"]
)
+27 -7
View File
@@ -137,7 +137,7 @@ def _overlay_union(df1, df2):
return dfunion.reindex(columns=columns)
def overlay(df1, df2, how="intersection", keep_geom_type=True):
def overlay(df1, df2, how="intersection", keep_geom_type=None):
"""Perform spatial overlay between two GeoDataFrames.
Currently only supports data GeoDataFrames with uniform geometry types,
@@ -156,7 +156,9 @@ def overlay(df1, df2, how="intersection", keep_geom_type=True):
'identity', 'symmetric_difference' or 'difference'.
keep_geom_type : bool
If True, return only geometries of the same geometry type as df1 has,
if False, return all resulting gemetries.
if False, return all resulting geometries. Default is None,
which will set keep_geom_type to True but warn upon dropping
geometries.
Returns
-------
@@ -241,6 +243,12 @@ def overlay(df1, df2, how="intersection", keep_geom_type=True):
if not _check_crs(df1, df2):
_crs_mismatch_warn(df1, df2, stacklevel=3)
if keep_geom_type is None:
keep_geom_type = True
keep_geom_type_warning = True
else:
keep_geom_type_warning = False
polys = ["Polygon", "MultiPolygon"]
lines = ["LineString", "MultiLineString", "LinearRing"]
points = ["Point", "MultiPoint"]
@@ -280,20 +288,32 @@ def overlay(df1, df2, how="intersection", keep_geom_type=True):
exploded = result.reset_index(drop=True).explode()
exploded = exploded.reset_index(level=0)
type = df1.geom_type.iloc[0]
if type in polys:
orig_num_geoms = result.shape[0]
geom_type = df1.geom_type.iloc[0]
if geom_type in polys:
exploded = exploded.loc[exploded.geom_type.isin(polys)]
elif type in lines:
elif geom_type in lines:
exploded = exploded.loc[exploded.geom_type.isin(lines)]
elif type in points:
elif geom_type in points:
exploded = exploded.loc[exploded.geom_type.isin(points)]
else:
raise TypeError("`keep_geom_type` does not support {}.".format(type))
raise TypeError("`keep_geom_type` does not support {}.".format(geom_type))
# level_0 created with above reset_index operation
# and represents the original geometry collections
result = exploded.dissolve(by="level_0")[key_order]
if (result.shape[0] != orig_num_geoms) and keep_geom_type_warning:
num_dropped = orig_num_geoms - result.shape[0]
warnings.warn(
"`keep_geom_type=True` in overlay resulted in {} dropped "
"geometries of different geometry types than df1 has. "
"Set `keep_geom_type=False` to retain all "
"geometries".format(num_dropped),
UserWarning,
stacklevel=2,
)
result.reset_index(drop=True, inplace=True)
result.drop(["__idx1", "__idx2"], axis=1, inplace=True)
return result