Skip to content

Instantly share code, notes, and snippets.

@psychemedia
Last active October 27, 2015 20:47
Show Gist options
  • Save psychemedia/f7385255f89137c503b5 to your computer and use it in GitHub Desktop.
Save psychemedia/f7385255f89137c503b5 to your computer and use it in GitHub Desktop.
Code Club week 7 code resources
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('<iframe srcdoc="{srcdoc}" style="width: 100%; height: 510px; border: none"></iframe>'.format(srcdoc=map.HTML.replace('"', '&quot;')))
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('<iframe src="files/{path}" style="width: 100%; height: 510px; border: none"></iframe>'.format(path=path))
import json
import requests
def getFoodRatingData(name,address):
params={'name':name,'address':address}
r=requests.get('http://api.ratings.food.gov.uk/Establishments',
headers={"x-api-version":2},
params=params)
return r
def parseFoodRatingData(jdata):
df=pd.DataFrame()
for establishment in jdata['establishments']:
info={}
for item in ['BusinessName','FHRSID','PostCode','RatingValue','RatingDate']:
info[item]= establishment[item]
for item in establishment['geocode']:
info[item]= establishment['geocode'][item]
for item in establishment['scores']:
info[item]= establishment['scores'][item]
df=df.append(info,ignore_index=True)
return df
def getAndParseFoodRatingData(name,address):
r=getFoodRatingData(name,address)
jdata=json.loads(r.content)
df=parseFoodRatingData(jdata)
return df
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "",
"signature": "sha256:084b03018099bca8d5925040e4347eca0615e892705e5b9c929f4c2cbd637894"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Code Club Week 7"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you have a dataset that contains latitude and longitude data, one natural thing to do with it is put it on a map.\n",
"\n",
"In this notebook, we'll look at how to put the Code Club Eats data onto a map...\n",
"\n",
"The original data can be found in the [Code Club Eats Google spreadsheet](bitly.com/codeclubeats).\n",
"\n",
"In *Code Club Week 6*, you saw how we could geocode the date using the Google Maps geocoder in OpenRefine:\n",
"\n",
"- open the spreadsheet data into a new OpenRefine project\n",
"- from the *Postcode* column, `Edit column -> Add column by fetching URLs`, name the column something like *jsondata* and then use the following GREL expression to generate the URLs: `'http://maps.googleapis.com/maps/api/geocode/json?address='+escape(value,'url')+'&sensor=False'`\n",
"- from the new *jsondata* column, we need to create a couple of new columns (`Edit column -> Add column based on this column`), one called *Latitude* and one called *Longitude* (or something similar...)\n",
" - in one column, `parseJson(value)['results'][0]['geometry']['location']['lat']`\n",
" - in the other, `parseJson(value)['results'][0]['geometry']['location']['lng']`\n",
"- from the `Export` menu (top right), select `Custom tabular exporter`, select all the columns except the *jsondata* column, and save the file as a comma separated CSV file. (By the by, it is also possible to upload data from OpenRefine to Google spreadsheets using the Custom Tabular Exporter.) When you export the file, it should be placed into your normal *Downloads* directory."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Code Club Eats"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import pandas as pd"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Load the exported data file into a pandas dataframe."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Use the path to your own file\n",
"#If the file is in the current working directory, you just need the filename\n",
"#!pwd on Mac, !cd on Windows to find the current working directory, remember...\n",
"#Note that depending on your machine settings, sometimes when you look at the file in a file browser,\n",
"## the file suffix (.csv) may not be displayed.. But it is still there and does need adding to the filename\n",
"cceats=pd.read_csv('/Users/ajh59/Downloads/Code-Club-s-Fave-Restaurants-Sheet1-csv.csv')\n",
"cceats"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": [
{
"html": [
"<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Name</th>\n",
" <th>Postcode</th>\n",
" <th>longitude</th>\n",
" <th>latitude</th>\n",
" <th>Person recommended</th>\n",
" <th>Type of food</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0 </th>\n",
" <td> Sacro Cuore</td>\n",
" <td> NW10 3NB</td>\n",
" <td>-0.217232</td>\n",
" <td> 51.531975</td>\n",
" <td> Marcus</td>\n",
" <td> Pizza</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1 </th>\n",
" <td> Casse-Cro\ufffd\ufffdte</td>\n",
" <td> SE1 3XB</td>\n",
" <td>-0.081578</td>\n",
" <td> 51.500636</td>\n",
" <td> Timur</td>\n",
" <td> Bistro</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2 </th>\n",
" <td> Donna Margherita</td>\n",
" <td> SW11 5TE</td>\n",
" <td>-0.159551</td>\n",
" <td> 51.464603</td>\n",
" <td> Laia</td>\n",
" <td> Italian</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3 </th>\n",
" <td> Le Mercury</td>\n",
" <td> N1 1QY</td>\n",
" <td>-0.102773</td>\n",
" <td> 51.539820</td>\n",
" <td> Julia</td>\n",
" <td> French</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4 </th>\n",
" <td> Mondello</td>\n",
" <td> W1T 2QN</td>\n",
" <td>-0.135335</td>\n",
" <td> 51.519695</td>\n",
" <td> Danni</td>\n",
" <td> Italian</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5 </th>\n",
" <td> McDonald's</td>\n",
" <td> SW12 9AU</td>\n",
" <td>-0.151805</td>\n",
" <td> 51.444311</td>\n",
" <td> Andy</td>\n",
" <td> American</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6 </th>\n",
" <td> Silk Road </td>\n",
" <td> SE5 8TR</td>\n",
" <td>-0.089592</td>\n",
" <td> 51.474050</td>\n",
" <td> Steph</td>\n",
" <td> Chinese</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7 </th>\n",
" <td> Pedlar</td>\n",
" <td> SE15 4JR</td>\n",
" <td>-0.066710</td>\n",
" <td> 51.465554</td>\n",
" <td> Sam</td>\n",
" <td> Anything seasonal</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8 </th>\n",
" <td> Polpo Covent Garden</td>\n",
" <td> WC2E 7NA</td>\n",
" <td>-0.122964</td>\n",
" <td> 51.510676</td>\n",
" <td> Silvia</td>\n",
" <td> Venetian</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9 </th>\n",
" <td> McDonald's</td>\n",
" <td> WC1V 2JS</td>\n",
" <td>-0.117823</td>\n",
" <td> 51.517905</td>\n",
" <td> Tara</td>\n",
" <td> Fast food</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td> Il Convivio</td>\n",
" <td> SW1W 9QN</td>\n",
" <td>-0.150446</td>\n",
" <td> 51.492894</td>\n",
" <td> Francesca</td>\n",
" <td> Italian</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td> Al Maeda</td>\n",
" <td> E26DG</td>\n",
" <td>-0.071187</td>\n",
" <td> 51.524944</td>\n",
" <td> Ashraf</td>\n",
" <td> Turkish</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td> Climpson's Arch</td>\n",
" <td> E8 3SB</td>\n",
" <td>-0.058345</td>\n",
" <td> 51.539453</td>\n",
" <td> Joe</td>\n",
" <td> Thai</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td> Pizza Express</td>\n",
" <td> SE1 9QQ</td>\n",
" <td>-0.088722</td>\n",
" <td> 51.506211</td>\n",
" <td> Adrian</td>\n",
" <td> Pizza</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td> Janetira</td>\n",
" <td> W1F 0SR</td>\n",
" <td>-0.134633</td>\n",
" <td> 51.512193</td>\n",
" <td> Madeleine</td>\n",
" <td> Thai</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td> Pizza Express</td>\n",
" <td> SW17 7HR</td>\n",
" <td>-0.166470</td>\n",
" <td> 51.442481</td>\n",
" <td> Hina</td>\n",
" <td> Pizza</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td> Bodean's </td>\n",
" <td> SW4 7SS</td>\n",
" <td>-0.136328</td>\n",
" <td> 51.462159</td>\n",
" <td> Jon</td>\n",
" <td> BBQ</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 41,
"text": [
" Name Postcode longitude latitude Person recommended \\\n",
"0 Sacro Cuore NW10 3NB -0.217232 51.531975 Marcus \n",
"1 Casse-Cro\ufffd\ufffdte SE1 3XB -0.081578 51.500636 Timur \n",
"2 Donna Margherita SW11 5TE -0.159551 51.464603 Laia \n",
"3 Le Mercury N1 1QY -0.102773 51.539820 Julia \n",
"4 Mondello W1T 2QN -0.135335 51.519695 Danni \n",
"5 McDonald's SW12 9AU -0.151805 51.444311 Andy \n",
"6 Silk Road SE5 8TR -0.089592 51.474050 Steph \n",
"7 Pedlar SE15 4JR -0.066710 51.465554 Sam \n",
"8 Polpo Covent Garden WC2E 7NA -0.122964 51.510676 Silvia \n",
"9 McDonald's WC1V 2JS -0.117823 51.517905 Tara \n",
"10 Il Convivio SW1W 9QN -0.150446 51.492894 Francesca \n",
"11 Al Maeda E26DG -0.071187 51.524944 Ashraf \n",
"12 Climpson's Arch E8 3SB -0.058345 51.539453 Joe \n",
"13 Pizza Express SE1 9QQ -0.088722 51.506211 Adrian \n",
"14 Janetira W1F 0SR -0.134633 51.512193 Madeleine \n",
"15 Pizza Express SW17 7HR -0.166470 51.442481 Hina \n",
"16 Bodean's SW4 7SS -0.136328 51.462159 Jon \n",
"\n",
" Type of food \n",
"0 Pizza \n",
"1 Bistro \n",
"2 Italian \n",
"3 French \n",
"4 Italian \n",
"5 American \n",
"6 Chinese \n",
"7 Anything seasonal \n",
"8 Venetian \n",
"9 Fast food \n",
"10 Italian \n",
"11 Turkish \n",
"12 Thai \n",
"13 Pizza \n",
"14 Thai \n",
"15 Pizza \n",
"16 BBQ "
]
}
],
"prompt_number": 41
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You may get an error when trying to load the data saying something along the lines of an ASCII codec not being able to handle UTF-8 (?!)... If so, here's the fix... (this is a *Good Fragment to Remember*...)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#http://stackoverflow.com/questions/3828723/why-we-need-sys-setdefaultencodingutf-8-in-a-py-script\n",
"#If you get the ascii/utf-8 error, uncomment and run the following\n",
"#import sys\n",
"#reload(sys)\n",
"#sys.setdefaultencoding(\"utf-8\")\n",
"#NOTE - you should only need to do this once"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To plot markers on to a map idetnifying each Code Club Eats location, we need to do a couple of things:\n",
"\n",
"- get a map;\n",
"- put a separate marker on to the map for each object.\n",
"\n",
"To make life easier working with maps, we can use the *folium* package, which contains a set of functions that do lots of heavy lifting for us and give us a simple means by which we can work with maps.\n",
"\n",
"*folium* is not part of the standard Anaconda python distribution, so we need to install the package before we can load it."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#This should work - uncomment (remove the #) and run the following command line command:\n",
"#!pip install folium\n",
"\n",
"#NOTE - you only need to install the package once.\n",
"#What the command does is fetch the package files from an online directory of python packages and then\n",
"## install them into the python distribution on your own computer.\n",
"\n",
"#If it doesn't work (i.e. you get error messages...) then try to run the command directly:\n",
"## - open a terminal/command prompt\n",
"## - go to the Anaconda directory\n",
"## - go into the bin directory (which is where the pip command lives...) and run:\n",
"#pip install folium"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Having installed the package, we can load it in to the notebook\n",
"import folium"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#If the package has not been installed, you will see something like:\n",
"#ImportError: No module named folium\n",
"\n",
"#If you ever see that sort of error, you need to install the missing package...\n",
"#So if you try to run:\n",
"#import foo\n",
"#and see: ImportError: No module named foo\n",
"#what do you need to do?\n",
"#Try: pip install foo"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To embed maps in notebooks, we need to add a couple of helper functions that allow us to insert generated maps into a notebook in a couple of ways.\n",
"\n",
"From the gist at [bit.ly/ccweek7code](https://gist.github.com/psychemedia/f7385255f89137c503b5), grab the code from *folium_base.py* and run it in a code cell."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Programmers share code - and reuse each others' code - all the time...\n",
"#(that's partly what libraries and packages are about).\n",
"#Copy and paste the folium_base.py code here and run the cell\n",
"\n"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import HTML\n",
"import folium\n",
" \n",
"def inline_map(map):\n",
" \"\"\"\n",
" Embeds the HTML source of the map directly into the IPython notebook.\n",
" \n",
" This method will not work if the map depends on any files (json data). Also this uses\n",
" the HTML5 srcdoc attribute, which may not be supported in all browsers.\n",
" \"\"\"\n",
" map._build_map()\n",
" return HTML('<iframe srcdoc=\"{srcdoc}\" style=\"width: 100%; height: 510px; border: none\"></iframe>'.format(srcdoc=map.HTML.replace('\"', '&quot;')))\n",
" \n",
"def embed_map(map, path=\"map.html\"):\n",
" \"\"\"\n",
" Embeds a linked iframe to the map into the IPython notebook.\n",
" \n",
" Note: this method will not capture the source of the map into the notebook.\n",
" This method should work for all maps (as long as they use relative urls).\n",
" \"\"\"\n",
" map.create_map(path=path)\n",
" return HTML('<iframe src=\"files/{path}\" style=\"width: 100%; height: 510px; border: none\"></iframe>'.format(path=path))"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The *folium_base.py* code contains two functions - one embeds a map directly in the notebook (`inline_map()`), the other generates a file (by default called *map.html* (can you figure out how to change that to *mymap.html*?) that will be saved to your current working directory and that is then loaded into an HTML iframe in the notebook (`embed_map()`)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To create a map and pop markers on it using *folium*, we need to:\n",
"\n",
"- create the basemap (`folium.Map(location=[LAT, LONG])`), specifiying an initial central point as a list containing a latitude and a longitude, and optionally a zoom level (e.g. `zoom_start=9`)\n",
"- add markers one at a time (`.simple_marker( [MARKER_LAT, MARKER_LONG] )`"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cceats"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"fmap=folium.Map(location=[51.5, 0])\n",
"def plotmarker(row):\n",
" fmap.simple_marker( [row['latitude'], row['longitude']] )\n",
" \n",
"# \"for\" loops are common to a wide variety of proramming languages, allowing you to do something a particular number\n",
"# of times or for each item in a list or set of things.\n",
"#The iterrows() method enables you to iterate through each row in the dataframe.\n",
"#This allows you to do something to each row in turn\n",
"#iterrows() actually returns a couple of items at each pass - the row index value, and the row values by column name\n",
"#We want to access the second of those items, the row values by column name, so count to the second item: 0,1,..\n",
"#Once we have that second item, we need to say which column value we want from the row\n",
"for row in cceats.iterrows():\n",
" #The 'latitude' and 'longitude' names correspond to column names in the original cceats dataframe\n",
" latlon = [ row[1]['latitude'], row[1]['longitude'] ]\n",
" fmap.simple_marker( latlon )\n",
"embed_map(fmap)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**GOTCHA** - if maps stop displaying for any reason, save the notebook, shutdown that notebook down, then reopen it... (i.e. switch it off and on again?!;-) Note that you will need to re-run the code cells (but won't need to install it again from *pip*)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Alternative ways of doing it\n",
"\n",
"There are *always* other ways of doing things... To apply a function to each row of a *pandas* dataframe, we can use the `.apply()` method applied to `axis=1`. For example, we can create a simple function to add a marker to a map, and then \"apply\" that function to each row of the `cceats` dataframe.\n",
"\n",
"In the following example, note how we also calculate an intitial central point for the map automatically. (What other strategies might you use for finding a mid-point?)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"lat=cceats['latitude'].mean()\n",
"lon=cceats['longitude'].mean()\n",
"\n",
"fmap=folium.Map(location=[lat, lon], zoom_start=9)\n",
"\n",
"def plotmarker(row):\n",
" fmap.simple_marker( [row['latitude'], row['longitude']] )\n",
" \n",
"cceats.apply( plotmarker, axis=1)\n",
"inline_map(fmap)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Adding Marker Text\n",
"\n",
"If you click on a marker, you will notice that a pop box appears contain some not very interesting text...\n",
"\n",
"We can customise the text using the `popup` parameter. The text we use for the pop-up can contain HTML tags."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"fmap=folium.Map(location=[lat, lon], zoom_start=9)\n",
"\n",
"for row in cceats.iterrows():\n",
" latlon = [ row[1]['latitude'], row[1]['longitude'] ]\n",
" fmap.simple_marker( latlon, popup='This is my <strong>label</strong>' )\n",
"\n",
"inline_map(fmap)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": [
{
"html": [
"<iframe srcdoc=\"<!DOCTYPE html>\n",
"<head>\n",
" <meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=UTF-8&quot; />\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css&quot; />\n",
" <script src=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js&quot;></script>\n",
"\n",
" <script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js&quot;></script>\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css&quot;>\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css&quot;>\n",
" <script src=&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js&quot;></script>\n",
"\n",
" <link href=&quot;//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css&quot; rel=&quot;stylesheet&quot;>\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//rawgit.com/lvoogdt/Leaflet.awesome-markers/2.0/develop/dist/leaflet.awesome-markers.css&quot;>\n",
" <script src=&quot;//rawgithub.com/lvoogdt/Leaflet.awesome-markers/2.0/develop/dist/leaflet.awesome-markers.js&quot;></script>\n",
"\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/MarkerCluster.Default.css&quot;>\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/MarkerCluster.css&quot;>\n",
" <script src=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/leaflet.markercluster-src.js&quot;></script>\n",
" <script src=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/leaflet.markercluster.js&quot;></script>\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//birdage.github.io/Leaflet.awesome-markers/dist/leaflet.awesome.rotate.css&quot;>\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
" <style>\n",
"\n",
" html, body {\n",
" width: 100%;\n",
" height: 100%;\n",
" margin: 0;\n",
" padding: 0;\n",
" }\n",
"\n",
" #map {\n",
" position:absolute;\n",
" top:0;\n",
" bottom:0;\n",
" right:0;\n",
" left:0;\n",
" }\n",
"\n",
" </style>\n",
"</head>\n",
"\n",
"<body>\n",
"\n",
" <div class=&quot;folium-map&quot; id=&quot;folium_29c2cb5b425844d5ab72cea1b2555099&quot; style=&quot;width: 960px; height: 500px&quot;></div>\n",
"\n",
" <script>\n",
"\n",
" \n",
"\n",
" var base_tile = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {\n",
" maxZoom: 18,\n",
" minZoom: 1,\n",
" attribution: 'Map data (c) <a href=&quot;http://openstreetmap.org&quot;>OpenStreetMap</a> contributors'\n",
" });\n",
"\n",
" var baseLayer = {\n",
" &quot;Base Layer&quot;: base_tile\n",
" };\n",
"\n",
" /*\n",
" addition of the wms layers\n",
" */\n",
"\n",
" \n",
"\n",
" /*\n",
" addition of the tile layers\n",
" */\n",
" \n",
"\n",
" /*\n",
" list of layers to be added\n",
" */\n",
" var layer_list = {\n",
" \n",
" };\n",
"\n",
" /*\n",
" Bounding box.\n",
" */\n",
" var southWest = L.latLng(-90, -180),\n",
" northEast = L.latLng(90, 180),\n",
" bounds = L.latLngBounds(southWest, northEast);\n",
"\n",
" /*\n",
" Creates the map and adds the selected layers\n",
" */\n",
" var map = L.map('folium_29c2cb5b425844d5ab72cea1b2555099', {\n",
" center:[51.4970329471, -0.120676123529],\n",
" zoom: 9,\n",
" maxBounds: bounds,\n",
" layers: [base_tile]\n",
" });\n",
"\n",
" L.control.layers(baseLayer, layer_list).addTo(map);\n",
"\n",
" //cluster group\n",
" var clusteredmarkers = L.markerClusterGroup();\n",
" //section for adding clustered markers\n",
" \n",
" //add the clustered markers to the group anyway\n",
" map.addLayer(clusteredmarkers);\n",
"\n",
" \n",
" var marker_1_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_1 = L.marker([51.5319751, \n",
"\t\t\t\t\t\t\t-0.2172317],\n",
"\t\t\t\t\t\t\t{'icon':marker_1_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_1.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_1._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_1)\n",
" \n",
" var marker_2_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_2 = L.marker([51.5006362, \n",
"\t\t\t\t\t\t\t-0.0815785],\n",
"\t\t\t\t\t\t\t{'icon':marker_2_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_2.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_2._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_2)\n",
" \n",
" var marker_3_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_3 = L.marker([51.4646027, \n",
"\t\t\t\t\t\t\t-0.1595512],\n",
"\t\t\t\t\t\t\t{'icon':marker_3_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_3.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_3._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_3)\n",
" \n",
" var marker_4_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_4 = L.marker([51.5398198, \n",
"\t\t\t\t\t\t\t-0.1027733],\n",
"\t\t\t\t\t\t\t{'icon':marker_4_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_4.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_4._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_4)\n",
" \n",
" var marker_5_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_5 = L.marker([51.5196951, \n",
"\t\t\t\t\t\t\t-0.1353352],\n",
"\t\t\t\t\t\t\t{'icon':marker_5_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_5.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_5._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_5)\n",
" \n",
" var marker_6_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_6 = L.marker([51.4443105, \n",
"\t\t\t\t\t\t\t-0.151805],\n",
"\t\t\t\t\t\t\t{'icon':marker_6_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_6.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_6._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_6)\n",
" \n",
" var marker_7_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_7 = L.marker([51.47405, \n",
"\t\t\t\t\t\t\t-0.0895917],\n",
"\t\t\t\t\t\t\t{'icon':marker_7_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_7.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_7._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_7)\n",
" \n",
" var marker_8_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_8 = L.marker([51.4655545, \n",
"\t\t\t\t\t\t\t-0.0667096],\n",
"\t\t\t\t\t\t\t{'icon':marker_8_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_8.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_8._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_8)\n",
" \n",
" var marker_9_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_9 = L.marker([51.5106761, \n",
"\t\t\t\t\t\t\t-0.122964],\n",
"\t\t\t\t\t\t\t{'icon':marker_9_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_9.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_9._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_9)\n",
" \n",
" var marker_10_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_10 = L.marker([51.5179055, \n",
"\t\t\t\t\t\t\t-0.1178234],\n",
"\t\t\t\t\t\t\t{'icon':marker_10_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_10.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_10._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_10)\n",
" \n",
" var marker_11_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_11 = L.marker([51.4928939, \n",
"\t\t\t\t\t\t\t-0.1504457],\n",
"\t\t\t\t\t\t\t{'icon':marker_11_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_11.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_11._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_11)\n",
" \n",
" var marker_12_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_12 = L.marker([51.5249436, \n",
"\t\t\t\t\t\t\t-0.0711867],\n",
"\t\t\t\t\t\t\t{'icon':marker_12_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_12.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_12._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_12)\n",
" \n",
" var marker_13_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_13 = L.marker([51.5394525, \n",
"\t\t\t\t\t\t\t-0.0583448],\n",
"\t\t\t\t\t\t\t{'icon':marker_13_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_13.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_13._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_13)\n",
" \n",
" var marker_14_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_14 = L.marker([51.5062113, \n",
"\t\t\t\t\t\t\t-0.0887223],\n",
"\t\t\t\t\t\t\t{'icon':marker_14_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_14.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_14._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_14)\n",
" \n",
" var marker_15_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_15 = L.marker([51.5121932, \n",
"\t\t\t\t\t\t\t-0.1346328],\n",
"\t\t\t\t\t\t\t{'icon':marker_15_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_15.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_15._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_15)\n",
" \n",
" var marker_16_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_16 = L.marker([51.4424815, \n",
"\t\t\t\t\t\t\t-0.16647],\n",
"\t\t\t\t\t\t\t{'icon':marker_16_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_16.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_16._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_16)\n",
" \n",
" var marker_17_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_17 = L.marker([51.4621586, \n",
"\t\t\t\t\t\t\t-0.1363282],\n",
"\t\t\t\t\t\t\t{'icon':marker_17_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_17.bindPopup(&quot;This is my <strong>label</strong>&quot;);\n",
" marker_17._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_17)\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </script>\n",
"\n",
"</body>\" style=\"width: 100%; height: 510px; border: none\"></iframe>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 39,
"text": [
"<IPython.core.display.HTML at 0x1093b3a50>"
]
}
],
"prompt_number": 39
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**See if you can change the popup text in the previous code cell and then regenerate the map.**\n",
"\n",
"**Does it work as you expected?**\n",
"\n",
"\n",
"\n",
"\n",
"Having the same popup text for each marker is not very interesting. What text would be more informative?\n",
"\n",
"I think it could be more interesting to put the name of the eatery into the popup box. But how can we do that?\n",
"\n",
"One way would be to set the popup string value to the name of the establishment. You've already seen how to get the latitude and longitude for each row, so how would you set `popup` equal to the name?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"fmap=folium.Map(location=[lat, lon], zoom_start=9)\n",
"\n",
"for row in cceats.iterrows():\n",
" latlon = [ row[1]['latitude'], row[1]['longitude'] ]\n",
" fmap.simple_marker( latlon, popup=row[1]['Name'] )\n",
"\n",
"inline_map(fmap)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": [
{
"html": [
"<iframe srcdoc=\"<!DOCTYPE html>\n",
"<head>\n",
" <meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=UTF-8&quot; />\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css&quot; />\n",
" <script src=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js&quot;></script>\n",
"\n",
" <script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js&quot;></script>\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css&quot;>\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css&quot;>\n",
" <script src=&quot;//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js&quot;></script>\n",
"\n",
" <link href=&quot;//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css&quot; rel=&quot;stylesheet&quot;>\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//rawgit.com/lvoogdt/Leaflet.awesome-markers/2.0/develop/dist/leaflet.awesome-markers.css&quot;>\n",
" <script src=&quot;//rawgithub.com/lvoogdt/Leaflet.awesome-markers/2.0/develop/dist/leaflet.awesome-markers.js&quot;></script>\n",
"\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/MarkerCluster.Default.css&quot;>\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/MarkerCluster.css&quot;>\n",
" <script src=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/leaflet.markercluster-src.js&quot;></script>\n",
" <script src=&quot;//cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.4.0/leaflet.markercluster.js&quot;></script>\n",
"\n",
" <link rel=&quot;stylesheet&quot; href=&quot;//birdage.github.io/Leaflet.awesome-markers/dist/leaflet.awesome.rotate.css&quot;>\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
" <style>\n",
"\n",
" html, body {\n",
" width: 100%;\n",
" height: 100%;\n",
" margin: 0;\n",
" padding: 0;\n",
" }\n",
"\n",
" #map {\n",
" position:absolute;\n",
" top:0;\n",
" bottom:0;\n",
" right:0;\n",
" left:0;\n",
" }\n",
"\n",
" </style>\n",
"</head>\n",
"\n",
"<body>\n",
"\n",
" <div class=&quot;folium-map&quot; id=&quot;folium_cb13c858035447d2865a0ecd86d6dd62&quot; style=&quot;width: 960px; height: 500px&quot;></div>\n",
"\n",
" <script>\n",
"\n",
" \n",
"\n",
" var base_tile = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {\n",
" maxZoom: 18,\n",
" minZoom: 1,\n",
" attribution: 'Map data (c) <a href=&quot;http://openstreetmap.org&quot;>OpenStreetMap</a> contributors'\n",
" });\n",
"\n",
" var baseLayer = {\n",
" &quot;Base Layer&quot;: base_tile\n",
" };\n",
"\n",
" /*\n",
" addition of the wms layers\n",
" */\n",
"\n",
" \n",
"\n",
" /*\n",
" addition of the tile layers\n",
" */\n",
" \n",
"\n",
" /*\n",
" list of layers to be added\n",
" */\n",
" var layer_list = {\n",
" \n",
" };\n",
"\n",
" /*\n",
" Bounding box.\n",
" */\n",
" var southWest = L.latLng(-90, -180),\n",
" northEast = L.latLng(90, 180),\n",
" bounds = L.latLngBounds(southWest, northEast);\n",
"\n",
" /*\n",
" Creates the map and adds the selected layers\n",
" */\n",
" var map = L.map('folium_cb13c858035447d2865a0ecd86d6dd62', {\n",
" center:[51.4970329471, -0.120676123529],\n",
" zoom: 9,\n",
" maxBounds: bounds,\n",
" layers: [base_tile]\n",
" });\n",
"\n",
" L.control.layers(baseLayer, layer_list).addTo(map);\n",
"\n",
" //cluster group\n",
" var clusteredmarkers = L.markerClusterGroup();\n",
" //section for adding clustered markers\n",
" \n",
" //add the clustered markers to the group anyway\n",
" map.addLayer(clusteredmarkers);\n",
"\n",
" \n",
" var marker_1_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_1 = L.marker([51.5319751, \n",
"\t\t\t\t\t\t\t-0.2172317],\n",
"\t\t\t\t\t\t\t{'icon':marker_1_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_1.bindPopup(&quot;Sacro Cuore&quot;);\n",
" marker_1._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_1)\n",
" \n",
" var marker_2_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_2 = L.marker([51.5006362, \n",
"\t\t\t\t\t\t\t-0.0815785],\n",
"\t\t\t\t\t\t\t{'icon':marker_2_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_2.bindPopup(&quot;Casse-Cro\\ufffd\\ufffdte&quot;);\n",
" marker_2._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_2)\n",
" \n",
" var marker_3_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_3 = L.marker([51.4646027, \n",
"\t\t\t\t\t\t\t-0.1595512],\n",
"\t\t\t\t\t\t\t{'icon':marker_3_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_3.bindPopup(&quot;Donna Margherita&quot;);\n",
" marker_3._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_3)\n",
" \n",
" var marker_4_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_4 = L.marker([51.5398198, \n",
"\t\t\t\t\t\t\t-0.1027733],\n",
"\t\t\t\t\t\t\t{'icon':marker_4_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_4.bindPopup(&quot;Le Mercury&quot;);\n",
" marker_4._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_4)\n",
" \n",
" var marker_5_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_5 = L.marker([51.5196951, \n",
"\t\t\t\t\t\t\t-0.1353352],\n",
"\t\t\t\t\t\t\t{'icon':marker_5_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_5.bindPopup(&quot;Mondello&quot;);\n",
" marker_5._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_5)\n",
" \n",
" var marker_6_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_6 = L.marker([51.4443105, \n",
"\t\t\t\t\t\t\t-0.151805],\n",
"\t\t\t\t\t\t\t{'icon':marker_6_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_6.bindPopup(&quot;McDonald's&quot;);\n",
" marker_6._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_6)\n",
" \n",
" var marker_7_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_7 = L.marker([51.47405, \n",
"\t\t\t\t\t\t\t-0.0895917],\n",
"\t\t\t\t\t\t\t{'icon':marker_7_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_7.bindPopup(&quot;Silk Road &quot;);\n",
" marker_7._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_7)\n",
" \n",
" var marker_8_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_8 = L.marker([51.4655545, \n",
"\t\t\t\t\t\t\t-0.0667096],\n",
"\t\t\t\t\t\t\t{'icon':marker_8_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_8.bindPopup(&quot;Pedlar&quot;);\n",
" marker_8._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_8)\n",
" \n",
" var marker_9_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_9 = L.marker([51.5106761, \n",
"\t\t\t\t\t\t\t-0.122964],\n",
"\t\t\t\t\t\t\t{'icon':marker_9_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_9.bindPopup(&quot;Polpo Covent Garden&quot;);\n",
" marker_9._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_9)\n",
" \n",
" var marker_10_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_10 = L.marker([51.5179055, \n",
"\t\t\t\t\t\t\t-0.1178234],\n",
"\t\t\t\t\t\t\t{'icon':marker_10_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_10.bindPopup(&quot;McDonald's&quot;);\n",
" marker_10._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_10)\n",
" \n",
" var marker_11_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_11 = L.marker([51.4928939, \n",
"\t\t\t\t\t\t\t-0.1504457],\n",
"\t\t\t\t\t\t\t{'icon':marker_11_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_11.bindPopup(&quot;Il Convivio&quot;);\n",
" marker_11._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_11)\n",
" \n",
" var marker_12_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_12 = L.marker([51.5249436, \n",
"\t\t\t\t\t\t\t-0.0711867],\n",
"\t\t\t\t\t\t\t{'icon':marker_12_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_12.bindPopup(&quot;Al Maeda&quot;);\n",
" marker_12._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_12)\n",
" \n",
" var marker_13_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_13 = L.marker([51.5394525, \n",
"\t\t\t\t\t\t\t-0.0583448],\n",
"\t\t\t\t\t\t\t{'icon':marker_13_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_13.bindPopup(&quot;Climpson's Arch&quot;);\n",
" marker_13._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_13)\n",
" \n",
" var marker_14_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_14 = L.marker([51.5062113, \n",
"\t\t\t\t\t\t\t-0.0887223],\n",
"\t\t\t\t\t\t\t{'icon':marker_14_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_14.bindPopup(&quot;Pizza Express&quot;);\n",
" marker_14._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_14)\n",
" \n",
" var marker_15_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_15 = L.marker([51.5121932, \n",
"\t\t\t\t\t\t\t-0.1346328],\n",
"\t\t\t\t\t\t\t{'icon':marker_15_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_15.bindPopup(&quot;Janetira&quot;);\n",
" marker_15._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_15)\n",
" \n",
" var marker_16_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_16 = L.marker([51.4424815, \n",
"\t\t\t\t\t\t\t-0.16647],\n",
"\t\t\t\t\t\t\t{'icon':marker_16_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_16.bindPopup(&quot;Pizza Express&quot;);\n",
" marker_16._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_16)\n",
" \n",
" var marker_17_icon = L.AwesomeMarkers.icon({ icon: 'info-sign',markerColor: 'blue',prefix: 'glyphicon',extraClasses: 'fa-rotate-0'});\n",
" var marker_17 = L.marker([51.4621586, \n",
"\t\t\t\t\t\t\t-0.1363282],\n",
"\t\t\t\t\t\t\t{'icon':marker_17_icon}\n",
"\t\t\t\t\t\t\t);\n",
" marker_17.bindPopup(&quot;Bodean's &quot;);\n",
" marker_17._popup.options.maxWidth = 300;\n",
" map.addLayer(marker_17)\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </script>\n",
"\n",
"</body>\" style=\"width: 100%; height: 510px; border: none\"></iframe>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 40,
"text": [
"<IPython.core.display.HTML at 0x1093dc9d0>"
]
}
],
"prompt_number": 40
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**SEE IF YOU CAN CHANGE THE CODE SO THAT THE POPUP DISPLAYS THE NAME OF THE PERSON WHO RECOMMENDED THAT LOCATION.**\n",
"\n",
"**Once you've done that, try this...** *How would you modify the `plotmarker()` function to plot the name of each eatery in the `.apply()` route to adding map markers?*\n",
"\n",
"Copy the orginal code cell and hack the code yourself to see if you can generate popups containing the name of eatery using that method."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Adding the name of the eatery or person who recommended it to the popup box is one thing, but sometimes we may want to have more elaborate popup messages.\n",
"\n",
"To construct complex strings that blend static content and \"variable\" content, we can use the `\"\".format()` string method to produce template generated sentences."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\"This is my string.\".format()"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(\"This is my {} string.\".format(\"variable\"))\n",
"print(\"This is my {} string{}.\".format(\"variable\",\", okay?\"))\n",
"print(\"This is my {var1} string{other}.\".format(other=\"variable\",var1=\", okay?\"))"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**So how might you construct some (templated) popup text that says something taking the form:** *Wagamama (suggested by Sam)*."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"#Stuck? HINT: popup='Name: {name}'.format(name=row[1]['Name'])"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##Sharing Maps"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At the current time, a map created using `embed_map()` and saved to an HTML file (eg as *map.html*) expects to be viewed via a webserver. If you share the map file with someone (eg by emailing it to them) and they just double click on it to load it into a browser, the markers won't display because certain files used to display the markers can't be found (the browser looks for them on your computer rather than on the web).\n",
"\n",
"The following hack will patch the file so that the files can be found..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def patcher(fn='map.html'):\n",
" f=open(fn,'r')\n",
" html=f.read()\n",
" f.close()\n",
" html=html.replace('\"//','\"http://')\n",
" f=open(fn,'w')\n",
" f.write(html)\n",
" f.close()"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Run the patcher - by default, the file we look for is map.html in the current working directory\n",
"patcher()\n",
"\n",
"#You should now be able to double click on the file to open and view it correctly in your browser, share it by email etc"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Augmenting the Map With Data from Elsewhere\n",
"\n",
"The [Food Standards Agency](http://www.food.gov.uk/) is the agency that collates food hygiene ratings for all food related establishments in the UK. The site allows you to search for establishments by name and postcode and it will display the rating for that location. The FSA also publish an API that allow machines to get hold of the same information in a machine readable way.\n",
"\n",
"In Python, the `requests` library provides a range of tools that may it each to call an API and pull data (and web pages) down from the web."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import requests\n",
"\n",
"#http://api.ratings.food.gov.uk/help\n",
"#http://docs.python-requests.org/en/latest/user/quickstart/\n",
"\n",
"params={'name':\"McDonald's\",'address':'SW12 9AU'}\n",
"r=requests.get('http://api.ratings.food.gov.uk/Establishments',\n",
" headers={\"x-api-version\":2},\n",
" params=params)\n",
"r.content"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The data is returned as JSON - the same sort of stuff we got back from the Google geocoding API. Just as we coould parse that data in OpenRefine, we can do much the same in Python.\n",
"\n",
"In this case, the `json` library has the tools we need to parse the JSON into a Python `dict`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import json\n",
"\n",
"j=json.loads(r.content)\n",
"j"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"j['establishments'][0]['BusinessName']"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"j['establishments'][0]['geocode']['latitude']"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**How would you pull out the postcode?**\n",
"\n",
"**How would you pull out the *Hygiene* score?**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's have a go at trying to pull down the food ratings scores for Code Club Eateries. We could annotate the data we got from OpenRefine, but instead - noting that the FSA data includes latitude and longitude co-ordinates - let's just work from the original data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To grab a Google Spreadsheet file as a CSV file, use the URL pattern (SHEETNUMBER starts at 0):"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"https://docs.google.com/spreadsheets/d/<KEY>/export?gid=SHEETNUMBER&format=csv"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"url='https://docs.google.com/a/okfn.org/spreadsheets/d/1M14S4hqG4F5P8H78VdOMMeoITOPBpVZEGoiCvXEFBQg/export?gid=0&format=csv'\n",
"cceats_google=pd.read_csv(url)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cceats_google"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Be lazy... we can turn the original example of calling the FSA website into a function\n",
"def getFoodRatingData(name,address):\n",
" params={'name':name,'address':address}\n",
" r=requests.get('http://api.ratings.food.gov.uk/Establishments',\n",
" headers={\"x-api-version\":2},\n",
" params=params)\n",
" return r"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"tmp=getFoodRatingData(\"Mcdonald's\",\"SW12 9AU\")\n",
"tmp.content"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"tmp=getFoodRatingData('Sacro Cuore','NW10 3NB')\n",
"tmp.content"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Whilst we could manuually grab the data for establishment, that's not the lazy way. If you find yourself repeating yourself, let some code take the strain and automate the hassle away...\n",
"\n",
"We're going to do that in a couple of ways:\n",
"\n",
"- firstly, we'll automate the parsing of the JSON data returned for each establishment from the FSA and grab some of that data into a data frame\n",
"- secondly, we'll annotate the Code Club eats dataset with this food hygiene data"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#The pandas DataFrame .append() method can be used to add a python dict to a dataframe\n",
"stuff={'book':'War and Peace', 'opinion':'too long'}\n",
"\n",
"df_tmp = pd.DataFrame()\n",
"df_tmp = df_tmp.append(stuff,ignore_index=True)\n",
"df_tmp"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"df_tmp=df_tmp.append({'opinion':'cracking read','book':'Flash Boys'},ignore_index=True)\n",
"df_tmp"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also append one dataframe onto the end of another:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"df_tmp.append(df_tmp)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can parse the JSON data we got back from the FSA into a Python `dict`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Let's parse a json response from the FSA API as a function\n",
"def parseFoodRatingData(jdata):\n",
" df=pd.DataFrame()\n",
" #The FSA return a list of establishments, though the list may only contain one establishment\n",
" #Generate one row per establishment we get back\n",
" for establishment in jdata['establishments']:\n",
" #Create an empty dict to hold the data we want from the FSA API\n",
" info={}\n",
" #Here are some of the data items I want\n",
" for item in ['BusinessName','FHRSID','PostCode','RatingValue','RatingDate']:\n",
" #Take those items from the data returned from the FSA and put them into my 'useful data' dict\n",
" info[item]= establishment[item]\n",
" #We can also iterate through the items contained nested elements of the FSA data dict\n",
" for item in establishment['geocode']:\n",
" #..that is, the latitude and longitude elements...\n",
" info[item]= establishment['geocode'][item] \n",
" for item in establishment['scores']:\n",
" #..and here we grab the individual score components\n",
" info[item]= establishment['scores'][item]\n",
" #Now use the data we grabbed as the basis for a dataframe row\n",
" df=df.append(info,ignore_index=True)\n",
" return df"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"parseFoodRatingData(jdata)"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Let's simplify further - create another function that:\n",
"#-- gets the data from the FSA website\n",
"#-- parses it\n",
"#--returns it as a dataframe\n",
"def getAndParseFoodRatingData(name,address):\n",
" r=getFoodRatingData(name,address)\n",
" jdata=json.loads(r.content)\n",
" df=parseFoodRatingData(jdata)\n",
" return df"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"getAndParseFoodRatingData('Sacro Cuore','NW10 3NB')"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now it's time to construct a dataset that contains FSA information for each of the Code Club eateries. **Can you think of a way to do that?**\n",
"\n",
"One way might be to iterate through each item in the `cceats_google` Google dataframe and build a dataframe (that starts out empty) using dataframes generated from the FSA data."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#TRY HACKING SOMETHING TO SEE IF YOU CAN FIGURE OUT A WAY OF DOING IT..\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Here's one solution\n",
"\n",
"#Create a dummy dataframe to put stuff into\n",
"cceats_fsa=pd.DataFrame()\n",
"\n",
"#Iterate through each eatery in the data we grabbed from the Google spreadsheet\n",
"for place in cceats_google.iterrows():\n",
" #Using the name and postcode, grab the FSA rating for that establishment and add it to the growing cceats_fsa dataframe\n",
" cceats_fsa=cceats_fsa.append(getAndParseFoodRatingData(place[1]['Name'],place[1]['Postcode']),ignore_index=True)\n",
" \n",
"cceats_fsa"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Fortuitously, the postcodes in the original dataset are all unique, and they're also *exactly the same in terms of string equivalance* as the ones returned from the FSA. Which means we can use them as unique identifiers to merge the two datasets (the original one from the Google dataset, the other constructed from the FSA data)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cceats_bigdata=pd.merge(cceats_fsa,cceats_google,left_on='PostCode',right_on='Postcode')\n",
"cceats_bigdata"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Display the dataframe using reordered columns\n",
"cceats_bigdata[['FHRSID','BusinessName','Person recommended','Type of food','PostCode','RatingDate','RatingValue','latitude','longitude',\n",
" 'Structural','Hygiene','ConfidenceInManagement']]"
],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Using this dataset, see if you can generate a map with pop up markers that display the name of the establishment, the name of the person who recommended it, the food type, the rating value and (in brackets) the last inspection date. Remember, the pop text can include HTML, so if you know HTML, you should be able add in things like line breaks (&lt;br/&gt;) or emphasis, eg using &lt;strong&gt;&lt;/strong&gt; to display the establishment name using strong emphasis, (that is, in a bold font).**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {
"activity": false
},
"outputs": []
}
],
"metadata": {}
}
]
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment