diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py index 3091e52..cd9c475 100644 --- a/geopandas/geodataframe.py +++ b/geopandas/geodataframe.py @@ -68,7 +68,7 @@ class GeoDataFrame(DataFrame): def set_geometry(self, col, drop=False, inplace=False, crs=None): """ - Set the GeoDataFrame geometry using either an existing column or + Set the GeoDataFrame geometry using either an existing column or the specified input. By default yields a new object. The original geometry column is replaced with the input. @@ -80,6 +80,10 @@ class GeoDataFrame(DataFrame): Delete column to be used as the new geometry inplace : boolean, default False Modify the GeoDataFrame in place (do not create a new object) + crs : str/result of fion.get_crs (optional) + Coordinate system to use. If passed, overrides both DataFrame and + col's crs. Otherwise, tries to get crs from passed col values or + DataFrame. Examples -------- @@ -96,7 +100,8 @@ class GeoDataFrame(DataFrame): else: frame = self.copy() - crs = crs or self.crs + if not crs: + crs = getattr(col, 'crs', self.crs) to_remove = None geo_column_name = DEFAULT_GEO_COLUMN_NAME @@ -122,6 +127,11 @@ class GeoDataFrame(DataFrame): if to_remove: del frame[to_remove] + if isinstance(level, GeoSeries) and level.crs != crs: + # avoids caching issues/crs sharing issues + level = level.copy() + level.crs = crs + frame[geo_column_name] = level frame._geometry_column_name = geo_column_name frame.crs = crs diff --git a/tests/test_geodataframe.py b/tests/test_geodataframe.py index 8e4486e..bacbc55 100644 --- a/tests/test_geodataframe.py +++ b/tests/test_geodataframe.py @@ -73,6 +73,11 @@ class TestDataFrame(unittest.TestCase): tu.assert_geoseries_equal(df.geometry, new_geom) tu.assert_geoseries_equal(df['geometry'], new_geom) + # new crs + gs = GeoSeries(new_geom, crs="epsg:26018") + df.geometry = gs + self.assertEqual(df.crs, "epsg:26018") + def test_geometry_property_errors(self): # TODO: Much cleaner if we use pandas test options (since assertRaises # contextmanager and friends not available in 2.6), but need 0.13 for @@ -124,6 +129,21 @@ class TestDataFrame(unittest.TestCase): self.assertRaises(ValueError, self.df.set_geometry, self.df) + # new crs - setting should default to GeoSeries' crs + gs = GeoSeries(geom, crs="epsg:26018") + new_df = self.df.set_geometry(gs) + self.assertEqual(new_df.crs, "epsg:26018") + + # explicit crs overrides self and dataframe + new_df = self.df.set_geometry(gs, crs="epsg:27159") + self.assertEqual(new_df.crs, "epsg:27159") + self.assertEqual(new_df.geometry.crs, "epsg:27159") + + # Series should use dataframe's + new_df = self.df.set_geometry(geom.values) + self.assertEqual(new_df.crs, self.df.crs) + self.assertEqual(new_df.geometry.crs, self.df.crs) + def test_set_geometry_col(self): g = self.df.geometry g_simplified = g.simplify(100)