class plotnine.geoms.geom_map(*args, **kwargs)[source]

Draw map feature

The map feature are drawn without any special projections.


geom_map(mapping=None, data=None, stat='identity', position='identity',
         na_rm=False, inherit_aes=True, show_legend=None, draw='Polygon',

Only the mapping and data can be positional, the rest must be keyword arguments. **kwargs can be aesthetics (or parameters) used by the stat.

mapping : aes, optional

Aesthetic mappings created with aes(). If specified and inherit.aes=True, it is combined with the default mapping for the plot. You must supply mapping if there is no plot mapping.

Aesthetic Default value
alpha 1
color '#111111'
fill '#333333'
linetype 'solid'
shape 'o'
size 0.5
stroke 0.5

The bold aesthetics are required.

data : dataframe, optional

The data to be displayed in this layer. If None, the data from from the ggplot() call is used. If specified, it overrides the data from the ggplot() call.

stat : str or stat, optional (default: identity)

The statistical transformation to use on the data for this layer. If it is a string, it must be the registered and known to Plotnine.

position : str or position, optional (default: identity)

Position adjustment. If it is a string, it must be registered and known to Plotnine.

na_rm : bool, optional (default: False)

If False, removes missing values with a warning. If True silently removes missing values.

inherit_aes : bool, optional (default: True)

If False, overrides the default aesthetics.

show_legend : bool or dict, optional (default: None)

Whether this layer should be included in the legends. None the default, includes any aesthetics that are mapped. If a bool, False never includes and True always includes. A dict can be used to exclude specific aesthetis of the layer from showing in the legend. e.g show_legend={'color': False}, any other aesthetic are included by default.

draw : str in ['Polygon', 'Point', 'LineString']

What geometry types to draw. Note that Polygon includes MultiPolygon type.


This geom is best suited for plotting a shapefile read into geopandas dataframe. The dataframe should have a geometry column.


In [1]:
from geopandas import GeoDataFrame
import pandas as pd
from plotnine import *

%matplotlib inline

The Political Territories of Westeros

Layering different features on a Map

Read data and select features in Westeros only.

In [2]:
continents = GeoDataFrame.from_file('data/lands-of-ice-and-fire/continents.shp')
islands = GeoDataFrame.from_file('data/lands-of-ice-and-fire/islands.shp')
lakes = GeoDataFrame.from_file('data/lands-of-ice-and-fire/lakes.shp')
rivers = GeoDataFrame.from_file('data/lands-of-ice-and-fire/rivers.shp')
political = GeoDataFrame.from_file('data/lands-of-ice-and-fire/political.shp')
wall = GeoDataFrame.from_file('data/lands-of-ice-and-fire/wall.shp')
roads = GeoDataFrame.from_file('data/lands-of-ice-and-fire/roads.shp')
locations = GeoDataFrame.from_file('data/lands-of-ice-and-fire/locations.shp')

westeros = continents.query('name=="Westeros"')
islands = islands.query('continent=="Westeros" and name!="Summer Islands"')
lakes = lakes.query('continent=="Westeros"')
rivers = rivers.query('continent=="Westeros"')
roads = roads.query('continent=="Westeros"')

wg = westeros.geometry[0]
bool_idx = [wg.contains(g) for g in locations.geometry]
westeros_locations = locations[bool_idx]
cities = westeros_locations[westeros_locations['type'] == 'City']

Create map by placing the features in layers in an order that limits obstraction.

The GeoDataFrame.geometry.centroid property has the center coordinates of polygons, we use these to place the labels of the political regions.

In [3]:
# colors
water_color = '#a3ccff'
wall_color = 'white'
road_color = 'brown'

# Create label text by merging the territory name and
# the claimant to the territory
def fmt_labels(names, claimants):
    labels = []
    for name, claimant in zip(names, claimants):
        if name:
            labels.append('{} ({})'.format(name, claimant))
    return labels

 + geom_map(westeros, fill=None)
 + geom_map(islands, fill=None)
 + geom_map(political, aes(fill='ClaimedBy'), color=None, show_legend=False)
 + geom_map(wall, draw='LineString', color=wall_color, size=2)
 + geom_map(lakes, fill=water_color, color=None)
 + geom_map(rivers, aes(size='size'), draw='LineString', color=water_color, show_legend=False)
 + geom_map(roads, aes(size='size'), draw='LineString', color=road_color, alpha=0.5, show_legend=False)
 + geom_map(cities, draw='Point', size=1)
 + geom_text(
     aes('geometry.centroid.x', 'geometry.centroid.y', label='fmt_labels(name, ClaimedBy)'),
 + geom_text(
     aes('geometry.centroid.x', 'geometry.centroid.y', label='name'),
 + labs(title="The Political Territories of Westeros")
 + scale_fill_brewer(type='qual', palette=8)
 + scale_x_continuous(expand=(0, 0, 0, 1))
 + scale_y_continuous(expand=(0, 1, 0, 0))
 + scale_size_continuous(range=(0.4, 1))
 + theme_void()
 + theme(figure_size=(8, 12), panel_background=element_rect(fill=water_color))
<ggplot: (97654321012345679)>

Credit: cadaei of the cartographersguild website forum.