World database of large urban areas, 1950-2050

Public domain data by Nordpil: http://nordpil.com/go/resources/world-database-of-large-cities/

As of Seaborn 0.5, you will be able to supply custom projections with FacetGrid.

This example shows how can combine this feature with Cartopy to plot faceted data on maps.

In [1]:
%matplotlib inline

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

import cartopy.crs
import cartopy.feature
In [2]:
df = pd.read_table('https://gist.githubusercontent.com/shoyer/9698df62662ca7243180/raw/'
                   'c9d45b7c9acb3a47341cc8510415887f1b8f5e28/urbanareas1_1.tsv')
df = pd.melt(df, id_vars=['City', 'City_Alternate', 'Country', 'Latitude', 'Longitude', 'Country_ISO3'],
             value_name='Population')
df['Year'] = df['variable'].str.slice(3, 7).astype(int)
df['PopulationCategory'] = pd.cut(df['Population'], [0, 1000, 2000, 3000, 5000, 100000], right=False)
In [3]:
df.head()
Out[3]:
City City_Alternate Country Latitude Longitude Country_ISO3 variable Population Year PopulationCategory
0 Sofia NaN Bulgaria 42.70 23.33 BGR pop1950 520 1950 [0, 1000)
1 Mandalay NaN Myanmar 21.97 96.08 MMR pop1950 170 1950 [0, 1000)
2 Nay Pyi Taw NaN Myanmar 19.75 96.10 MMR pop1950 0 1950 [0, 1000)
3 Yangon Rangoon Myanmar 16.87 96.12 MMR pop1950 1300 1950 [1000, 2000)
4 Minsk NaN Belarus 53.89 27.57 BLR pop1950 280 1950 [0, 1000)
In [4]:
def scatterplot(x, y, s, color=None, **kwargs):
    # the default plt.scatter handles size scaling poorly, so we define our own
    # see also: https://github.com/mwaskom/seaborn/issues/315
    scaled_size = 0.005 * s
    plt.scatter(x, y, s=scaled_size, edgecolor=color, facecolor='none', linewidth=1, **kwargs)

g = sns.FacetGrid(df[df['Year'] % 25 == 0], col="Year", hue='PopulationCategory',
                  col_wrap=2, size=3.5, aspect=2, palette=sns.dark_palette('Red', 5),
                  subplot_kws=dict(projection=cartopy.crs.Mollweide()))
g.map(scatterplot, "Longitude", "Latitude", "Population",
      transform=cartopy.crs.PlateCarree(), zorder=10)
for ax in g.axes.ravel():
    ax.add_feature(cartopy.feature.COASTLINE)
    ax.add_feature(cartopy.feature.BORDERS)
    ax.set_global()