mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-25 13:40:11 +08:00
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:
co-authored by
Martin Fleischmann
Joris Van den Bossche
parent
01943827b0
commit
4a650af202
@@ -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"]
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user