mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-25 13:40:11 +08:00
API: expose sjoin_nearest, clip and overlay as methods (#2150)
Co-authored-by: Brendan Ward <bcward@astutespruce.com> Co-authored-by: Joris Van den Bossche <jorisvandenbossche@gmail.com>
This commit is contained in:
co-authored by
Brendan Ward
Joris Van den Bossche
parent
087858c12a
commit
0a7eebf6d1
@@ -59,6 +59,24 @@ Aggregating and exploding
|
||||
GeoDataFrame.dissolve
|
||||
GeoDataFrame.explode
|
||||
|
||||
Spatial joins
|
||||
-------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: api/
|
||||
|
||||
GeoDataFrame.sjoin
|
||||
GeoDataFrame.sjoin_nearest
|
||||
|
||||
Overlay operations
|
||||
------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: api/
|
||||
|
||||
GeoDataFrame.clip
|
||||
GeoDataFrame.overlay
|
||||
|
||||
Plotting
|
||||
--------
|
||||
|
||||
|
||||
@@ -144,6 +144,14 @@ Missing values
|
||||
GeoSeries.isna
|
||||
GeoSeries.notna
|
||||
|
||||
Overlay operations
|
||||
------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: api/
|
||||
|
||||
GeoSeries.clip
|
||||
|
||||
Plotting
|
||||
--------
|
||||
|
||||
|
||||
@@ -91,21 +91,25 @@ In a Spatial Join, two geometry objects are merged based on their spatial relati
|
||||
|
||||
# Execute spatial join
|
||||
|
||||
cities_with_country = geopandas.sjoin(cities, countries, how="inner", predicate='intersects')
|
||||
cities_with_country = cities.sjoin(countries, how="inner", predicate='intersects')
|
||||
cities_with_country.head()
|
||||
|
||||
|
||||
GeoPandas provides two spatial-join functions:
|
||||
|
||||
- :func:`sjoin`: joins based on binary predicates (intersects, contains, etc.)
|
||||
- :func:`sjoin_nearest`: joins based on proximity, with the ability to set a maximum search radius.
|
||||
- :meth:`GeoDataFrame.sjoin`: joins based on binary predicates (intersects, contains, etc.)
|
||||
- :meth:`GeoDataFrame.sjoin_nearest`: joins based on proximity, with the ability to set a maximum search radius.
|
||||
|
||||
.. note::
|
||||
For historical reasons, both methods are also available as top-level functions :func:`sjoin` and :func:`sjoin_nearest`.
|
||||
It is recommended to use methods as the functions may be deprecated in the future.
|
||||
|
||||
Binary Predicate Joins
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Binary predicate joins are available via :func:`sjoin`.
|
||||
Binary predicate joins are available via :meth:`GeoDataFrame.sjoin`.
|
||||
|
||||
:func:`sjoin` has two core arguments: ``how`` and ``predicate``.
|
||||
:meth:`GeoDataFrame.sjoin` has two core arguments: ``how`` and ``predicate``.
|
||||
|
||||
**predicate**
|
||||
|
||||
@@ -132,7 +136,7 @@ The `how` argument specifies the type of join that will occur and which geometry
|
||||
:class:`GeoDataFrame`. It accepts the following options:
|
||||
|
||||
* ``left``: use the index from the first (or `left_df`) :class:`GeoDataFrame` that you provide
|
||||
to :func:`sjoin`; retain only the `left_df` geometry column
|
||||
to :meth:`GeoDataFrame.sjoin`; retain only the `left_df` geometry column
|
||||
* ``right``: use index from second (or `right_df`); retain only the `right_df` geometry column
|
||||
* ``inner``: use intersection of index values from both :class:`GeoDataFrame`; retain only the `left_df` geometry column
|
||||
|
||||
@@ -143,9 +147,9 @@ point into a circle of appropriate radius, then intersect those buffered circles
|
||||
Nearest Joins
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Proximity-based joins can be done via :func:`sjoin_nearest`.
|
||||
Proximity-based joins can be done via :meth:`GeoDataFrame.sjoin_nearest`.
|
||||
|
||||
:func:`sjoin_nearest` shares the ``how`` argument with :func:`sjoin`, and
|
||||
:meth:`GeoDataFrame.sjoin_nearest` shares the ``how`` argument with :meth:`GeoDataFrame.sjoin`, and
|
||||
includes two additional arguments: ``max_distance`` and ``distance_col``.
|
||||
|
||||
**max_distance**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. currentmodule:: geopandas
|
||||
|
||||
.. ipython:: python
|
||||
:suppress:
|
||||
|
||||
@@ -14,22 +16,23 @@ When working with multiple spatial datasets -- especially multiple *polygon* or
|
||||
those datasets overlap (or don't overlap). These manipulations are often
|
||||
referred using the language of sets -- intersections, unions, and differences.
|
||||
These types of operations are made available in the *geopandas* library through
|
||||
the :func:`~geopandas.overlay` function.
|
||||
the :meth:`~geopandas.GeoDataFrame.overlay` method.
|
||||
|
||||
The basic idea is demonstrated by the graphic below but keep in mind that
|
||||
overlays operate at the DataFrame level, not on individual geometries, and the
|
||||
properties from both are retained. In effect, for every shape in the first
|
||||
:class:`~geopandas.GeoDataFrame`, this operation is executed against every other shape in the other
|
||||
properties from both are retained. In effect, for every shape in the left
|
||||
:class:`~geopandas.GeoDataFrame`, this operation is executed against every other shape in the right
|
||||
:class:`~geopandas.GeoDataFrame`:
|
||||
|
||||
.. image:: ../../_static/overlay_operations.png
|
||||
|
||||
**Source: QGIS Documentation**
|
||||
|
||||
(Note to users familiar with the *shapely* library: :func:`~geopandas.overlay` can be thought
|
||||
of as offering versions of the standard *shapely* set-operations that deal with
|
||||
the complexities of applying set operations to two *GeoSeries*. The standard
|
||||
*shapely* set-operations are also available as :class:`~geopandas.GeoSeries` methods.)
|
||||
.. note::
|
||||
Note to users familiar with the *shapely* library: :meth:`~geopandas.GeoDataFrame.overlay` can be thought
|
||||
of as offering versions of the standard *shapely* set-operations that deal with
|
||||
the complexities of applying set operations to two *GeoSeries*. The standard
|
||||
*shapely* set-operations are also available as :class:`~geopandas.GeoSeries` methods.
|
||||
|
||||
|
||||
The different Overlay operations
|
||||
@@ -57,16 +60,20 @@ These two GeoDataFrames have some overlapping areas:
|
||||
df2.plot(ax=ax, color='green', alpha=0.5);
|
||||
|
||||
We illustrate the different overlay modes with the above example.
|
||||
The :func:`~geopandas.overlay` function will determine the set of all individual geometries
|
||||
The :meth:`~geopandas.GeoDataFrame.overlay` method will determine the set of all individual geometries
|
||||
from overlaying the two input GeoDataFrames. This result covers the area covered
|
||||
by the two input GeoDataFrames, and also preserves all unique regions defined by
|
||||
the combined boundaries of the two GeoDataFrames.
|
||||
|
||||
.. note::
|
||||
For historical reasons, the overlay method is also available as a top-level function :func:`overlay`.
|
||||
It is recommended to use the method as the function may be deprecated in the future.
|
||||
|
||||
When using ``how='union'``, all those possible geometries are returned:
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
res_union = geopandas.overlay(df1, df2, how='union')
|
||||
res_union = df1.overlay(df2, how='union')
|
||||
res_union
|
||||
|
||||
ax = res_union.plot(alpha=0.5, cmap='tab10')
|
||||
@@ -80,7 +87,7 @@ by both GeoDataFrames:
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
res_intersection = geopandas.overlay(df1, df2, how='intersection')
|
||||
res_intersection = df1.overlay(df2, how='intersection')
|
||||
res_intersection
|
||||
|
||||
ax = res_intersection.plot(cmap='tab10')
|
||||
@@ -93,7 +100,7 @@ the geometries that are only part of one of the GeoDataFrames but not of both:
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
res_symdiff = geopandas.overlay(df1, df2, how='symmetric_difference')
|
||||
res_symdiff = df1.overlay(df2, how='symmetric_difference')
|
||||
res_symdiff
|
||||
|
||||
ax = res_symdiff.plot(cmap='tab10')
|
||||
@@ -106,7 +113,7 @@ To obtain the geometries that are part of ``df1`` but are not contained in
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
res_difference = geopandas.overlay(df1, df2, how='difference')
|
||||
res_difference = df1.overlay(df2, how='difference')
|
||||
res_difference
|
||||
|
||||
ax = res_difference.plot(cmap='tab10')
|
||||
@@ -119,7 +126,7 @@ but with the geometries obtained from overlaying ``df1`` with ``df2``:
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
res_identity = geopandas.overlay(df1, df2, how='identity')
|
||||
res_identity = df1.overlay(df2, how='identity')
|
||||
res_identity
|
||||
|
||||
ax = res_identity.plot(cmap='tab10')
|
||||
@@ -146,7 +153,7 @@ First, we load the countries and cities example datasets and select :
|
||||
countries = countries.to_crs('epsg:3395')
|
||||
capitals = capitals.to_crs('epsg:3395')
|
||||
|
||||
To illustrate the :func:`~geopandas.overlay` function, consider the following case in which one
|
||||
To illustrate the :meth:`~geopandas.GeoDataFrame.overlay` method, consider the following case in which one
|
||||
wishes to identify the "core" portion of each country -- defined as areas within
|
||||
500km of a capital -- using a ``GeoDataFrame`` of countries and a
|
||||
``GeoDataFrame`` of capitals.
|
||||
@@ -171,7 +178,7 @@ To select only the portion of countries within 500km of a capital, we specify th
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
country_cores = geopandas.overlay(countries, capitals, how='intersection')
|
||||
country_cores = countries.overlay(capitals, how='intersection')
|
||||
@savefig country_cores.png width=5in
|
||||
country_cores.plot(alpha=0.5, edgecolor='k', cmap='tab10');
|
||||
|
||||
@@ -179,7 +186,7 @@ Changing the "how" option allows for different types of overlay operations. For
|
||||
|
||||
.. ipython:: python
|
||||
|
||||
country_peripheries = geopandas.overlay(countries, capitals, how='difference')
|
||||
country_peripheries = countries.overlay(capitals, how='difference')
|
||||
@savefig country_peripheries.png width=5in
|
||||
country_peripheries.plot(alpha=0.5, edgecolor='k', cmap='tab10');
|
||||
|
||||
@@ -194,7 +201,7 @@ Changing the "how" option allows for different types of overlay operations. For
|
||||
keep_geom_type keyword
|
||||
----------------------
|
||||
|
||||
In default settings, :func:`~geopandas.overlay` returns only geometries of the same geometry type as df1
|
||||
In default settings, :meth:`~geopandas.GeoDataFrame.overlay` returns only geometries of the same geometry type as GeoDataFrame
|
||||
(left one) has, where Polygon and MultiPolygon is considered as a same type (other types likewise).
|
||||
You can control this behavior using ``keep_geom_type`` option, which is set to
|
||||
True by default. Once set to False, ``overlay`` will return all geometry types resulting from
|
||||
@@ -205,7 +212,7 @@ where two polygons intersects in a line or a point.
|
||||
More Examples
|
||||
-------------
|
||||
|
||||
A larger set of examples of the use of :func:`~geopandas.overlay` can be found `here <https://nbviewer.jupyter.org/github/geopandas/geopandas/blob/master/doc/source/gallery/overlays.ipynb>`_
|
||||
A larger set of examples of the use of :meth:`~geopandas.GeoDataFrame.overlay` can be found `here <https://nbviewer.jupyter.org/github/geopandas/geopandas/blob/master/doc/source/gallery/overlays.ipynb>`_
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Overlays\n",
|
||||
"\n",
|
||||
@@ -16,20 +15,19 @@
|
||||
"not on individual geometries, and the properties from both are retained\n",
|
||||
"\n",
|
||||
""
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now we can load up two GeoDataFrames containing (multi)polygon geometries..."
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"from shapely.geometry import Point\n",
|
||||
@@ -47,43 +45,44 @@
|
||||
" {'geometry': Point(x, y).buffer(10000), 'value1': x + y, 'value2': x - y}\n",
|
||||
" for x, y in zip(range(b[0], b[2], int((b[2] - b[0]) / N)),\n",
|
||||
" range(b[1], b[3], int((b[3] - b[1]) / N)))])"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The first dataframe contains multipolygons of the NYC boros"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"polydf.plot()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"And the second GeoDataFrame is a sequentially generated set of circles in the same geographic space. We'll plot these with a [different color palette](https://matplotlib.org/examples/color/colormaps_reference.html)."
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"polydf2.plot(cmap='tab20b')"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The `geopandas.tools.overlay` function takes three arguments:\n",
|
||||
"\n",
|
||||
@@ -99,104 +98,104 @@
|
||||
" 'symmetric_difference',\n",
|
||||
" 'difference']\n",
|
||||
"\n",
|
||||
"So let's identify the areas (and attributes) where both dataframes intersect using the `overlay` tool. "
|
||||
]
|
||||
"So let's identify the areas (and attributes) where both dataframes intersect using the `overlay` method. "
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from geopandas.tools import overlay\n",
|
||||
"newdf = overlay(polydf, polydf2, how=\"intersection\")\n",
|
||||
"newdf = polydf.overlay(polydf2, how=\"intersection\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"And take a look at the attributes; we see that the attributes from both of the original GeoDataFrames are retained. "
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"polydf.head()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"polydf2.head()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newdf.head()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now let's look at the other `how` operations:"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newdf = overlay(polydf, polydf2, how=\"union\")\n",
|
||||
"newdf = polydf.overlay(polydf2, how=\"union\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
],
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newdf = overlay(polydf, polydf2, how=\"identity\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
]
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"newdf = polydf.overlay(polydf2, how=\"identity\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"newdf = polydf.overlay(polydf2, how=\"symmetric_difference\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"nbsphinx-thumbnail"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newdf = overlay(polydf, polydf2, how=\"symmetric_difference\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newdf = overlay(polydf, polydf2, how=\"difference\")\n",
|
||||
"newdf = polydf.overlay(polydf2, how=\"difference\")\n",
|
||||
"newdf.plot(cmap='tab20b')"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -220,4 +219,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,17 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Clip Vector Data with GeoPandas\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Learn how to clip geometries to the boundary of a polygon geometry\n",
|
||||
"using GeoPandas."
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The example below shows you how to clip a set of vector geometries\n",
|
||||
"to the spatial extent / shape of another vector object. Both sets of geometries\n",
|
||||
@@ -33,33 +32,33 @@
|
||||
"be clipped to the total boundary of all polygons in clip object.\n",
|
||||
"</div>\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Import Packages\n",
|
||||
"---------------\n",
|
||||
"\n",
|
||||
"To begin, import the needed packages.\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import geopandas\n",
|
||||
"from shapely.geometry import Polygon"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Get or Create Example Data\n",
|
||||
"--------------------------\n",
|
||||
@@ -68,13 +67,12 @@
|
||||
"Additionally, a polygon is created with shapely and then converted into a\n",
|
||||
"GeoDataFrame with the same CRS as the GeoPandas world dataset.\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"capitals = geopandas.read_file(geopandas.datasets.get_path(\"naturalearth_cities\"))\n",
|
||||
"world = geopandas.read_file(geopandas.datasets.get_path(\"naturalearth_lowres\"))\n",
|
||||
@@ -85,22 +83,22 @@
|
||||
"# Create a custom polygon\n",
|
||||
"polygon = Polygon([(0, 0), (0, 90), (180, 90), (180, 0), (0, 0)])\n",
|
||||
"poly_gdf = geopandas.GeoDataFrame([1], geometry=[polygon], crs=world.crs)"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Plot the Unclipped Data\n",
|
||||
"-----------------------\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))\n",
|
||||
"world.plot(ax=ax1)\n",
|
||||
@@ -112,17 +110,18 @@
|
||||
"ax1.set_axis_off()\n",
|
||||
"ax2.set_axis_off()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Clip the Data\n",
|
||||
"--------------\n",
|
||||
"\n",
|
||||
"When you call `clip`, the first object called is the object that will\n",
|
||||
"be clipped. The second object called is the clip extent. The returned output\n",
|
||||
"The object on which you call `clip` is the object that will\n",
|
||||
"be clipped. The object you pass is the clip extent. The returned output\n",
|
||||
"will be a new clipped GeoDataframe. All of the attributes for each returned\n",
|
||||
"geometry will be retained when you clip.\n",
|
||||
"\n",
|
||||
@@ -131,33 +130,28 @@
|
||||
"Note\n",
|
||||
"\n",
|
||||
"Recall that the data must be in the same CRS in order to use the\n",
|
||||
"`clip` function. If the data are not in the same CRS, be sure to use\n",
|
||||
"`clip` method. If the data are not in the same CRS, be sure to use\n",
|
||||
"the GeoPandas `GeoDataFrame.to_crs` method to ensure both datasets\n",
|
||||
"are in the same CRS.\n",
|
||||
"</div>\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Clip the World Data\n",
|
||||
"--------------------\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"nbsphinx-thumbnail"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"world_clipped = geopandas.clip(world, polygon)\n",
|
||||
"world_clipped = world.clip(polygon)\n",
|
||||
"\n",
|
||||
"# Plot the clipped data\n",
|
||||
"# The plot below shows the results of the clip function applied to the world\n",
|
||||
@@ -169,24 +163,36 @@
|
||||
"ax.set_title(\"World Clipped\", fontsize=20)\n",
|
||||
"ax.set_axis_off()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"nbsphinx-thumbnail"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-info\">\n",
|
||||
" \n",
|
||||
"Note\n",
|
||||
"\n",
|
||||
"For historical reasons, the clip method is also available as a top-level function `geopandas.clip`.\n",
|
||||
"It is recommended to use the method as the function may be deprecated in the future.\n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
"Clip the Capitals Data\n",
|
||||
"----------------------\n",
|
||||
"\n"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"capitals_clipped = geopandas.clip(capitals, south_america)\n",
|
||||
"capitals_clipped = capitals.clip(south_america)\n",
|
||||
"\n",
|
||||
"# Plot the clipped data\n",
|
||||
"# The plot below shows the results of the clip function applied to the capital cities\n",
|
||||
@@ -196,7 +202,9 @@
|
||||
"ax.set_title(\"Capitals Clipped\", fontsize=20)\n",
|
||||
"ax.set_axis_off()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -220,4 +228,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Spatial Joins\n",
|
||||
"\n",
|
||||
@@ -13,11 +12,11 @@
|
||||
"A common use case might be a spatial join between a point layer and a polygon layer where you want to retain the point geometries and grab the attributes of the intersecting polygons.\n",
|
||||
"\n",
|
||||
""
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n",
|
||||
"## Types of spatial joins\n",
|
||||
@@ -85,27 +84,25 @@
|
||||
" 0101000000F0D88AA0E1A4EEBF7052F7E5B115E9BF | 2 | 20\n",
|
||||
"(4 rows) \n",
|
||||
"```"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Spatial Joins between two GeoDataFrames\n",
|
||||
"\n",
|
||||
"Let's take a look at how we'd implement these using `GeoPandas`. First, load up the NYC test data into `GeoDataFrames`:"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"from shapely.geometry import Point\n",
|
||||
"from geopandas import datasets, GeoDataFrame, read_file\n",
|
||||
"from geopandas.tools import overlay\n",
|
||||
"\n",
|
||||
"# NYC Boros\n",
|
||||
"zippath = datasets.get_path('nybb')\n",
|
||||
@@ -121,100 +118,101 @@
|
||||
"\n",
|
||||
"# Make sure they're using the same projection reference\n",
|
||||
"pointdf.crs = polydf.crs"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pointdf"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"polydf"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pointdf.plot()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"polydf.plot()"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Joins"
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from geopandas.tools import sjoin\n",
|
||||
"join_left_df = sjoin(pointdf, polydf, how=\"left\")\n",
|
||||
"join_left_df = pointdf.sjoin(polydf, how=\"left\")\n",
|
||||
"join_left_df\n",
|
||||
"# Note the NaNs where the point did not intersect a boro"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"join_right_df = sjoin(pointdf, polydf, how=\"right\")\n",
|
||||
"join_right_df = pointdf.sjoin(polydf, how=\"right\")\n",
|
||||
"join_right_df\n",
|
||||
"# Note Staten Island is repeated"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"join_inner_df = sjoin(pointdf, polydf, how=\"inner\")\n",
|
||||
"join_inner_df = pointdf.sjoin(polydf, how=\"inner\")\n",
|
||||
"join_inner_df\n",
|
||||
"# Note the lack of NaNs; dropped anything that didn't intersect"
|
||||
]
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We're not limited to using the `intersection` binary predicate. Any of the `Shapely` geometry methods that return a Boolean can be used by specifying the `op` kwarg."
|
||||
]
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sjoin(pointdf, polydf, how=\"left\", op=\"within\")"
|
||||
]
|
||||
"pointdf.sjoin(polydf, how=\"left\", op=\"within\")"
|
||||
],
|
||||
"outputs": [],
|
||||
"metadata": {}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -238,4 +236,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user