From 739d04ebe5a4a0b8eb52c84fade844d6554cc703 Mon Sep 17 00:00:00 2001 From: Kelsey Jordahl Date: Sun, 3 Nov 2013 15:58:56 -0500 Subject: [PATCH 1/2] ENH: Add a coordinate indexer to allow slicing of GeoSeries by x, y coordinates --- geopandas/geoseries.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/geopandas/geoseries.py b/geopandas/geoseries.py index 06a2f14..a1f4267 100644 --- a/geopandas/geoseries.py +++ b/geopandas/geoseries.py @@ -5,9 +5,10 @@ import fiona from fiona.crs import from_epsg import numpy as np from pandas import Series, DataFrame +from pandas.core.indexing import _NDFrameIndexer from pandas.util.decorators import cache_readonly import pyproj -from shapely.geometry import shape, Polygon, Point +from shapely.geometry import box, shape, Polygon, Point from shapely.geometry.collection import GeometryCollection from shapely.geometry.base import BaseGeometry from shapely.ops import cascaded_union, unary_union, transform @@ -29,6 +30,28 @@ def _is_empty(x): return False +class _CoordinateIndexer(_NDFrameIndexer): + """ Indexing by coordinate slices """ + def _getitem_tuple(self, tup): + obj = self.obj + xs, ys = tup + # handle numeric values as x and/or y coordinate index + if type(xs) is not slice: + xs = slice(xs, xs) + if type(ys) is not slice: + ys = slice(ys, ys) + # don't know how to handle step; should this raise? + if xs.step is not None or ys.step is not None: + warn("Ignoring step - full interval is used.") + xmin, ymin, xmax, ymax = obj.total_bounds + bbox = box(xs.start or xmin, + ys.start or ymin, + xs.stop or xmax, + ys.stop or ymax) + idx = obj.intersects(bbox) + return obj[idx] + + class GeoSeries(Series): """A Series object designed to store shapely geometry objects.""" _metadata = ['name', 'crs'] @@ -620,3 +643,5 @@ class GeoSeries(Series): result.__class__ = GeoSeries result.crs = crs return result + +GeoSeries._create_indexer('cx', _CoordinateIndexer) From 3062dc9638d1d3ca81996faf7e31536cfeef7135 Mon Sep 17 00:00:00 2001 From: Kelsey Jordahl Date: Sun, 3 Nov 2013 16:08:41 -0500 Subject: [PATCH 2/2] TST: Tests for coordinate slices --- tests/test_geoseries.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_geoseries.py b/tests/test_geoseries.py index 28af929..acee152 100644 --- a/tests/test_geoseries.py +++ b/tests/test_geoseries.py @@ -292,3 +292,9 @@ class TestSeries(unittest.TestCase): self.assertEqual(self.landmarks.total_bounds, bbox) self.assertEqual(self.g1.total_bounds, (0, 0, 1, 1)) + def test_coord_slice(self): + """ Test CoordinateSlicer """ + # need some better test cases + self.assertTrue(geom_equals(self.g3, self.g3.cx[:, :])) + self.assertTrue(geom_equals(self.g3[[True, False]], self.g3.cx[0.9:, :0.1])) + self.assertTrue(geom_equals(self.g3[[False, True]], self.g3.cx[0:0.1, 0.9:1.0]))