#http://bit.ly/ccweek7code from IPython.display import HTML import folium def inline_map(map): """ Embeds the HTML source of the map directly into the IPython notebook. This method will not work if the map depends on any files (json data). Also this uses the HTML5 srcdoc attribute, which may not be supported in all browsers. """ map._build_map() return HTML(''.format(srcdoc=map.HTML.replace('"', '"'))) def embed_map(map, path="map.html"): """ Embeds a linked iframe to the map into the IPython notebook. Note: this method will not capture the source of the map into the notebook. This method should work for all maps (as long as they use relative urls). """ map.create_map(path=path) return HTML(''.format(path=path)) geojson_url_iw='http://mapit.mysociety.org/area/65791.geojson' iw_map = folium.Map(location=[50.666, -1.37], zoom_start=11) iw_map.geo_json(geo_path= geojson_url_iw) embed_map(iw_map,'iw_map.html') def patcher(fn='map.html'): f=open(fn,'r') html=f.read() f.close() html=html.replace('"//','"http://') f=open(fn,'w') f.write(html) f.close() patcher('iw_map.html') #We can also move up a level to the South East region (http://mapit.mysociety.org/area/11811.html) for example geojson_url_se='http://mapit.mysociety.org/area/11811.geojson' se_map = folium.Map(location=[51.4, -1], zoom_start=8) se_map.geo_json(geo_path= geojson_url_se,fill_color='green',fill_opacity=0.3) embed_map(se_map,'se_map.html') #See if you can figure out how to add several regions to the map, perhaps with different colours... #We can add additional layers to the map object, just as we added additional markers to the map last week #So for example, add an IW layer to the SE map... se_map.geo_json(geo_path= geojson_url_iw,fill_color='orange',fill_opacity=0.3) embed_map(se_map,'se_map.html') #Use the requests library to load the json data import requests import json regions='http://mapit.mysociety.org/area/61005/covers?type=UTE' jsondata=json.loads( requests.get(regions).content ) jsondata #We can iterate through the covered regions to grab their ids for key in jsondata: print(key) #Using iw_map, try to add white colour filled shapes for each UTE region in Newport for key in jsondata: tmp_url='http://mapit.mysociety.org/area/{}.geojson'.format(key) iw_map.geo_json(geo_path= tmp_url,fill_color='white',fill_opacity=1) embed_map(iw_map,'iw_map.html') #See if you can grab the data from http://www.electionforecast.co.uk/tables/predicted_probability_by_seat.html #into a pandas dataframe... #We can grab the data into a data frame by scraping the tabular HTML data from the URL directly #The pandas .read_html() function can accept a URL and will return a list of tables scraped from the page import pandas as pd df=pd.read_html('http://www.electionforecast.co.uk/tables/predicted_probability_by_seat.html') #We index into the table list response to get the table we want... df[0][:3] #Grab Westminster parliamentary constituency shapefiles from Martin Chorley's github repository import requests url='https://github.com/martinjc/UK-GeoJSON/blob/master/json/electoral/gb/wpc.json?raw=true' r = requests.get(url) #And save it to the local directory as the file wpc.json with open("wpc.json", "wb") as code: code.write(r.content) #Free up memory... r=None ?iw_map.geo_json #Now try plotting a map of UK Westminster Parliamentary Constituency boundaries #Here's one way... #Create a base map wpc_map = folium.Map(location=[55, 0], zoom_start=5) wpc_map.geo_json(geo_path= "wpc.json",fill_color='orange',fill_opacity=0.3) embed_map(wpc_map,'wpc_map.html') wpc_map.geo_json(geo_path='wpc.json', data=df[0],data_out='data_lab.json', columns=['Seat', 'Labour'], key_on='feature.properties.PCON13NM',threshold_scale=[0, 20, 40, 60, 80, 100], fill_color='OrRd') embed_map(wpc_map) #Create a forecast map showing the likelihood of the Conservatives taking each seat #Use a different colour theme such as GnBu for the colour scale #Other colour schemes can be found from the library docmentation - http://folium.readthedocs.org/en/latest/ forecast_m =pd.melt(df[0], id_vars=['Seat','Region'], value_vars=['Conservatives','Labour','Liberal Democrats','SNP','Plaid Cymru','Greens','UKIP','Other'], var_name='Party', value_name='forecast') forecast_m[:3] likelyparty=forecast_m.sort('forecast', ascending=False).groupby('Seat', as_index=False).first() likelyparty[:3] partycolours={'Conservatives':'blue', 'Labour':'red', 'Liberal Democrats':'yellow', 'SNP':'orange', 'Plaid Cymru':'pink', 'Greens':'green', 'UKIP':'purple', 'Other':'black'} likelyparty['colour']=likelyparty['Party'].map(partycolours) likelyparty[:3] import json jj=json.load(open('wpc.json')) for c in jj['features'][:3]: print(c['properties']['PCON13NM']) likelyparty[likelyparty['Seat']=='Aberavon'] #If we convert the dataframe to a dict, we can lookup colour by seat #Set the index to be the seat, then we get a nested dict keyed at the top level by column and then by seat likelyparty_dict=likelyparty.set_index('Seat').to_dict() likelyparty_dict['colour'] #Can you remember how we added boundaries for areas in Newport to the Isle of Wight map... #The following approach uses a similar principle forecast_map = folium.Map(location=[55, 0], zoom_start=5) #Iterate through each constituency in the geojson file getting each feature (constituency shapefile) in turn for c in jj['features']: #The geojson format requires that features are provided in a list and a FeatureCollection defined as the type #So we wrap the feature definition for each constituency in the necessary format geodata= {"type": "FeatureCollection", "features": [c]} #Get the name of the seat for the current constituency seat=c['properties']['PCON13NM'] #We can now lookup the colour colour= likelyparty_dict['colour'][seat] forecast_map.geo_json(geo_str= json.dumps(geodata),fill_color=colour,fill_opacity=1) embed_map(forecast_map,'forecast_map.html') #You will probably ned to install pyshp which contains the shapefile package #!pip install pyshp import shapefile #I got a few cribs for how to use this package to generate JOSN file from here #https://github.com/mlaloux/PyShp-as-Fiona--with-geo_interface- def records(filename): # generator reader = shapefile.Reader(filename) fields = reader.fields[1:] field_names = [field[0] for field in fields] for sr in reader.shapeRecords(): geom = sr.shape.__geo_interface__ atr = dict(zip(field_names, sr.record)) yield dict(geometry=geom,properties=atr) #shapefiles for African countries can be found here: #http://www.mapmakerdata.co.uk/library/stacks/Africa/ #eg I downloaded a file for Botswana via http://www.mapmakerdata.co.uk/library/stacks/Africa/Botswana/index.htm #from http://www.mapmakerdata.co.uk/library/stacks/Africa/Botswana/BOT_admin_SHP.zip #and then unzipped the file f='/Users/ajh59/Downloads/BOT_admin_SHP/BOT.shp' #Use the records() function to parse the shapefile c= records(f) #Here's what a single record looks like c.next() import json #The following routine will generate a json file equivalent of the shapefile def geojsonify(shpfile,fn='gtest.json'): geojson = open(fn, "w") features=[row for row in records(shpfile)] for row in features: row["type"]="Feature" geojson.write(json.dumps(dict(type='FeatureCollection',features=features))) geojson.close() !ls geojsonify(f,'gtestX.json') map_shp = folium.Map(location=[-25, 15], zoom_start=5) map_shp.geo_json(geo_path='gtestX.json') inline_map(map_shp)