From 0d38f10a9507bba80ed23b91c697a74fe95250cd Mon Sep 17 00:00:00 2001 From: TLouf <31036680+TLouf@users.noreply.github.com> Date: Sun, 2 May 2021 17:59:23 +0200 Subject: [PATCH] DOC: document contextily layers functionality (#1922) * DOC: document contextily layers functionality * DOC: restructured background map example - Explain CRS matching better - Renamed projected df - Add sections to better reflect that projecting to mercator is not mandatory - Change the sections title levels to match other examples of the gallery * DOC: reduced line length in md * DOC: remove last empty cell from basemap example --- .../gallery/plotting_basemap_background.ipynb | 163 ++++++++++++++---- 1 file changed, 129 insertions(+), 34 deletions(-) diff --git a/doc/source/gallery/plotting_basemap_background.ipynb b/doc/source/gallery/plotting_basemap_background.ipynb index 325be15..22c3425 100644 --- a/doc/source/gallery/plotting_basemap_background.ipynb +++ b/doc/source/gallery/plotting_basemap_background.ipynb @@ -10,7 +10,10 @@ "This example shows how you can add a background basemap to plots created\n", "with the geopandas ``.plot()`` method. This makes use of the\n", "[contextily](https://github.com/geopandas/contextily) package to retrieve\n", - "web map tiles from several sources (OpenStreetMap, Stamen).\n" + "web map tiles from several sources (OpenStreetMap, Stamen). Also have a\n", + "look at contextily's \n", + "[introduction guide](https://contextily.readthedocs.io/en/latest/intro_guide.html#Using-transparent-layers)\n", + "for possible new features not covered here.\n" ] }, { @@ -19,7 +22,8 @@ "metadata": {}, "outputs": [], "source": [ - "import geopandas" + "import geopandas\n", + "import contextily as cx" ] }, { @@ -45,15 +49,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Convert the data to Web Mercator\n", - "================================\n", + "## Matching coordinate systems \n", "\n", + "\n", + "Before adding web map tiles to this plot, we first need to ensure the\n", + "coordinate reference systems (CRS) of the tiles and the data match.\n", "Web map tiles are typically provided in\n", "[Web Mercator](https://en.wikipedia.org/wiki/Web_Mercator>)\n", - "([EPSG 3857](https://epsg.io/3857)), so we need to make sure to convert\n", - "our data first to the same CRS to combine our polygons and background tiles\n", - "in the same map:\n", - "\n" + "([EPSG 3857](https://epsg.io/3857)), so let us first check what\n", + "CRS our NYC boroughs are in:" ] }, { @@ -62,28 +66,36 @@ "metadata": {}, "outputs": [], "source": [ - "df = df.to_crs(epsg=3857)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import contextily as ctx" + "df.crs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Add background tiles to plot\n", - "============================\n", + "Now we know the CRS do not match, so we need to choose in which\n", + "CRS we wish to visualize the data: either the CRS of the tiles,\n", + "the one of the data, or even a different one.\n", "\n", - "We can use `add_basemap` function of contextily to easily add a background\n", - "map to our plot. :\n", - "\n" + "The first option to match CRS is to leverage the `to_crs` method\n", + "of GeoDataFrames to convert the CRS of our data, here to Web Mercator:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df_wm = df.to_crs(epsg=3857)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can then use `add_basemap` function of contextily to easily add a\n", + "background map to our plot:" ] }, { @@ -95,9 +107,45 @@ ] }, "outputs": [], + "source": [ + "ax = df_wm.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", + "cx.add_basemap(ax)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to convert the CRS of the tiles instead, which might be advisable\n", + "for large datasets, we can use the `crs` keyword argument of `add_basemap`\n", + "as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "ax = df.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", - "ctx.add_basemap(ax)" + "cx.add_basemap(ax, crs=df.crs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This reprojects map tiles to a target CRS which may in some cases cause a\n", + "loss of sharpness. See \n", + "[contextily's guide on warping tiles](https://contextily.readthedocs.io/en/latest/warping_guide.html)\n", + "for more information on the subject." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Controlling the level of detail" ] }, { @@ -116,8 +164,15 @@ "metadata": {}, "outputs": [], "source": [ - "ax = df.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", - "ctx.add_basemap(ax, zoom=12)" + "ax = df_wm.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", + "cx.add_basemap(ax, zoom=12)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Choosing a different style" ] }, { @@ -125,7 +180,7 @@ "metadata": {}, "source": [ "By default, contextily uses the Stamen Terrain style. We can specify a\n", - "different style using ``ctx.providers``:\n", + "different style using ``cx.providers``:\n", "\n" ] }, @@ -135,24 +190,64 @@ "metadata": {}, "outputs": [], "source": [ - "ax = df.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", - "ctx.add_basemap(ax, url=ctx.providers.Stamen.TonerLite)\n", + "ax = df_wm.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", + "cx.add_basemap(ax, source=cx.providers.Stamen.TonerLite)\n", "ax.set_axis_off()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Adding labels as an overlay" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sometimes, when you plot data on a basemap, the data will obscure some important map elements, such as labels,\n", + "that you would otherwise want to see unobscured. Some map tile providers offer multiple sets of partially\n", + "transparent tiles to solve this, and `contextily` will do its best to auto-detect these transparent layers\n", + "and put them on top." + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "ax = df_wm.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", + "cx.add_basemap(ax, source=cx.providers.Stamen.TonerLite)\n", + "cx.add_basemap(ax, source=cx.providers.Stamen.TonerLabels)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By splitting the layers like this, you can also independently manipulate the level of zoom on each layer,\n", + "for example to make labels larger while still showing a lot of detail." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ax = df_wm.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')\n", + "cx.add_basemap(ax, source=cx.providers.Stamen.Watercolor, zoom=12)\n", + "cx.add_basemap(ax, source=cx.providers.Stamen.TonerLabels, zoom=10)" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "geopandas_docs", "language": "python", - "name": "python3" + "name": "geopandas_docs" }, "language_info": { "codemirror_mode": { @@ -164,9 +259,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.1" } }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file