# Non contiguous cartogram in Python

Cartograms are a kind a map that changes region size and/or shape according to a numerical variable. It's for example used to highlight population density differences between countries.

This post explains how to create a non-contiguous cartogram, which is a kind of cartogram that preserves shape but modify sizes. We'll go over a concrete example to illustrate difference in population density in Asia.

To give you a visual idea, here is the cartogram we will step-by-step create in this post:

## Libraries & Data

For creating this chart, we will need to load the following libraries:

• matplotlib for plotting the chart
• `geopandas` and `geoplot`: for spatial data plotting
• pypalettes: for the color palette
• highlight_text for the annotations
``````# matplotlib tools
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

# map libraries
import geopandas as gpd
import geoplot as gplt
import geoplot.crs as gcrs

# colors

# annotations
from highlight_text import fig_text, ax_text

# data manipulation
import pandas as pd

# increase resolution
plt.rcParams['figure.dpi'] = 300
plt.rcParams['savefig.dpi'] = 300``````

## Dataset

``````world = gpd.read_file('https://raw.githubusercontent.com/holtzy/The-Python-Graph-Gallery/master/static/data/all_world.geojson')
name geometry
0 Fiji MULTIPOLYGON (((180.00000 -16.06713, 180.00000...
1 Tanzania POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...
2 W. Sahara POLYGON ((-8.66559 27.65643, -8.66512 27.58948...
3 Canada MULTIPOLYGON (((-122.84000 49.00000, -122.9742...
4 United States of America MULTIPOLYGON (((-122.84000 49.00000, -120.0000...

``````# get asian population dataset
url = 'https://raw.githubusercontent.com/holtzy/The-Python-Graph-Gallery/master/static/data/asia.csv'
Country Total Population Surface Area (sq. km)
0 Russia 1.444444e+08 17098250.0
1 China 1.425671e+09 9600013.0
2 India 1.428628e+09 3287259.0
3 Kazakhstan 1.960663e+07 2724902.0
4 Saudi Arabia 3.694702e+07 2149690.0

Once we have our 2 datasets, we can merge them and create `pop_norm_surface` column as a measure of population density:

``````# merge the datasets together
data = world.merge(asia, how='right', left_on='name', right_on='Country')

# filter the data
data = data[['Country', 'geometry', 'Total Population', 'Surface Area (sq. km)']]
data.dropna(inplace=True)
data['pop_norm_surface'] = data['Total Population'] / data['Surface Area (sq. km)']

# display first rows
data.columns = ['Country', 'geometry', 'pop', 'surfaces', 'pop_norm_surface']
Country geometry pop surfaces pop_norm_surface
1 China MULTIPOLYGON (((109.47521 18.19770, 108.65521 ... 1.425671e+09 9600013.0 148.507231
2 India POLYGON ((97.32711 28.26158, 97.40256 27.88254... 1.428628e+09 3287259.0 434.595407
3 Kazakhstan POLYGON ((87.35997 49.21498, 86.59878 48.54918... 1.960663e+07 2724902.0 7.195354
4 Saudi Arabia POLYGON ((34.95604 29.35655, 36.06894 29.19749... 3.694702e+07 2149690.0 17.187141
5 Indonesia MULTIPOLYGON (((141.00021 -2.60015, 141.01706 ... 2.775341e+08 1916862.0 144.785656

## Simple map of Asia

Let's start by a creating a simple version of our chart:

• create a figure and axe using the `figure()` and `add_subplot()` functions
• create the cartogram with the `cartogram()` function from geoplot. We specify that we want the size and the color of each country to be mapped with the `pop_norm_surface` column of our dataset (aka density population)
• create the background map with the `popyplot()` function from geoplot

And that's it!

``````fig = plt.figure(figsize=(12, 7))

gplt.cartogram(
data, projection=gcrs.PlateCarree(),
scale='pop_norm_surface', hue='pop_norm_surface', limits=(0,1),
ax=ax
)
gplt.polyplot(data, ax=ax)
plt.show()``````

## Custom colors

Now we can add a bit of customization:

• load a color map using pypalettes
• use the `set_facecolor()` function to change the background color of the graph
• change the color of the background map
• reduce the `linewidth` argument from 1 to 0.1
``````# colors
background_color = '#edf2f4'
text_color = '#14213d'
map_color = 'white'

fig = plt.figure(figsize=(12, 7))