diff --git a/.gitignore b/.gitignore
index 1cfe9fe..8eefebd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,7 +61,7 @@ examples/nybb_*.zip
doc/source/savefig
doc/source/reference
-doc/source/docs/reference/api
+doc/source/docs/reference/api/*.rst
geopandas.egg-info
geopandas/version.py
diff --git a/doc/source/_static/binary_geo-difference.svg b/doc/source/_static/binary_geo-difference.svg
new file mode 100644
index 0000000..d430d25
--- /dev/null
+++ b/doc/source/_static/binary_geo-difference.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/_static/binary_geo-intersection.svg b/doc/source/_static/binary_geo-intersection.svg
new file mode 100644
index 0000000..2a06f5b
--- /dev/null
+++ b/doc/source/_static/binary_geo-intersection.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/_static/binary_geo-symm_diff.svg b/doc/source/_static/binary_geo-symm_diff.svg
new file mode 100644
index 0000000..f33736b
--- /dev/null
+++ b/doc/source/_static/binary_geo-symm_diff.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/_static/binary_geo-union.svg b/doc/source/_static/binary_geo-union.svg
new file mode 100644
index 0000000..1c6901a
--- /dev/null
+++ b/doc/source/_static/binary_geo-union.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/_static/binary_op-01.svg b/doc/source/_static/binary_op-01.svg
new file mode 100644
index 0000000..3bedcb6
--- /dev/null
+++ b/doc/source/_static/binary_op-01.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/_static/binary_op-02.svg b/doc/source/_static/binary_op-02.svg
new file mode 100644
index 0000000..a8d4087
--- /dev/null
+++ b/doc/source/_static/binary_op-02.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/_static/binary_op-03.svg b/doc/source/_static/binary_op-03.svg
new file mode 100644
index 0000000..37b1fa6
--- /dev/null
+++ b/doc/source/_static/binary_op-03.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/doc/source/docs/reference/geoseries.rst b/doc/source/docs/reference/geoseries.rst
index 4f6bfd2..82726ac 100644
--- a/doc/source/docs/reference/geoseries.rst
+++ b/doc/source/docs/reference/geoseries.rst
@@ -49,11 +49,12 @@ Binary Predicates
.. autosummary::
:toctree: api/
- GeoSeries.geom_almost_equals
GeoSeries.contains
GeoSeries.crosses
GeoSeries.disjoint
GeoSeries.geom_equals
+ GeoSeries.geom_almost_equals
+ GeoSeries.geom_equals_exact
GeoSeries.intersects
GeoSeries.overlaps
GeoSeries.touches
diff --git a/geopandas/base.py b/geopandas/base.py
index b2e2802..a4edd73 100644
--- a/geopandas/base.py
+++ b/geopandas/base.py
@@ -24,11 +24,11 @@ def is_geometry_type(data):
return False
-def _delegate_binary_method(op, this, other, *args, **kwargs):
+def _delegate_binary_method(op, this, other, align, *args, **kwargs):
# type: (str, GeoSeries, GeoSeries) -> GeoSeries/Series
this = this.geometry
if isinstance(other, GeoPandasBase):
- if not this.index.equals(other.index):
+ if align and not this.index.equals(other.index):
warn("The indices of the two GeoSeries are different.")
this, other = this.align(other.geometry)
else:
@@ -45,19 +45,19 @@ def _delegate_binary_method(op, this, other, *args, **kwargs):
return data, this.index
-def _binary_geo(op, this, other):
+def _binary_geo(op, this, other, align):
# type: (str, GeoSeries, GeoSeries) -> GeoSeries
"""Binary operation on GeoSeries objects that returns a GeoSeries"""
from .geoseries import GeoSeries
- geoms, index = _delegate_binary_method(op, this, other)
+ geoms, index = _delegate_binary_method(op, this, other, align)
return GeoSeries(geoms.data, index=index, crs=this.crs)
-def _binary_op(op, this, other, *args, **kwargs):
+def _binary_op(op, this, other, align, *args, **kwargs):
# type: (str, GeoSeries, GeoSeries, args/kwargs) -> Series[bool/float]
"""Binary operation on GeoSeries objects that returns a Series"""
- data, index = _delegate_binary_method(op, this, other, *args, **kwargs)
+ data, index = _delegate_binary_method(op, this, other, align, *args, **kwargs)
return Series(data, index=index)
@@ -727,9 +727,9 @@ GeometryCollection
# Binary operations that return a pandas Series
#
- def contains(self, other):
+ def contains(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that contains `other`.
+ each aligned geometry that contains `other`.
An object is said to contain `other` if its `interior` contains the
`boundary` and `interior` of the other object and their boundaries do
@@ -738,36 +738,230 @@ GeometryCollection
This is the inverse of :meth:`within` in the sense that the expression
``a.contains(b) == b.within(a)`` always evaluates to ``True``.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if is
contained.
- """
- return _binary_op("contains", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def geom_equals(self, other):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(0, 0), (0, 2)]),
+ ... LineString([(0, 0), (0, 1)]),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(0, 4),
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (1, 2), (0, 2)]),
+ ... LineString([(0, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 1 LINESTRING (0.00000 0.00000, 0.00000 2.00000)
+ 2 LINESTRING (0.00000 0.00000, 0.00000 1.00000)
+ 3 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 POLYGON ((0.00000 0.00000, 1.00000 2.00000, 0....
+ 3 LINESTRING (0.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries contains a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> point = Point(0, 1)
+ >>> s.contains(point)
+ 0 False
+ 1 True
+ 2 False
+ 3 True
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s2.contains(s, align=True)
+ 0 False
+ 1 False
+ 2 False
+ 3 True
+ 4 False
+ dtype: bool
+
+ >>> s2.contains(s, align=False)
+ 1 True
+ 2 False
+ 3 True
+ 4 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries ``contains`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.within
+ """
+ return _binary_op("contains", self, other, align)
+
+ def geom_equals(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry equal to `other`.
+ each aligned geometry equal to `other`.
An object is said to be equal to `other` if its set-theoretic
`boundary`, `interior`, and `exterior` coincides with those of the
other.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test for
equality.
- """
- return _binary_op("geom_equals", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def geom_almost_equals(self, other, decimal=6):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (1, 2), (0, 2)]),
+ ... LineString([(0, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (1, 2), (0, 2)]),
+ ... Point(0, 1),
+ ... LineString([(0, 0), (0, 2)]),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 1.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 POLYGON ((0.00000 0.00000, 1.00000 2.00000, 0....
+ 3 POINT (0.00000 1.00000)
+ 4 LINESTRING (0.00000 0.00000, 0.00000 2.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries contains a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> polygon = Polygon([(0, 0), (2, 2), (0, 2)])
+ >>> s.geom_equals(polygon)
+ 0 True
+ 1 False
+ 2 False
+ 3 False
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.geom_equals(s2)
+ 0 False
+ 1 False
+ 2 False
+ 3 True
+ 4 False
+ dtype: bool
+
+ >>> s.geom_equals(s2, align=False)
+ 0 True
+ 1 True
+ 2 False
+ 3 False
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries is equal to *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.geom_almost_equals
+ GeoSeries.geom_equals_exact
+
+ """
+ return _binary_op("geom_equals", self, other, align)
+
+ def geom_almost_equals(self, other, decimal=6, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` if
- each geometry is approximately equal to `other`.
+ each aligned geometry is approximately equal to `other`.
Approximate equality is tested at all points to the specified `decimal`
- place precision. See also :meth:`geom_equals`.
+ place precision.
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
Parameters
----------
@@ -775,90 +969,677 @@ GeometryCollection
The GeoSeries (elementwise) or geometric object to compare to.
decimal : int
Decimal place presion used when testing for approximate equality.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
+
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Point(0, 1.1),
+ ... Point(0, 1.01),
+ ... Point(0, 1.001),
+ ... ],
+ ... )
+
+ >>> s
+ 0 POINT (0.00000 1.10000)
+ 1 POINT (0.00000 1.01000)
+ 2 POINT (0.00000 1.00100)
+ dtype: geometry
+
+
+ >>> s.geom_almost_equals(Point(0, 1), decimal=2)
+ 0 False
+ 1 False
+ 2 True
+ dtype: bool
+
+ >>> s.geom_almost_equals(Point(0, 1), decimal=1)
+ 0 False
+ 1 True
+ 2 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries is equal to *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.geom_equals
+ GeoSeries.geom_equals_exact
+
"""
- return _binary_op("geom_almost_equals", self, other, decimal=decimal)
+ return _binary_op(
+ "geom_almost_equals", self, other, decimal=decimal, align=align
+ )
- def geom_equals_exact(self, other, tolerance):
- """Return True for all geometries that equal *other* to a given
- tolerance, else False"""
- return _binary_op("geom_equals_exact", self, other, tolerance=tolerance)
+ def geom_equals_exact(self, other, tolerance, align=True):
+ """Return True for all geometries that equal aligned *other* to a given
+ tolerance, else False.
- def crosses(self, other):
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
+ Parameters
+ ----------
+ other : GeoSeries or geometric object
+ The GeoSeries (elementwise) or geometric object to compare to.
+ tolerance : float
+ Decimal place presion used when testing for approximate equality.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
+
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Point(0, 1.1),
+ ... Point(0, 1.0),
+ ... Point(0, 1.2),
+ ... ]
+ ... )
+
+ >>> s
+ 0 POINT (0.00000 1.10000)
+ 1 POINT (0.00000 1.00000)
+ 2 POINT (0.00000 1.20000)
+ dtype: geometry
+
+
+ >>> s.geom_equals_exact(Point(0, 1), tolerance=0.1)
+ 0 False
+ 1 True
+ 2 False
+ dtype: bool
+
+ >>> s.geom_equals_exact(Point(0, 1), tolerance=0.15)
+ 0 True
+ 1 True
+ 2 False
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries is equal to *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.geom_equals
+ GeoSeries.geom_almost_equals
+ """
+ return _binary_op(
+ "geom_equals_exact", self, other, tolerance=tolerance, align=align
+ )
+
+ def crosses(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that cross `other`.
+ each aligned geometry that cross `other`.
An object is said to cross `other` if its `interior` intersects the
`interior` of the other but does not contain it, and the dimension of
the intersection is less than the dimension of the one or the other.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if is
crossed.
- """
- return _binary_op("crosses", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def disjoint(self, other):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 2 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 2 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (1.00000 1.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries crosses a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> line = LineString([(-1, 1), (3, 1)])
+ >>> s.crosses(line)
+ 0 True
+ 1 True
+ 2 True
+ 3 False
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.crosses(s2, align=True)
+ 0 False
+ 1 True
+ 2 False
+ 3 False
+ 4 False
+ dtype: bool
+
+ >>> s.crosses(s2, align=False)
+ 0 True
+ 1 True
+ 2 False
+ 3 False
+ dtype: bool
+
+ Notice that a line does not cross a point that it contains.
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries ``crosses`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.disjoint
+ GeoSeries.intersects
+
+ """
+ return _binary_op("crosses", self, other, align)
+
+ def disjoint(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry disjoint to `other`.
+ each aligned geometry disjoint to `other`.
An object is said to be disjoint to `other` if its `boundary` and
`interior` does not intersect at all with those of the other.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if is
disjoint.
- """
- return _binary_op("disjoint", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def intersects(self, other):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(-1, 0), (-1, 2), (0, -2)]),
+ ... LineString([(0, 0), (0, 1)]),
+ ... Point(1, 1),
+ ... Point(0, 0),
+ ... ],
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 2 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 0 POLYGON ((-1.00000 0.00000, -1.00000 2.00000, ...
+ 1 LINESTRING (0.00000 0.00000, 0.00000 1.00000)
+ 2 POINT (1.00000 1.00000)
+ 3 POINT (0.00000 0.00000)
+ dtype: geometry
+
+ We can check each geometry of GeoSeries to a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> line = LineString([(0, 0), (2, 0)])
+ >>> s.disjoint(line)
+ 0 False
+ 1 False
+ 2 False
+ 3 True
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.disjoint(s2)
+ 0 True
+ 1 False
+ 2 False
+ 3 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries is equal to *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.intersects
+ GeoSeries.touches
+
+ """
+ return _binary_op("disjoint", self, other, align)
+
+ def intersects(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that intersects `other`.
+ each aligned geometry that intersects `other`.
An object is said to intersect `other` if its `boundary` and `interior`
intersects in any way with those of the other.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if is
intersected.
- """
- return _binary_op("intersects", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def overlaps(self, other):
- """Returns True for all geometries that overlap *other*, else False.
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 2 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 2 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (1.00000 1.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries crosses a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> line = LineString([(-1, 1), (3, 1)])
+ >>> s.intersects(line)
+ 0 True
+ 1 True
+ 2 True
+ 3 True
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.intersects(s2, align=True)
+ 0 False
+ 1 True
+ 2 True
+ 3 False
+ 4 False
+ dtype: bool
+
+ >>> s.intersects(s2, align=False)
+ 0 True
+ 1 True
+ 2 True
+ 3 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries ``crosses`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.disjoint
+ GeoSeries.crosses
+ GeoSeries.touches
+ GeoSeries.intersection
+ """
+ return _binary_op("intersects", self, other, align)
+
+ def overlaps(self, other, align=True):
+ """Returns True for all aligned geometries that overlap *other*, else False.
+
+ Geometries overlaps if they have more than one but not all
+ points in common, have the same dimension, and the intersection of the
+ interiors of the geometries has the same dimension as the geometries
+ themselves.
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if
overlaps.
- """
- return _binary_op("overlaps", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def touches(self, other):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, MultiPoint, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... MultiPoint([(0, 0), (0, 1)]),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 0), (0, 2)]),
+ ... LineString([(0, 1), (1, 1)]),
+ ... LineString([(1, 1), (3, 3)]),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 MULTIPOINT (0.00000 0.00000, 0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 2.00000 0.00000, 0....
+ 2 LINESTRING (0.00000 1.00000, 1.00000 1.00000)
+ 3 LINESTRING (1.00000 1.00000, 3.00000 3.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries overlaps a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
+ >>> s.overlaps(polygon)
+ 0 True
+ 1 True
+ 2 False
+ 3 False
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.overlaps(s2)
+ 0 False
+ 1 True
+ 2 False
+ 3 False
+ 4 False
+ dtype: bool
+
+ >>> s.overlaps(s2, align=False)
+ 0 True
+ 1 False
+ 2 True
+ 3 False
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries ``overlaps`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.crosses
+ GeoSeries.intersects
+
+ """
+ return _binary_op("overlaps", self, other, align)
+
+ def touches(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that touches `other`.
+ each aligned geometry that touches `other`.
An object is said to touch `other` if it has at least one point in
common with `other` and its interior does not intersect with any part
- of the other.
+ of the other. Overlapping features therefore do not touch.
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if is
touched.
- """
- return _binary_op("touches", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def within(self, other):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, MultiPoint, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... MultiPoint([(0, 0), (0, 1)]),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (-2, 0), (0, -2)]),
+ ... LineString([(0, 1), (1, 1)]),
+ ... LineString([(1, 1), (3, 0)]),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 MULTIPOINT (0.00000 0.00000, 0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, -2.00000 0.00000, 0...
+ 2 LINESTRING (0.00000 1.00000, 1.00000 1.00000)
+ 3 LINESTRING (1.00000 1.00000, 3.00000 0.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries touches a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+
+ >>> line = LineString([(0, 0), (-1, -2)])
+ >>> s.touches(line)
+ 0 True
+ 1 True
+ 2 True
+ 3 True
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.touches(s2, align=True)
+ 0 False
+ 1 True
+ 2 True
+ 3 False
+ 4 False
+ dtype: bool
+
+ >>> s.touches(s2, align=False)
+ 0 True
+ 1 False
+ 2 True
+ 3 False
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries ``touches`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.overlaps
+ GeoSeries.intersects
+
+ """
+ return _binary_op("touches", self, other, align)
+
+ def within(self, other, align=True):
"""Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that is within `other`.
+ each aligned geometry that is within `other`.
An object is said to be within `other` if its `boundary` and `interior`
intersects only with the `interior` of the other (not its `boundary` or
@@ -868,23 +1649,121 @@ GeometryCollection
expression ``a.within(b) == b.contains(a)`` always evaluates to
``True``.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : GeoSeries or geometric object
The GeoSeries (elementwise) or geometric object to test if each
geometry is within.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
+ Returns
+ -------
+ Series (bool)
+
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (1, 2), (0, 2)]),
+ ... LineString([(0, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(0, 0), (0, 2)]),
+ ... LineString([(0, 0), (0, 1)]),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 1.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 0.00000 2.00000)
+ 3 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 0.00000 2.00000)
+ 3 LINESTRING (0.00000 0.00000, 0.00000 1.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries is within a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> polygon = Polygon([(0, 0), (2, 2), (0, 2)])
+ >>> s.within(polygon)
+ 0 True
+ 1 True
+ 2 False
+ 3 False
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s2.within(s)
+ 0 False
+ 1 False
+ 2 True
+ 3 False
+ 4 False
+ dtype: bool
+
+ >>> s2.within(s, align=False)
+ 1 True
+ 2 False
+ 3 True
+ 4 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries is ``within`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.contains
"""
- return _binary_op("within", self, other)
+ return _binary_op("within", self, other, align)
- def covers(self, other):
+ def covers(self, other, align=True):
"""
Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that is entirely covering `other`.
+ each aligned geometry that is entirely covering `other`.
An object A is said to cover another object B if no points of B lie
in the exterior of A.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
See
https://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html
for reference.
@@ -893,17 +1772,111 @@ GeometryCollection
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to check is being covered.
- """
- return _binary_geo("covers", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def covered_by(self, other):
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... Point(0, 0),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)]),
+ ... Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
+ ... LineString([(1, 1), (1.5, 1.5)]),
+ ... Point(0, 0),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 0.00000, 2....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 POINT (0.00000 0.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.50000 0.50000, 1.50000 0.50000, 1....
+ 2 POLYGON ((0.00000 0.00000, 2.00000 0.00000, 2....
+ 3 LINESTRING (1.00000 1.00000, 1.50000 1.50000)
+ 4 POINT (0.00000 0.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries covers a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> poly = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
+ >>> s.covers(poly)
+ 0 True
+ 1 False
+ 2 False
+ 3 False
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.covers(s2, align=True)
+ 0 False
+ 1 False
+ 2 False
+ 3 False
+ 4 False
+ dtype: bool
+
+ >>> s.covers(s2, align=False)
+ 0 True
+ 1 False
+ 2 True
+ 3 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries ``covers`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.covered_by
+ GeoSeries.overlaps
+ """
+ return _binary_op("covers", self, other, align)
+
+ def covered_by(self, other, align=True):
"""
Returns a ``Series`` of ``dtype('bool')`` with value ``True`` for
- each geometry that is entirely covered by `other`.
+ each aligned geometry that is entirely covered by `other`.
An object A is said to cover another object B if no points of B lie
in the exterior of A.
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
See
https://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html
for reference.
@@ -912,74 +1885,649 @@ GeometryCollection
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to check is being covered.
- """
- return _binary_geo("covered_by", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def distance(self, other):
- """Returns a ``Series`` containing the distance to `other`.
+ Returns
+ -------
+ Series (bool)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)]),
+ ... Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
+ ... LineString([(1, 1), (1.5, 1.5)]),
+ ... Point(0, 0),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... Point(0, 0),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.50000 0.50000, 1.50000 0.50000, 1....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 0.00000, 2....
+ 2 LINESTRING (1.00000 1.00000, 1.50000 1.50000)
+ 3 POINT (0.00000 0.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 2.00000 0.00000, 2....
+ 2 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 3 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 4 POINT (0.00000 0.00000)
+ dtype: geometry
+
+ We can check if each geometry of GeoSeries is covered by a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> poly = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
+ >>> s.covered_by(poly)
+ 0 True
+ 1 True
+ 2 True
+ 3 True
+ dtype: bool
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.covered_by(s2, align=True)
+ 0 False
+ 1 True
+ 2 True
+ 3 True
+ 4 False
+ dtype: bool
+
+ >>> s.covered_by(s2, align=False)
+ 0 True
+ 1 False
+ 2 True
+ 3 True
+ dtype: bool
+
+ Notes
+ -----
+ This method works in a row-wise manner. It does not check if an element
+ of one GeoSeries is ``covered_by`` *any* element of the other one.
+
+ See also
+ --------
+ GeoSeries.covers
+ GeoSeries.overlaps
+ """
+ return _binary_op("covered_by", self, other, align)
+
+ def distance(self, other, align=True):
+ """Returns a ``Series`` containing the distance to aligned `other`.
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
Parameters
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to find the
distance to.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
+
+
+ Returns
+ -------
+ Series (float)
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 0), (1, 1)]),
+ ... Polygon([(0, 0), (-1, 0), (-1, 1)]),
+ ... LineString([(1, 1), (0, 0)]),
+ ... Point(0, 0),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)]),
+ ... Point(3, 1),
+ ... LineString([(1, 0), (2, 0)]),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 5),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 1.00000 0.00000, 1....
+ 1 POLYGON ((0.00000 0.00000, -1.00000 0.00000, -...
+ 2 LINESTRING (1.00000 1.00000, 0.00000 0.00000)
+ 3 POINT (0.00000 0.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.50000 0.50000, 1.50000 0.50000, 1....
+ 2 POINT (3.00000 1.00000)
+ 3 LINESTRING (1.00000 0.00000, 2.00000 0.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can check the distance of each geometry of GeoSeries to a single
+ geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> point = Point(-1, 0)
+ >>> s.distance(point)
+ 0 1.0
+ 1 0.0
+ 2 1.0
+ 3 1.0
+ dtype: float64
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and use elements with the same index using
+ ``align=True`` or ignore index and use elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.distance(s2, align=True)
+ 0 NaN
+ 1 0.707107
+ 2 2.000000
+ 3 1.000000
+ 4 NaN
+ dtype: float64
+
+ >>> s.distance(s2, align=False)
+ 0 0.000000
+ 1 3.162278
+ 2 0.707107
+ 3 1.000000
+ dtype: float64
"""
- return _binary_op("distance", self, other)
+ return _binary_op("distance", self, other, align)
#
# Binary operations that return a GeoSeries
#
- def difference(self, other):
- """Returns a ``GeoSeries`` of the points in each geometry that
+ def difference(self, other, align=True):
+ """Returns a ``GeoSeries`` of the points in each aligned geometry that
are not in `other`.
+ .. image:: ../../../_static/binary_geo-difference.svg
+ :align: center
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to find the
difference to.
- """
- return _binary_geo("difference", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def symmetric_difference(self, other):
+ Returns
+ -------
+ GeoSeries
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 6),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 2 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (1.00000 1.00000)
+ 5 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can do difference of each geometry and a single
+ shapely geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> s.difference(Polygon([(0, 0), (1, 1), (0, 1)]))
+ 0 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 1 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 2 LINESTRING (1.00000 1.00000, 2.00000 2.00000)
+ 3 MULTILINESTRING ((2.00000 0.00000, 1.00000 1.0...
+ 4 POINT EMPTY
+ dtype: geometry
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.difference(s2, align=True)
+ 0 None
+ 1 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 2 MULTILINESTRING ((0.00000 0.00000, 1.00000 1.0...
+ 3 LINESTRING EMPTY
+ 4 POINT (0.00000 1.00000)
+ 5 None
+ dtype: geometry
+
+ >>> s.difference(s2, align=False)
+ 0 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 1 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 2 MULTILINESTRING ((0.00000 0.00000, 1.00000 1.0...
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT EMPTY
+ dtype: geometry
+
+ See Also
+ --------
+ GeoSeries.symmetric_difference
+ GeoSeries.union
+ GeoSeries.intersection
+ """
+ return _binary_geo("difference", self, other, align)
+
+ def symmetric_difference(self, other, align=True):
"""Returns a ``GeoSeries`` of the symmetric difference of points in
- each geometry with `other`.
+ each aligned geometry with `other`.
For each geometry, the symmetric difference consists of points in the
geometry not in `other`, and points in `other` not in the geometry.
+ .. image:: ../../../_static/binary_geo-symm_diff.svg
+ :align: center
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
+
Parameters
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to find the
symmetric difference to.
- """
- return _binary_geo("symmetric_difference", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def union(self, other):
- """Returns a ``GeoSeries`` of the union of points in each geometry with
+ Returns
+ -------
+ GeoSeries
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 6),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 2 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (1.00000 1.00000)
+ 5 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can do symmetric difference of each geometry and a single
+ shapely geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> s.symmetric_difference(Polygon([(0, 0), (1, 1), (0, 1)]))
+ 0 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 1 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 2 GEOMETRYCOLLECTION (LINESTRING (1.00000 1.0000...
+ 3 GEOMETRYCOLLECTION (LINESTRING (2.00000 0.0000...
+ 4 POLYGON ((0.00000 0.00000, 0.00000 1.00000, 1....
+ dtype: geometry
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.symmetric_difference(s2, align=True)
+ 0 None
+ 1 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 2 MULTILINESTRING ((0.00000 0.00000, 1.00000 1.0...
+ 3 LINESTRING EMPTY
+ 4 MULTIPOINT (0.00000 1.00000, 1.00000 1.00000)
+ 5 None
+ dtype: geometry
+
+ >>> s.symmetric_difference(s2, align=False)
+ 0 POLYGON ((0.00000 1.00000, 0.00000 2.00000, 2....
+ 1 GEOMETRYCOLLECTION (LINESTRING (1.00000 0.0000...
+ 2 MULTILINESTRING ((0.00000 0.00000, 1.00000 1.0...
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT EMPTY
+ dtype: geometry
+
+ See Also
+ --------
+ GeoSeries.difference
+ GeoSeries.union
+ GeoSeries.intersection
+ """
+ return _binary_geo("symmetric_difference", self, other, align)
+
+ def union(self, other, align=True):
+ """Returns a ``GeoSeries`` of the union of points in each aligned geometry with
`other`.
+ .. image:: ../../../_static/binary_geo-union.svg
+ :align: center
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
+
Parameters
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to find the union
with.
- """
- return _binary_geo("union", self, other)
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- def intersection(self, other):
+ Returns
+ -------
+ GeoSeries
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 6),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 2 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (1.00000 1.00000)
+ 5 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can do union of each geometry and a single
+ shapely geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> s.union(Polygon([(0, 0), (1, 1), (0, 1)]))
+ 0 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 1 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 2 GEOMETRYCOLLECTION (LINESTRING (1.00000 1.0000...
+ 3 GEOMETRYCOLLECTION (LINESTRING (2.00000 0.0000...
+ 4 POLYGON ((0.00000 0.00000, 0.00000 1.00000, 1....
+ dtype: geometry
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.union(s2, align=True)
+ 0 None
+ 1 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 2 MULTILINESTRING ((0.00000 0.00000, 1.00000 1.0...
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 MULTIPOINT (0.00000 1.00000, 1.00000 1.00000)
+ 5 None
+ dtype: geometry
+
+ >>> s.union(s2, align=False)
+ 0 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 1 GEOMETRYCOLLECTION (LINESTRING (1.00000 0.0000...
+ 2 MULTILINESTRING ((0.00000 0.00000, 1.00000 1.0...
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+
+ See Also
+ --------
+ GeoSeries.symmetric_difference
+ GeoSeries.difference
+ GeoSeries.intersection
+ """
+ return _binary_geo("union", self, other, align)
+
+ def intersection(self, other, align=True):
"""Returns a ``GeoSeries`` of the intersection of points in each
- geometry with `other`.
+ aligned geometry with `other`.
+
+ .. image:: ../../../_static/binary_geo-intersection.svg
+ :align: center
+
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : Geoseries or geometric object
The Geoseries (elementwise) or geometric object to find the
intersection with.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
+
+ Returns
+ -------
+ GeoSeries
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 6),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 2 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (1.00000 1.00000)
+ 5 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can also do intersection of each geometry and a single
+ shapely geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> s.intersection(Polygon([(0, 0), (1, 1), (0, 1)]))
+ 0 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 1 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 1.00000 1.00000)
+ 3 POINT (1.00000 1.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.intersection(s2, align=True)
+ 0 None
+ 1 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 2 POINT (1.00000 1.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT EMPTY
+ 5 None
+ dtype: geometry
+
+ >>> s.intersection(s2, align=False)
+ 0 POLYGON ((1.00000 1.00000, 0.00000 0.00000, 0....
+ 1 LINESTRING (1.00000 1.00000, 1.00000 2.00000)
+ 2 POINT (1.00000 1.00000)
+ 3 POINT (1.00000 1.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+
+ See Also
+ --------
+ GeoSeries.difference
+ GeoSeries.symmetric_difference
+ GeoSeries.union
"""
- return _binary_geo("intersection", self, other)
+ return _binary_geo("intersection", self, other, align)
#
# Other operations
@@ -1161,28 +2709,123 @@ GeometryCollection
"""
return _delegate_geo_method("simplify", self, *args, **kwargs)
- def relate(self, other):
+ def relate(self, other, align=True):
"""
Returns the DE-9IM intersection matrices for the geometries
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
Parameters
----------
other : BaseGeometry or GeoSeries
The other geometry to computed
the DE-9IM intersection matrices from.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
Returns
----------
spatial_relations: Series of strings
The DE-9IM intersection matrices which describe
the spatial relations of the other geometry.
- """
- return _binary_op("relate", self, other)
- def project(self, other, normalized=False):
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(0, 1),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (1, 1), (0, 1)]),
+ ... LineString([(1, 0), (1, 3)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... Point(1, 1),
+ ... Point(0, 1),
+ ... ],
+ ... index=range(1, 6),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 2 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POLYGON ((0.00000 0.00000, 1.00000 1.00000, 0....
+ 2 LINESTRING (1.00000 0.00000, 1.00000 3.00000)
+ 3 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ 4 POINT (1.00000 1.00000)
+ 5 POINT (0.00000 1.00000)
+ dtype: geometry
+
+ We can relate each geometry and a single
+ shapely geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> s.relate(Polygon([(0, 0), (1, 1), (0, 1)]))
+ 0 212F11FF2
+ 1 212F11FF2
+ 2 F11F00212
+ 3 F01FF0212
+ 4 F0FFFF212
+ dtype: object
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and compare elements with the same index using
+ ``align=True`` or ignore index and compare elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.relate(s2, align=True)
+ 0 None
+ 1 212F11FF2
+ 2 0F1FF0102
+ 3 1FFF0FFF2
+ 4 FF0FFF0F2
+ 5 None
+ dtype: object
+
+ >>> s.relate(s2, align=False)
+ 0 212F11FF2
+ 1 1F20F1102
+ 2 0F1FF0102
+ 3 0F1FF0FF2
+ 4 0FFFFFFF2
+ dtype: object
+
+ """
+ return _binary_op("relate", self, other, align)
+
+ def project(self, other, normalized=False, align=True):
"""
Return the distance along each geometry nearest to *other*
+ The operation works on a 1-to-1 row-wise manner:
+
+ .. image:: ../../../_static/binary_op-01.svg
+ :align: center
+
+ The project method is the inverse of interpolate.
+
+
Parameters
----------
other : BaseGeometry or GeoSeries
@@ -1190,10 +2833,83 @@ GeometryCollection
normalized : boolean
If normalized is True, return the distance normalized to
the length of the object.
+ align : bool (default True)
+ If True, automatically aligns GeoSeries based on their indices.
+ If False, the order of elements is preserved.
- The project method is the inverse of interpolate.
+ Returns
+ -------
+ Series
+
+ Examples
+ --------
+ >>> from shapely.geometry import Polygon, LineString, Point
+ >>> s = geopandas.GeoSeries(
+ ... [
+ ... Polygon([(0, 0), (2, 2), (0, 2)]),
+ ... LineString([(0, 0), (2, 2)]),
+ ... LineString([(2, 0), (0, 2)]),
+ ... ],
+ ... )
+ >>> s2 = geopandas.GeoSeries(
+ ... [
+ ... Point(1, 0),
+ ... Point(1, 0),
+ ... Point(2, 1),
+ ... ],
+ ... index=range(1, 4),
+ ... )
+
+ >>> s
+ 0 POLYGON ((0.00000 0.00000, 2.00000 2.00000, 0....
+ 1 LINESTRING (0.00000 0.00000, 2.00000 2.00000)
+ 2 LINESTRING (2.00000 0.00000, 0.00000 2.00000)
+ dtype: geometry
+
+ >>> s2
+ 1 POINT (1.00000 0.00000)
+ 2 POINT (1.00000 0.00000)
+ 3 POINT (2.00000 1.00000)
+ dtype: geometry
+
+ We can project each geometry on a single
+ shapely geometry:
+
+ .. image:: ../../../_static/binary_op-03.svg
+ :align: center
+
+ >>> s.project(Point(1, 0))
+ 0 -1.000000
+ 1 0.707107
+ 2 0.707107
+ dtype: float64
+
+ We can also check two GeoSeries against each other, row by row.
+ The GeoSeries above have different indices. We can either align both GeoSeries
+ based on index values and project elements with the same index using
+ ``align=True`` or ignore index and project elements based on their matching
+ order using ``align=False``:
+
+ .. image:: ../../../_static/binary_op-02.svg
+
+ >>> s.project(s2, align=True)
+ 0 NaN
+ 1 0.707107
+ 2 0.707107
+ 3 NaN
+ dtype: float64
+
+ >>> s.project(s2, align=False)
+ 0 -1.000000
+ 1 0.707107
+ 2 0.707107
+ dtype: float64
+
+ See also
+ --------
+ GeoSeries.interpolate
"""
- return _binary_op("project", self, other, normalized=normalized)
+ return _binary_op("project", self, other, normalized=normalized, align=align)
def interpolate(self, distance, normalized=False):
"""
diff --git a/geopandas/tests/test_geom_methods.py b/geopandas/tests/test_geom_methods.py
index 1764a2f..d4a86a6 100644
--- a/geopandas/tests/test_geom_methods.py
+++ b/geopandas/tests/test_geom_methods.py
@@ -81,6 +81,7 @@ class TestGeomMethods:
self.empty = GeoSeries([])
self.all_none = GeoSeries([None, None])
self.empty_poly = Polygon()
+ self.g9 = GeoSeries(self.g0, index=range(1, 8))
# Crossed lines
self.l3 = LineString([(0, 0), (1, 1)])
@@ -244,15 +245,24 @@ class TestGeomMethods:
"intersection", self.all_none, self.g1, self.empty
)
+ assert len(self.g0.intersection(self.g9, align=True) == 8)
+ assert len(self.g0.intersection(self.g9, align=False) == 7)
+
def test_union_series(self):
self._test_binary_topological("union", self.sq, self.g1, self.g2)
+ assert len(self.g0.union(self.g9, align=True) == 8)
+ assert len(self.g0.union(self.g9, align=False) == 7)
+
def test_union_polygon(self):
self._test_binary_topological("union", self.sq, self.g1, self.t2)
def test_symmetric_difference_series(self):
self._test_binary_topological("symmetric_difference", self.sq, self.g3, self.g4)
+ assert len(self.g0.symmetric_difference(self.g9, align=True) == 8)
+ assert len(self.g0.symmetric_difference(self.g9, align=False) == 7)
+
def test_symmetric_difference_poly(self):
expected = GeoSeries([GeometryCollection(), self.sq], crs=self.g3.crs)
self._test_binary_topological(
@@ -263,6 +273,9 @@ class TestGeomMethods:
expected = GeoSeries([GeometryCollection(), self.t2])
self._test_binary_topological("difference", expected, self.g1, self.g2)
+ assert len(self.g0.difference(self.g9, align=True) == 8)
+ assert len(self.g0.difference(self.g9, align=False) == 7)
+
def test_difference_poly(self):
expected = GeoSeries([self.t1, self.t1])
self._test_binary_topological("difference", expected, self.g1, self.t2)
@@ -341,6 +354,12 @@ class TestGeomMethods:
expected = [True, False, True, False, False, False, False]
assert_array_dtype_equal(expected, self.g0.contains(self.t1))
+ expected = [False, True, True, True, True, True, False, False]
+ assert_array_dtype_equal(expected, self.g0.contains(self.g9, align=True))
+
+ expected = [False, False, True, False, False, False, False]
+ assert_array_dtype_equal(expected, self.g0.contains(self.g9, align=False))
+
def test_length(self):
expected = Series(np.array([2 + np.sqrt(2), 4]), index=self.g1.index)
self._test_unary_real("length", expected, self.g1)
@@ -359,10 +378,22 @@ class TestGeomMethods:
expected = [False, True]
assert_array_dtype_equal(expected, self.crossed_lines.crosses(self.l3))
+ expected = [False] * 8
+ assert_array_dtype_equal(expected, self.g0.crosses(self.g9, align=True))
+
+ expected = [False] * 7
+ assert_array_dtype_equal(expected, self.g0.crosses(self.g9, align=False))
+
def test_disjoint(self):
expected = [False, False, False, False, False, True, False]
assert_array_dtype_equal(expected, self.g0.disjoint(self.t1))
+ expected = [False] * 8
+ assert_array_dtype_equal(expected, self.g0.disjoint(self.g9, align=True))
+
+ expected = [False, False, False, False, True, False, False]
+ assert_array_dtype_equal(expected, self.g0.disjoint(self.g9, align=False))
+
def test_relate(self):
expected = Series(
[
@@ -381,6 +412,36 @@ class TestGeomMethods:
expected = Series(["FF0FFF212", None], index=self.g6.index)
assert_array_dtype_equal(expected, self.g6.relate(self.na_none))
+ expected = Series(
+ [
+ None,
+ "2FFF1FFF2",
+ "2FFF1FFF2",
+ "2FFF1FFF2",
+ "2FFF1FFF2",
+ "0FFFFFFF2",
+ None,
+ None,
+ ],
+ index=range(8),
+ )
+
+ assert_array_dtype_equal(expected, self.g0.relate(self.g9, align=True))
+
+ expected = Series(
+ [
+ "FF2F11212",
+ "2FF11F212",
+ "212FF1FF2",
+ "FF2F1F212",
+ "FF2FF10F2",
+ None,
+ None,
+ ],
+ index=self.g0.index,
+ )
+ assert_array_dtype_equal(expected, self.g0.relate(self.g9, align=False))
+
def test_distance(self):
expected = Series(
np.array([np.sqrt((5 - 1) ** 2 + (5 - 1) ** 2), np.nan]), self.na_none.index
@@ -390,6 +451,13 @@ class TestGeomMethods:
expected = Series(np.array([np.sqrt(4 ** 2 + 4 ** 2), np.nan]), self.g6.index)
assert_array_dtype_equal(expected, self.g6.distance(self.na_none))
+ expected = Series(np.array([np.nan, 0, 0, 0, 0, 0, np.nan, np.nan]), range(8))
+ assert_array_dtype_equal(expected, self.g0.distance(self.g9, align=True))
+
+ val = self.g0.iloc[4].distance(self.g9.iloc[4])
+ expected = Series(np.array([0, 0, 0, 0, val, np.nan, np.nan]), self.g0.index)
+ assert_array_dtype_equal(expected, self.g0.distance(self.g9, align=False))
+
def test_distance_crs_warning(self):
with pytest.warns(UserWarning, match="Geometry is in a geographic CRS"):
self.g4.distance(self.p0)
@@ -410,6 +478,12 @@ class TestGeomMethods:
expected = [False] * 7
assert_array_dtype_equal(expected, self.g0.intersects(self.empty_poly))
+ expected = [False, True, True, True, True, True, False, False]
+ assert_array_dtype_equal(expected, self.g0.intersects(self.g9, align=True))
+
+ expected = [True, True, True, True, False, False, False]
+ assert_array_dtype_equal(expected, self.g0.intersects(self.g9, align=False))
+
def test_overlaps(self):
expected = [True, True, False, False, False, False, False]
assert_array_dtype_equal(expected, self.g0.overlaps(self.inner_sq))
@@ -417,10 +491,22 @@ class TestGeomMethods:
expected = [False, False]
assert_array_dtype_equal(expected, self.g4.overlaps(self.t1))
+ expected = [False] * 8
+ assert_array_dtype_equal(expected, self.g0.overlaps(self.g9, align=True))
+
+ expected = [False] * 7
+ assert_array_dtype_equal(expected, self.g0.overlaps(self.g9, align=False))
+
def test_touches(self):
expected = [False, True, False, False, False, False, False]
assert_array_dtype_equal(expected, self.g0.touches(self.t1))
+ expected = [False] * 8
+ assert_array_dtype_equal(expected, self.g0.touches(self.g9, align=True))
+
+ expected = [True, False, False, True, False, False, False]
+ assert_array_dtype_equal(expected, self.g0.touches(self.g9, align=False))
+
def test_within(self):
expected = [True, False, False, False, False, False, False]
assert_array_dtype_equal(expected, self.g0.within(self.t1))
@@ -428,6 +514,12 @@ class TestGeomMethods:
expected = [True, True, True, True, True, False, False]
assert_array_dtype_equal(expected, self.g0.within(self.sq))
+ expected = [False, True, True, True, True, True, False, False]
+ assert_array_dtype_equal(expected, self.g0.within(self.g9, align=True))
+
+ expected = [False, True, False, False, False, False, False]
+ assert_array_dtype_equal(expected, self.g0.within(self.g9, align=False))
+
def test_covers_itself(self):
# Each polygon in a Series covers itself
res = self.g1.covers(self.g1)
@@ -439,6 +531,12 @@ class TestGeomMethods:
exp = Series([True, False])
assert_series_equal(res, exp)
+ expected = [False, True, True, True, True, True, False, False]
+ assert_array_dtype_equal(expected, self.g0.covers(self.g9, align=True))
+
+ expected = [False, False, True, False, False, False, False]
+ assert_array_dtype_equal(expected, self.g0.covers(self.g9, align=False))
+
def test_covers_inverse(self):
res = self.g8.covers(self.g7)
exp = Series([False, False])
@@ -453,6 +551,12 @@ class TestGeomMethods:
exp = Series([True, True])
assert_series_equal(res, exp)
+ expected = [False, True, True, True, True, True, False, False]
+ assert_array_dtype_equal(expected, self.g0.covered_by(self.g9, align=True))
+
+ expected = [False, True, False, False, False, False, False]
+ assert_array_dtype_equal(expected, self.g0.covered_by(self.g9, align=False))
+
def test_is_valid(self):
expected = Series(np.array([True] * len(self.g1)), self.g1.index)
self._test_unary_real("is_valid", expected, self.g1)
@@ -572,6 +676,13 @@ class TestGeomMethods:
expected = Series([1.0, 0.5], index=self.g5.index)
self._test_binary_real("project", expected, self.g5, p, normalized=True)
+ s = GeoSeries([Point(2, 2), Point(0.5, 0.5)], index=[1, 2])
+ expected = Series([np.nan, 2.0, np.nan])
+ assert_series_equal(self.g5.project(s), expected)
+
+ expected = Series([2.0, 0.5], index=self.g5.index)
+ assert_series_equal(self.g5.project(s, align=False), expected)
+
def test_affine_transform(self):
# 45 degree reflection matrix
matrix = [0, 1, 1, 0, 0, 0]
diff --git a/geopandas/tests/test_geoseries.py b/geopandas/tests/test_geoseries.py
index 9bcc763..1ffb649 100644
--- a/geopandas/tests/test_geoseries.py
+++ b/geopandas/tests/test_geoseries.py
@@ -136,20 +136,38 @@ class TestSeries:
def test_geom_equals_align(self):
with pytest.warns(UserWarning, match="The indices .+ different"):
- a = self.a1.geom_equals(self.a2)
+ a = self.a1.geom_equals(self.a2, align=True)
exp = pd.Series([False, True, False], index=["A", "B", "C"])
assert_series_equal(a, exp)
+ a = self.a1.geom_equals(self.a2, align=False)
+ exp = pd.Series([False, False], index=["A", "B"])
+ assert_series_equal(a, exp)
+
def test_geom_almost_equals(self):
# TODO: test decimal parameter
assert np.all(self.g1.geom_almost_equals(self.g1))
assert_array_equal(self.g1.geom_almost_equals(self.sq), [False, True])
+ assert_array_equal(
+ self.a1.geom_almost_equals(self.a2, align=True), [False, True, False]
+ )
+ assert_array_equal(
+ self.a1.geom_almost_equals(self.a2, align=False), [False, False]
+ )
+
def test_geom_equals_exact(self):
# TODO: test tolerance parameter
assert np.all(self.g1.geom_equals_exact(self.g1, 0.001))
assert_array_equal(self.g1.geom_equals_exact(self.sq, 0.001), [False, True])
+ assert_array_equal(
+ self.a1.geom_equals_exact(self.a2, 0.001, align=True), [False, True, False]
+ )
+ assert_array_equal(
+ self.a1.geom_equals_exact(self.a2, 0.001, align=False), [False, False]
+ )
+
def test_equal_comp_op(self):
s = GeoSeries([Point(x, x) for x in range(3)])
res = s == Point(1, 1)