Spaces:
Runtime error
Runtime error
File size: 5,396 Bytes
bcc2d25 |
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 |
import json
import folium
import pandas as pd
from folium import Marker
from folium.plugins import MarkerCluster
from jinja2 import Template
regions, countries, region_tree = json.load(
open("resources/country_regions.json", encoding="utf-8")
)
country_centers = json.load(
open("resources/country_center_coordinates.json", encoding="utf-8")
)
country_mappings = json.load(open("resources/country_mappings.json", encoding="utf-8"))
WORLD_GEO_URL = "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/world-countries.json"
ICON_CREATE_FUNCTIOM = """
function(cluster) {
var markers = cluster.getAllChildMarkers();
var sum = 0;
for (var i = 0; i < markers.length; i++) {
sum += markers[i].options.props.resources;
}
return L.divIcon({
html: '<b>' + sum + '</b>',
className: 'marker-cluster marker-cluster-small',
iconSize: new L.Point(20, 20)
});
}
"""
class MarkerWithProps(Marker):
_template = Template(
"""
{% macro script(this, kwargs) %}
var {{this.get_name()}} = L.marker(
[{{this.location[0]}}, {{this.location[1]}}],
{
icon: new L.Icon.Default(),
{%- if this.draggable %}
draggable: true,
autoPan: true,
{%- endif %}
{%- if this.props %}
props : {{ this.props }}
{%- endif %}
}
)
.addTo({{this._parent.get_name()}});
{% endmacro %}
"""
)
def __init__(
self, location, popup=None, tooltip=None, icon=None, draggable=False, props=None
):
super(MarkerWithProps, self).__init__(
location=location,
popup=popup,
tooltip=tooltip,
icon=icon,
draggable=draggable,
)
self.props = json.loads(json.dumps(props))
def get_region_center(region_name):
latitudes = []
longitudes = []
for name in region_tree[region_name]:
if name in region_tree:
region_latitudes, region_longitudes = get_region_center(name)
latitudes += region_latitudes
longitudes += region_longitudes
elif name in country_centers or name in country_mappings["to_center"]:
country_center = country_centers[
country_mappings["to_center"].get(name, name)
]
latitudes += [float(country_center["latitude"])]
longitudes += [float(country_center["longitude"])]
return latitudes, longitudes
def get_region_countries(region_name):
countries = []
for name in region_tree[region_name]:
if name in region_tree:
countries += get_region_countries(name)
else:
countries += [name]
return countries
def make_choro_map(resource_counts, marker_thres=0):
world_map = folium.Map(tiles="cartodbpositron", location=[0, 0], zoom_start=1.5)
marker_cluster = MarkerCluster(icon_create_function=ICON_CREATE_FUNCTIOM)
marker_cluster.add_to(world_map)
for name, count in resource_counts.items():
if name in country_centers or name in country_mappings["to_center"]:
country_center = country_centers[
country_mappings["to_center"].get(name, name)
]
MarkerWithProps(
location=[country_center["latitude"], country_center["longitude"]],
popup=f"{'Region' if name in region_tree else 'Country'} : {name}<br> \n Resources : {count} <br>",
props={"name": name, "resources": count},
).add_to(marker_cluster)
# put a pin at the center of the region
elif name in region_tree:
latitudes, longitudes = get_region_center(name)
if len(latitudes) > 0:
lat = sum(latitudes) / len(latitudes)
lon = sum(longitudes) / len(longitudes)
MarkerWithProps(
location=[lat, lon],
popup=f"{'Region' if name in region_tree else 'Country'} : {name}<br> \n Resources : {count} <br>",
props={"name": name, "resources": count},
).add_to(marker_cluster)
# for choropleth, add counts to all countries in a region
choropleth_counts = {}
for loc_name in list(resource_counts.keys()):
if loc_name in region_tree:
for country_name in get_region_countries(loc_name):
choropleth_counts[country_name] = (
choropleth_counts.get(country_name, 0) + resource_counts[loc_name]
)
else:
choropleth_counts[loc_name] = (
choropleth_counts.get(loc_name, 0) + resource_counts[loc_name]
)
df_resource_counts = pd.DataFrame(
[
(country_mappings["to_outline"].get(n, n), c)
for n, c in choropleth_counts.items()
],
columns=["Name", "Resources"],
)
folium.Choropleth(
geo_data=WORLD_GEO_URL,
name="resource map",
data=df_resource_counts,
columns=["Name", "Resources"],
key_on="feature.properties.name",
fill_color="PuRd",
nan_fill_color="white",
).add_to(world_map)
return world_map
|