1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
import geopandas
import matplotlib
orig = matplotlib.rcParams['figure.figsize']
matplotlib.rcParams['figure.figsize'] = [orig[0] * 1.5, orig[1] * 1.5]
import matplotlib.pyplot as plt
plt.close('all')
Mapping and plotting tools
=========================================
GeoPandas provides a high-level interface to the matplotlib_ library for making maps. Mapping shapes is as easy as using the :meth:`~GeoDataFrame.plot()` method on a :class:`GeoSeries` or :class:`GeoDataFrame`.
.. _matplotlib: https://matplotlib.org/stable/
Loading some example data:
.. ipython:: python
import geodatasets
chicago = geopandas.read_file(geodatasets.get_path("geoda.chicago_commpop"))
groceries = geopandas.read_file(geodatasets.get_path("geoda.groceries"))
You can now plot those GeoDataFrames:
.. ipython:: python
# Examine the chicago GeoDataFrame
chicago.head()
# Basic plot, single color
@savefig chicago_singlecolor.png
chicago.plot();
Note that in general, any options one can pass to `pyplot <http://matplotlib.org/api/pyplot_api.html>`_ in matplotlib_ (or `style options that work for lines <http://matplotlib.org/api/lines_api.html>`_) can be passed to the :meth:`~GeoDataFrame.plot` method.
Choropleth maps
-----------------
GeoPandas makes it easy to create Choropleth maps (maps where the color of each shape is based on the value of an associated variable). Simply use the plot command with the ``column`` argument set to the column whose values you want used to assign colors.
.. ipython:: python
:okwarning:
# Plot by population
@savefig chicago_population.png
chicago.plot(column="POP2010");
Creating a legend
~~~~~~~~~~~~~~~~~
When plotting a map, one can enable a legend using the ``legend`` argument:
.. ipython:: python
# Plot population estimates with an accurate legend
@savefig chicago_choro.png
chicago.plot(column='POP2010', legend=True);
The following example plots the color bar below the map and adds its label using ``legend_kwds``:
.. ipython:: python
# Plot population estimates with an accurate legend
@savefig chicago_horizontal.png
chicago.plot(
column="POP2010",
legend=True,
legend_kwds={"label": "Population in 2010", "orientation": "horizontal"},
);
However, the default appearance of the legend and plot axes may not be desirable. One can define the plot axes (with ``ax``) and the legend axes (with ``cax``) and then pass those in to the :meth:`~GeoDataFrame.plot` call. The following example uses ``mpl_toolkits`` to horizontally align the plot axes and the legend axes and change the width:
.. ipython:: python
# Plot population estimates with an accurate legend
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig, ax = plt.subplots(1, 1)
divider = make_axes_locatable(ax)
cax = divider.append_axes("bottom", size="5%", pad=0.1)
@savefig chicago_cax.png
chicago.plot(
column="POP2010",
ax=ax,
legend=True,
cax=cax,
legend_kwds={"label": "Population in 2010", "orientation": "horizontal"},
);
Choosing colors
~~~~~~~~~~~~~~~~
You can also modify the colors used by :meth:`~GeoDataFrame.plot` with the ``cmap`` option. For a full list of colormaps, see `Choosing Colormaps in Matplotlib <https://matplotlib.org/stable/tutorials/colors/colormaps.html>`_.
.. ipython:: python
@savefig chicago_red.png
chicago.plot(column='POP2010', cmap='OrRd');
To make the color transparent for when you just want to show the boundary, you have two options. One option is to do ``chicago.plot(facecolor="none", edgecolor="black")``. However, this can cause a lot of confusion because ``"none"`` and ``None`` are different in the context of using ``facecolor`` and they do opposite things. ``None`` does the "default behavior" based on matplotlib, and if you use it for ``facecolor``, it actually adds a color. The second option is to use ``chicago.boundary.plot()``. This option is more explicit and clear.:
.. ipython:: python
@savefig chicago_transparent.png
chicago.boundary.plot();
The way color maps are scaled can also be manipulated with the ``scheme`` option (if you have ``mapclassify`` installed, which can be accomplished via ``conda install -c conda-forge mapclassify``). The ``scheme`` option can be set to any scheme provided by mapclassify (e.g. 'box_plot', 'equal_interval',
'fisher_jenks', 'fisher_jenks_sampled', 'headtail_breaks', 'jenks_caspall', 'jenks_caspall_forced', 'jenks_caspall_sampled', 'max_p_classifier', 'maximum_breaks', 'natural_breaks', 'quantiles', 'percentiles', 'std_mean' or 'user_defined'). Arguments can be passed in classification_kwds dict. See the `mapclassify documentation <https://pysal.org/mapclassify>`_ for further details about these map classification schemes.
.. ipython:: python
@savefig chicago_quantiles.png
chicago.plot(column='POP2010', cmap='OrRd', scheme='quantiles');
Missing data
~~~~~~~~~~~~
In some cases one may want to plot data which contains missing values - for some features one simply does not know the value. Geopandas (from the version 0.7) by defaults ignores such features.
.. ipython:: python
import numpy as np
chicago.loc[np.random.choice(chicago.index, 30), 'POP2010'] = np.nan
@savefig missing_vals.png
chicago.plot(column='POP2010');
However, passing ``missing_kwds`` one can specify the style and label of features containing None or NaN.
.. ipython:: python
@savefig missing_vals_grey.png
chicago.plot(column='POP2010', missing_kwds={'color': 'lightgrey'});
@savefig missing_vals_hatch.png
chicago.plot(
column="POP2010",
legend=True,
scheme="quantiles",
figsize=(15, 10),
missing_kwds={
"color": "lightgrey",
"edgecolor": "red",
"hatch": "///",
"label": "Missing values",
},
);
Other map customizations
~~~~~~~~~~~~~~~~~~~~~~~~
Maps usually do not have to have axis labels. You can turn them off using ``set_axis_off()`` or ``axis("off")`` axis methods.
.. ipython:: python
ax = chicago.plot()
@savefig set_axis_off.png
ax.set_axis_off();
Maps with layers
-----------------
There are two strategies for making a map with multiple layers -- one more succinct, and one that is a little more flexible.
Before combining maps, however, remember to always ensure they share a common CRS (so they will align).
.. ipython:: python
# Look at capitals
# Note use of standard `pyplot` line style options
@savefig capitals.png
groceries.plot(marker='*', color='green', markersize=5);
# Check crs
groceries = groceries.to_crs(chicago.crs)
# Now you can overlay over the outlines
**Method 1**
.. ipython:: python
base = chicago.plot(color='white', edgecolor='black')
@savefig groceries_over_chicago_1.png
groceries.plot(ax=base, marker='o', color='red', markersize=5);
**Method 2: Using matplotlib objects**
.. ipython:: python
fig, ax = plt.subplots()
chicago.plot(ax=ax, color='white', edgecolor='black')
groceries.plot(ax=ax, marker='o', color='red', markersize=5)
@savefig groceries_over_chicago_2.png
plt.show();
Control the order of multiple layers in a plot
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When plotting multiple layers, use ``zorder`` to take control of the order of layers being plotted.
The lower the ``zorder`` is, the lower the layer is on the map and vice versa.
Without specified ``zorder``, cities (Points) gets plotted below world (Polygons), following the default order based on geometry types.
.. ipython:: python
ax = groceries.plot(color='k')
@savefig zorder_default.png
chicago.plot(ax=ax);
You can set the ``zorder`` for cities higher than for world to move it of top.
.. ipython:: python
ax = groceries.plot(color='k', zorder=2)
@savefig zorder_set.png
chicago.plot(ax=ax, zorder=1);
Pandas plots
-----------------
Plotting methods also allow for different plot styles from pandas
along with the default ``geo`` plot. These methods can be accessed using
the ``kind`` keyword argument in :meth:`~GeoDataFrame.plot`, and include:
* ``geo`` for mapping
* ``line`` for line plots
* ``bar`` or ``barh`` for bar plots
* ``hist`` for histogram
* ``box`` for boxplot
* ``kde`` or ``density`` for density plots
* ``area`` for area plots
* ``scatter`` for scatter plots
* ``hexbin`` for hexagonal bin plots
* ``pie`` for pie plots
.. ipython:: python
@savefig pandas_line_plot.png
chicago.plot(kind="scatter", x="POP2010", y="POP2000")
You can also create these other plots using the ``GeoDataFrame.plot.<kind>`` accessor methods instead of providing the ``kind`` keyword argument.
For example, ``hist``, can be used to plot histograms of population for two different years from the Chicago dataset.
.. ipython:: python
@savefig pandas_hist_plot.png
chicago[["POP2000", "POP2010", "geometry"]].plot.hist(alpha=.4)
For more information, see `Chart visualization <https://pandas.pydata.org/pandas-docs/stable/user_guide/visualization.html>`_ in the pandas documentation.
Other resources
-----------------
Links to Jupyter Notebooks for different mapping tasks:
`Making Heat Maps <http://nbviewer.jupyter.org/gist/perrygeo/c426355e40037c452434>`_
.. ipython:: python
:suppress:
matplotlib.rcParams['figure.figsize'] = orig
.. ipython:: python
:suppress:
import matplotlib.pyplot as plt
plt.close('all')
|