#!/usr/bin/python # -*- coding: UTF-8 -*- #Uncomment next two lines to run in goolge colab #!pip install geopandas #!pip install geojson #importing data used to download files: import zipfile import urllib import requests import io #importing the geodata and data packages: import geopandas as gpd import geojson import pandas as pd #folium is the package that creates the map: import folium #file locations: fp_geodata_url = r"https://titlon.uit.no/hht/data/valgkretser.zip" fp_coins = r"https://titlon.uit.no/hht/img/coins" fp_data= r"https://titlon.uit.no/hht/data/valgkretser/data.csv" fp_geodata=r"Valgkrets.geojson" def main(): fp_geodata,data,geodata=get_data() create_map(fp_geodata,geodata,data) def get_data(): #loading demographic data: data=pd.read_csv(fp_data,encoding="latin-1",delimiter=";") #loading the geographical data #and converting to a coordinate system that folium understands: geodata = gpd.read_file(fp_geodata_url) geodata=geodata.to_crs('epsg:4326') #pandas does not handle æ, ø å, so creates columns in both the demographic data and geodata that can be matched: data['Bydel_dec']=data['Bydel'].apply(lambda s: str(s).encode('ascii','ignore').decode('ascii')) geodata['Bydel_dec']=geodata['VKRETS_V_1'].apply(lambda s: s.encode('ascii','ignore').decode('ascii')) #saving the geodata to a geoJSON file for use in the map (folium only eats geoJSON) geodata.to_file(fp_geodata, driver='GeoJSON') #returning the path and variable of the geodata, and the demographic data: return fp_geodata,geodata, data def create_map(fp_geodata,data,geodata): #creating the map tromso=folium.Map(location=[69.67, 18.98],zoom_start=10) #adding the colour overlay displaying "redness" of municipalities: f=folium.Choropleth( geo_data=fp_geodata, name="choropleth", columns=["Bydel_dec", "Rødhet"], data=data, key_on="feature.properties.Bydel_dec", fill_color="RdBu", nan_fill_color='white', fill_opacity=0.5, legend_name="Valgresultat oppslutning H+Frp minus Ap+SV+Rødt", ).add_to(tromso) folium.LayerControl().add_to(tromso) #the data needs to be merged on a variable with the same name: geodata['Bydel']=geodata['VKRETS_V_1'] #merging the demographic data into the geodata: geodata=geodata.merge(data,on='Bydel') for i,r in geodata.iterrows(): #obtaining coordinates: lat=float(r['Lat']) lon=float(r['Lon']) #creating pin for general demographic data t=(f"
{r['Bydel']}
" f"Inntekt: {r['Inntekt']}
" f"Alder: {frmt_int(r['Alder'])}
" f"Høyere utdanning: {frmt_int(r['Andel med høyere utdanning'])}%
" f"Ap+SV+Rødt: {frmt_int(r['ApSVRV']*100)}%
" f"H+FrP: {frmt_int(r['HFrp']*100)}%") folium.Marker([lat,lon-0.01],tooltip=t,icon=folium.Icon(color='red')).add_to(tromso) #creating pin for wealth. The height of the stack of coins is determined by the #picture file f"./img/{int(r['Mynter'])}coins.png": icon=folium.features.CustomIcon(f"{fp_coins}/{int(r['Mynter'])}coins.png") folium.Marker([lat,lon+0.01],tooltip=f"Formue:{r['Formue']}",icon=icon).add_to(tromso) #saving the map as a html file: tromso.save('./tromso.html') def frmt_int(value): "This function ensures an error free conversion of value to int" try: return int(value) except: return value main()