BUG: convert_dtypes() converts GeoDataFrame to DataFrame (#2115)

* TST: test documenting existing convert dtypes behaviour

* TST: fix tests, compare to proper reference case

* BUG: overload convert_dtypes to fix GH1870

* COMPAT: update tests to handle pandas 1.0 and 0.25

* DOC: update wording to suggested

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

* CLN: simplify to *args and **kwargs following suggestion

Co-authored-by: Martin Fleischmann <martin@martinfleischmann.net>
This commit is contained in:
Matt Richards
2021-09-20 09:45:38 +01:00
committed by GitHub
co-authored by Martin Fleischmann
parent 0fe01e899b
commit b67ba848a7
2 changed files with 64 additions and 0 deletions
+28
View File
@@ -1652,6 +1652,34 @@ box': (2.0, 1.0, 2.0, 1.0)}], 'bbox': (1.0, 1.0, 2.0, 2.0)}
# do not return a GeoDataFrame
return pd.DataFrame(df)
def convert_dtypes(self, *args, **kwargs):
"""
Convert columns to best possible dtypes using dtypes supporting ``pd.NA``.
Always returns a GeoDataFrame as no conversions are applied to the
geometry column.
See the pandas.DataFrame.convert_dtypes docstring for more details.
Returns
-------
GeoDataFrame
"""
# Overridden to fix GH1870, that return type is not preserved always
# (and where it was, geometry col was not)
if not compat.PANDAS_GE_10:
raise NotImplementedError(
"GeoDataFrame.convert_dtypes requires pandas >= 1.0"
)
return GeoDataFrame(
super().convert_dtypes(*args, **kwargs),
geometry=self.geometry.name,
crs=self.crs,
)
def to_postgis(
self,
name,
+36
View File
@@ -262,6 +262,42 @@ def test_astype_invalid_geodataframe():
assert res["a"].dtype == object
@pytest.mark.xfail(
not compat.PANDAS_GE_10,
reason="Convert dtypes new in pandas 1.0",
raises=NotImplementedError,
)
def test_convert_dtypes(df):
# https://github.com/geopandas/geopandas/issues/1870
# Test geometry col is first col, first, geom_col_name=geometry
# (order is important in concat, used internally)
res1 = df.convert_dtypes() # note res1 done first for pandas < 1 xfail check
expected1 = GeoDataFrame(
pd.DataFrame(df).convert_dtypes(), crs=df.crs, geometry=df.geometry.name
)
# Checking type and metadata are right
assert_geodataframe_equal(expected1, res1)
# Test geom last, geom_col_name=geometry
res2 = df[["value1", "value2", "geometry"]].convert_dtypes()
assert_geodataframe_equal(expected1[["value1", "value2", "geometry"]], res2)
# Test again with crs set and custom geom col name
df2 = df.set_crs(epsg=4326).rename_geometry("points")
expected2 = GeoDataFrame(
pd.DataFrame(df2).convert_dtypes(), crs=df2.crs, geometry=df2.geometry.name
)
res3 = df2.convert_dtypes()
assert_geodataframe_equal(expected2, res3)
# Test geom last, geom_col=geometry
res4 = df2[["value1", "value2", "points"]].convert_dtypes()
assert_geodataframe_equal(expected2[["value1", "value2", "points"]], res4)
def test_to_csv(df):
exp = (