Skip to content

Instantly share code, notes, and snippets.

@ResidentMario
Last active February 13, 2023 21:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ResidentMario/ac2db57d1c6652ddbc4112a3d318c746 to your computer and use it in GitHub Desktop.
Save ResidentMario/ac2db57d1c6652ddbc4112a3d318c746 to your computer and use it in GitHub Desktop.
Sankey webmap
license: mit

This webmap demonstates the result of using the geoplot and mplleaflet Python libraries to generate a simple HTML webmap. It was created with the following code:

# Load the data (uses the `quilt` package).
import geopandas as gpd
from quilt.data.ResidentMario import geoplot_data

troop_movements = gpd.read_file(geoplot_data.napoleon_troop_movements())
troop_movements['from'] = troop_movements.geometry.map(lambda v: v[0])
troop_movements['to'] = troop_movements.geometry.map(lambda v: v[1])


# Plot the data. We'll use a custom colormap, to match Minard's.
import geoplot as gplt
import matplotlib.pyplot as plt
import mplleaflet

from matplotlib.colors import LinearSegmentedColormap
colors = [(215/255, 193/255, 126/255), (37/255, 37/255, 37/255)]
cm = LinearSegmentedColormap.from_list('minard', colors)


gplt.sankey(troop_movements, start='from', end='to',
            scale='survivors', limits=(0.5, 45),
            hue='direction', categorical=True, cmap=cm)
fig = plt.gcf()
mplleaflet.save_html(fig, fileobj='minard-napoleon-russia.html')

The visualization chosen here is Minard's famous visualization on Napoleon's lethal march to Moscow and back <https://en.wikipedia.org/wiki/Charles_Joseph_Minard#Work>_. Compare with the original:

<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css" />
<style>
#map5ad13fff52ed45d59add0f7bd113fdce {
height:100%;
}
</style>
</head>
<body>
<div id="map5ad13fff52ed45d59add0f7bd113fdce"></div>
<script text="text/javascript">
var map = L.map('map5ad13fff52ed45d59add0f7bd113fdce');
L.tileLayer(
"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{maxZoom:19, attribution: '<a href="https://github.com/jwass/mplleaflet">mplleaflet</a> | Map data (c) <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'}).addTo(map);
var gjData = {"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 45.0}, "geometry": {"type": "LineString", "coordinates": [[24.5, 55.0], [24.0, 54.9]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 45.0}, "geometry": {"type": "LineString", "coordinates": [[25.5, 54.5], [24.5, 55.0]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 42.351190476190474}, "geometry": {"type": "LineString", "coordinates": [[26.0, 54.7], [25.5, 54.5]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 39.70238095238095}, "geometry": {"type": "LineString", "coordinates": [[27.0, 54.8], [26.0, 54.7]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 37.05357142857142}, "geometry": {"type": "LineString", "coordinates": [[28.0, 54.9], [27.0, 54.8]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 31.75595238095238}, "geometry": {"type": "LineString", "coordinates": [[28.5, 55.0], [28.0, 54.9]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 27.782738095238095}, "geometry": {"type": "LineString", "coordinates": [[29.0, 55.1], [28.5, 55.0]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 23.809523809523807}, "geometry": {"type": "LineString", "coordinates": [[30.0, 55.2], [29.0, 55.1]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 23.147321428571427}, "geometry": {"type": "LineString", "coordinates": [[30.3, 55.3], [30.0, 55.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 19.174107142857142}, "geometry": {"type": "LineString", "coordinates": [[32.0, 54.8], [30.3, 55.3]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 18.51190476190476}, "geometry": {"type": "LineString", "coordinates": [[33.2, 54.9], [32.0, 54.8]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 16.80342261904762}, "geometry": {"type": "LineString", "coordinates": [[34.4, 55.5], [33.2, 54.9]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 13.214285714285714}, "geometry": {"type": "LineString", "coordinates": [[35.5, 55.4], [34.4, 55.5]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 13.214285714285714}, "geometry": {"type": "LineString", "coordinates": [[36.0, 55.5], [35.5, 55.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 13.214285714285714}, "geometry": {"type": "LineString", "coordinates": [[37.6, 55.8], [36.0, 55.5]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 13.214285714285714}, "geometry": {"type": "LineString", "coordinates": [[37.7, 55.7], [37.6, 55.8]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 12.949404761904761}, "geometry": {"type": "LineString", "coordinates": [[37.5, 55.7], [37.7, 55.7]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 12.816964285714285}, "geometry": {"type": "LineString", "coordinates": [[37.0, 55.0], [37.5, 55.7]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 12.684523809523808}, "geometry": {"type": "LineString", "coordinates": [[36.8, 55.0], [37.0, 55.0]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 11.492559523809524}, "geometry": {"type": "LineString", "coordinates": [[35.4, 55.3], [36.8, 55.0]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 7.254464285714286}, "geometry": {"type": "LineString", "coordinates": [[34.3, 55.2], [35.4, 55.3]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 4.870535714285714}, "geometry": {"type": "LineString", "coordinates": [[33.3, 54.8], [34.3, 55.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 3.1488095238095237}, "geometry": {"type": "LineString", "coordinates": [[32.0, 54.6], [33.3, 54.8]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 2.619047619047619}, "geometry": {"type": "LineString", "coordinates": [[30.4, 54.4], [32.0, 54.6]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 2.619047619047619}, "geometry": {"type": "LineString", "coordinates": [[29.2, 54.3], [30.4, 54.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 2.619047619047619}, "geometry": {"type": "LineString", "coordinates": [[28.5, 54.2], [29.2, 54.3]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 2.619047619047619}, "geometry": {"type": "LineString", "coordinates": [[28.3, 54.3], [28.5, 54.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 2.619047619047619}, "geometry": {"type": "LineString", "coordinates": [[27.5, 54.5], [28.3, 54.3]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 1.5595238095238095}, "geometry": {"type": "LineString", "coordinates": [[26.8, 54.3], [27.5, 54.5]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 1.8244047619047619}, "geometry": {"type": "LineString", "coordinates": [[26.4, 54.4], [26.8, 54.3]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 1.0297619047619047}, "geometry": {"type": "LineString", "coordinates": [[25.0, 54.4], [26.4, 54.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 0.5}, "geometry": {"type": "LineString", "coordinates": [[24.4, 54.4], [25.0, 54.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 0.5}, "geometry": {"type": "LineString", "coordinates": [[24.2, 54.4], [24.4, 54.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 0.5}, "geometry": {"type": "LineString", "coordinates": [[24.1, 54.4], [24.2, 54.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 7.916666666666666}, "geometry": {"type": "LineString", "coordinates": [[24.0, 55.1], [24.1, 54.4]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 7.916666666666666}, "geometry": {"type": "LineString", "coordinates": [[24.5, 55.2], [24.0, 55.1]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 7.916666666666666}, "geometry": {"type": "LineString", "coordinates": [[25.5, 54.7], [24.5, 55.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 5.267857142857142}, "geometry": {"type": "LineString", "coordinates": [[26.6, 55.7], [25.5, 54.7]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 4.340773809523809}, "geometry": {"type": "LineString", "coordinates": [[27.4, 55.6], [26.6, 55.7]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 4.340773809523809}, "geometry": {"type": "LineString", "coordinates": [[28.7, 55.5], [27.4, 55.6]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 4.340773809523809}, "geometry": {"type": "LineString", "coordinates": [[28.7, 55.5], [28.7, 55.5]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 3.943452380952381}, "geometry": {"type": "LineString", "coordinates": [[29.2, 54.2], [28.7, 55.5]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 3.943452380952381}, "geometry": {"type": "LineString", "coordinates": [[28.5, 54.1], [29.2, 54.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 3.6785714285714284}, "geometry": {"type": "LineString", "coordinates": [[28.3, 54.2], [28.5, 54.1]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 2.883928571428571}, "geometry": {"type": "LineString", "coordinates": [[24.0, 55.2], [28.3, 54.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 2.883928571428571}, "geometry": {"type": "LineString", "coordinates": [[24.5, 55.3], [24.0, 55.2]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#D7C17E", "weight": 0.7648809523809523}, "geometry": {"type": "LineString", "coordinates": [[24.6, 55.8], [24.5, 55.3]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 0.7648809523809523}, "geometry": {"type": "LineString", "coordinates": [[24.6, 55.8], [24.6, 55.8]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 0.7648809523809523}, "geometry": {"type": "LineString", "coordinates": [[24.2, 54.4], [24.6, 55.8]]}}, {"type": "Feature", "properties": {"opacity": 1, "color": "#252525", "weight": 0.7648809523809523}, "geometry": {"type": "LineString", "coordinates": [[24.1, 54.4], [24.2, 54.4]]}}]};
if (gjData.features.length != 0) {
var gj = L.geoJson(gjData, {
style: function (feature) {
return feature.properties;
},
pointToLayer: function (feature, latlng) {
var icon = L.divIcon({'html': feature.properties.html,
iconAnchor: [feature.properties.anchor_x,
feature.properties.anchor_y],
className: 'empty'}); // What can I do about empty?
return L.marker(latlng, {icon: icon});
}
});
gj.addTo(map);
map.fitBounds(gj.getBounds());
} else {
map.setView([0, 0], 1);
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment