This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git
The following commit(s) were added to refs/heads/master by this push:
new c7b5a7f69b [GH-2016] Geopandas.GeoSeries: Implement x(), y(), z(),
has_z (#2017)
c7b5a7f69b is described below
commit c7b5a7f69b1ae5cad2e8ea29cdbade807516a9cc
Author: Peter Nguyen <[email protected]>
AuthorDate: Tue Jul 1 14:56:15 2025 -0700
[GH-2016] Geopandas.GeoSeries: Implement x(), y(), z(), has_z (#2017)
* Implement x(), y(), z()
* Change None to np.nan
Co-authored-by: Copilot <[email protected]>
* Implemnet has_z
---------
Co-authored-by: Copilot <[email protected]>
---
python/sedona/geopandas/geoseries.py | 114 +++++++++++++++++++--
python/tests/geopandas/test_geoseries.py | 34 +++++-
.../tests/geopandas/test_match_geopandas_series.py | 23 ++++-
3 files changed, 157 insertions(+), 14 deletions(-)
diff --git a/python/sedona/geopandas/geoseries.py
b/python/sedona/geopandas/geoseries.py
index 4dc612d171..5844b3b21d 100644
--- a/python/sedona/geopandas/geoseries.py
+++ b/python/sedona/geopandas/geoseries.py
@@ -619,9 +619,37 @@ class GeoSeries(GeoFrame, pspd.Series):
raise NotImplementedError("This method is not implemented yet.")
@property
- def has_z(self):
- # Implementation of the abstract method
- raise NotImplementedError("This method is not implemented yet.")
+ def has_z(self) -> pspd.Series:
+ """Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
+ features that have a z-component.
+
+ Notes
+ -----
+ Every operation in GeoPandas is planar, i.e. the potential third
+ dimension is not taken into account.
+
+ Examples
+ --------
+ >>> from shapely.geometry import Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Point(0, 1),
+ ... Point(0, 1, 2),
+ ... ]
+ ... )
+ >>> s
+ 0 POINT (0 1)
+ 1 POINT Z (0 1 2)
+ dtype: geometry
+
+ >>> s.has_z
+ 0 False
+ 1 True
+ dtype: bool
+ """
+ return self._process_geometry_column(
+ "ST_HasZ", rename="has_z"
+ ).to_spark_pandas()
def get_precision(self):
# Implementation of the abstract method
@@ -865,15 +893,89 @@ class GeoSeries(GeoFrame, pspd.Series):
@property
def x(self) -> pspd.Series:
- raise NotImplementedError("GeoSeries.x() is not implemented yet.")
+ """Return the x location of point geometries in a GeoSeries
+
+ Returns
+ -------
+ pandas.Series
+
+ Examples
+ --------
+
+ >>> from shapely.geometry import Point
+ >>> s = geopandas.GeoSeries([Point(1, 1), Point(2, 2), Point(3, 3)])
+ >>> s.x
+ 0 1.0
+ 1 2.0
+ 2 3.0
+ dtype: float64
+
+ See Also
+ --------
+
+ GeoSeries.y
+ GeoSeries.z
+
+ """
+ return self._process_geometry_column("ST_X",
rename="x").to_spark_pandas()
@property
def y(self) -> pspd.Series:
- raise NotImplementedError("GeoSeries.y() is not implemented yet.")
+ """Return the y location of point geometries in a GeoSeries
+
+ Returns
+ -------
+ pandas.Series
+
+ Examples
+ --------
+
+ >>> from shapely.geometry import Point
+ >>> s = geopandas.GeoSeries([Point(1, 1), Point(2, 2), Point(3, 3)])
+ >>> s.y
+ 0 1.0
+ 1 2.0
+ 2 3.0
+ dtype: float64
+
+ See Also
+ --------
+
+ GeoSeries.x
+ GeoSeries.z
+ GeoSeries.m
+
+ """
+ return self._process_geometry_column("ST_Y",
rename="y").to_spark_pandas()
@property
def z(self) -> pspd.Series:
- raise NotImplementedError("GeoSeries.z() is not implemented yet.")
+ """Return the z location of point geometries in a GeoSeries
+
+ Returns
+ -------
+ pandas.Series
+
+ Examples
+ --------
+
+ >>> from shapely.geometry import Point
+ >>> s = geopandas.GeoSeries([Point(1, 1, 1), Point(2, 2, 2), Point(3,
3, 3)])
+ >>> s.z
+ 0 1.0
+ 1 2.0
+ 2 3.0
+ dtype: float64
+
+ See Also
+ --------
+
+ GeoSeries.x
+ GeoSeries.y
+ GeoSeries.m
+
+ """
+ return self._process_geometry_column("ST_Z",
rename="z").to_spark_pandas()
@property
def m(self) -> pspd.Series:
diff --git a/python/tests/geopandas/test_geoseries.py
b/python/tests/geopandas/test_geoseries.py
index 0c13e92673..cc1b3338b3 100644
--- a/python/tests/geopandas/test_geoseries.py
+++ b/python/tests/geopandas/test_geoseries.py
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
+import numpy as np
import pytest
import pandas as pd
import geopandas as gpd
@@ -77,13 +78,28 @@ class TestGeoSeries(TestBase):
)
def test_x(self):
- pass
+ geoseries = sgpd.GeoSeries(
+ [Point(0, -1, 2.5), Point(2.5, 0, -1), Point(-1, 2.5, 0),
Point(-1, 0)]
+ )
+ result = geoseries.x.to_pandas()
+ expected = pd.Series([0, 2.5, -1, -1])
+ assert_series_equal(result, expected)
def test_y(self):
- pass
+ geoseries = sgpd.GeoSeries(
+ [Point(0, -1, 2.5), Point(2.5, 0, -1), Point(-1, 2.5, 0),
Point(-1, 0)]
+ )
+ result = geoseries.y.to_pandas()
+ expected = pd.Series([-1, 0, 2.5, 0])
+ assert_series_equal(result, expected)
def test_z(self):
- pass
+ geoseries = sgpd.GeoSeries(
+ [Point(0, -1, 2.5), Point(2.5, 0, -1), Point(-1, 2.5, 0),
Point(-1, 0)]
+ )
+ result = geoseries.z.to_pandas()
+ expected = pd.Series([2.5, -1, 0, np.nan])
+ assert_series_equal(result, expected)
def test_m(self):
pass
@@ -204,7 +220,17 @@ class TestGeoSeries(TestBase):
pass
def test_has_z(self):
- pass
+ s = sgpd.GeoSeries(
+ [
+ Point(0, 1),
+ Point(0, 1, 2),
+ Polygon([(0, 0, 1), (0, 1, 2), (1, 1, 3), (0, 0, 1)]),
+ Polygon([(0, 0), (0, 1), (1, 1), (0, 0)]),
+ ]
+ )
+ result = s.has_z
+ expected = pd.Series([False, True, True, False])
+ assert_series_equal(result.to_pandas(), expected)
def test_get_precision(self):
pass
diff --git a/python/tests/geopandas/test_match_geopandas_series.py
b/python/tests/geopandas/test_match_geopandas_series.py
index fee2fa565d..c55db097db 100644
--- a/python/tests/geopandas/test_match_geopandas_series.py
+++ b/python/tests/geopandas/test_match_geopandas_series.py
@@ -213,13 +213,25 @@ class TestMatchGeopandasSeries(TestBase):
self.check_sgpd_equals_gpd(sgpd_result, gpd_result)
def test_x(self):
- pass
+ for pt in self.points:
+ sgpd_result = GeoSeries(pt).x
+ assert isinstance(sgpd_result, ps.Series)
+ gpd_result = gpd.GeoSeries(pt).x
+ self.check_pd_series_equal(sgpd_result, gpd_result)
def test_y(self):
- pass
+ for pt in self.points:
+ sgpd_result = GeoSeries(pt).y
+ assert isinstance(sgpd_result, ps.Series)
+ gpd_result = gpd.GeoSeries(pt).y
+ self.check_pd_series_equal(sgpd_result, gpd_result)
def test_z(self):
- pass
+ for pt in self.points:
+ sgpd_result = GeoSeries(pt).z
+ assert isinstance(sgpd_result, ps.Series)
+ gpd_result = gpd.GeoSeries(pt).z
+ self.check_pd_series_equal(sgpd_result, gpd_result)
def test_m(self):
pass
@@ -328,7 +340,10 @@ class TestMatchGeopandasSeries(TestBase):
pass
def test_has_z(self):
- pass
+ for _, geom in self.geoms:
+ sgpd_result = GeoSeries(geom).has_z
+ gpd_result = gpd.GeoSeries(geom).has_z
+ self.check_pd_series_equal(sgpd_result, gpd_result)
def test_get_precision(self):
pass