Last active
August 29, 2015 14:26
-
-
Save simeonf/052aee61c1e1481e6311 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Sample map of Countries with vincent\n", | |
"\n", | |
"This is actually pretty straightforward - once you figure out the naming issues to makes vincent look at your data.\n", | |
"\n", | |
"First we need to import `vincent`, `pandas`, and `json` + call the `vincent.initialize_notebook()` to load the javascript needed to render our map in the browser." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"\n", | |
" <script>\n", | |
" \n", | |
" function vct_load_lib(url, callback){\n", | |
" if(typeof d3 !== 'undefined' &&\n", | |
" url === 'http://d3js.org/d3.v3.min.js'){\n", | |
" callback()\n", | |
" }\n", | |
" var s = document.createElement('script');\n", | |
" s.src = url;\n", | |
" s.async = true;\n", | |
" s.onreadystatechange = s.onload = callback;\n", | |
" s.onerror = function(){\n", | |
" console.warn(\"failed to load library \" + url);\n", | |
" };\n", | |
" document.getElementsByTagName(\"head\")[0].appendChild(s);\n", | |
" };\n", | |
" var vincent_event = new CustomEvent(\n", | |
" \"vincent_libs_loaded\",\n", | |
" {bubbles: true, cancelable: true}\n", | |
" );\n", | |
" \n", | |
" function load_all_libs(){\n", | |
" console.log('Loading Vincent libs...')\n", | |
" vct_load_lib('http://d3js.org/d3.v3.min.js', function(){\n", | |
" vct_load_lib('http://d3js.org/d3.geo.projection.v0.min.js', function(){\n", | |
" vct_load_lib('http://wrobstory.github.io/d3-cloud/d3.layout.cloud.js', function(){\n", | |
" vct_load_lib('http://wrobstory.github.io/vega/vega.v1.3.3.js', function(){\n", | |
" window.dispatchEvent(vincent_event);\n", | |
" });\n", | |
" });\n", | |
" });\n", | |
" });\n", | |
" };\n", | |
" if(typeof define === \"function\" && define.amd){\n", | |
" if (window['d3'] === undefined ||\n", | |
" window['topojson'] === undefined){\n", | |
" require.config(\n", | |
" {paths: {\n", | |
" d3: 'http://d3js.org/d3.v3.min',\n", | |
" topojson: 'http://d3js.org/topojson.v1.min'\n", | |
" }\n", | |
" }\n", | |
" );\n", | |
" require([\"d3\"], function(d3){\n", | |
" console.log('Loading Vincent from require.js...')\n", | |
" window.d3 = d3;\n", | |
" require([\"topojson\"], function(topojson){\n", | |
" window.topojson = topojson;\n", | |
" load_all_libs();\n", | |
" });\n", | |
" });\n", | |
" } else {\n", | |
" load_all_libs();\n", | |
" };\n", | |
" }else{\n", | |
" console.log('Require.js not found, loading manually...')\n", | |
" load_all_libs();\n", | |
" };\n", | |
"\n", | |
" </script>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"import json\n", | |
"\n", | |
"import vincent\n", | |
"import pandas as pd\n", | |
"\n", | |
"vincent.initialize_notebook()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now imagine we have some data reflecting the level of interest in a product in various countries. We'll represent that here as `list` of `dict`." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"countries = [{\"id\": 'USA', \"Interest\": 55}, \n", | |
" {\"id\": 'MEX', \"Interest\": 20},\n", | |
" {'id': 'CAN', 'Interest': 19}\n", | |
" ]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"To do data binding with vincent we need that data to be in a `pandas.Dataframe`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Interest</th>\n", | |
" <th>id</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>55</td>\n", | |
" <td>USA</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>20</td>\n", | |
" <td>MEX</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>19</td>\n", | |
" <td>CAN</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Interest id\n", | |
"0 55 USA\n", | |
"1 20 MEX\n", | |
"2 19 CAN" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"data_df = pd.DataFrame(countries)\n", | |
"data_df.head()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now we can build a geometry layer for the map. Several explanation:\n", | |
"\n", | |
"- `geo_data` is a list of data sources. The `name` field in each data source is the primary key. (We'll call our data source *countries*)\n", | |
"- The url must be an http-accessible url where topo-json data can be loaded. Just drop the files from https://github.com/wrobstory/vincent_map_data in the same directory as your notebook and Jupyter will serve them up. Because we rendering country data we're loading the `world-countries.topo.json` file. (Note: I'm direct-linking to github so I can put up a public gist. Don't do this otherwise!)\n", | |
"- Last - the feature is a topo.json feature name. Fortunately it's a key in the json file and for countries we use `world-countries`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"geo_data = [{'name': 'countries',\n", | |
" 'url': 'https://raw.githubusercontent.com/wrobstory/vincent_map_data/master/world-countries.topo.json',\n", | |
" 'feature': 'world-countries'}]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"And finally we can draw the map. \n", | |
"\n", | |
"The `Map` constructor needs data (that's our `Dataframe`), `geo_data` (our list of map geometry layers).\n", | |
"\n", | |
"It also takes some parameters to figure out how to relate the data to the geometry data. \n", | |
"\n", | |
"- `data_bind` tells it what column to use as a range in our data and we point it to the `Interest` column of our dataframe.\n", | |
"- `data_key` tells it what column in our dataframe to use to relate to the geometry data.\n", | |
"- `map_key` is a composite key: `key` part of the dict tells what geometry layer to look in (we only have one but you have to specify) and the `value` part of the dict tells you what field in the geometries object to look at in order to join a piece of data to a particular object in this geometry.\n", | |
"\n", | |
"If you open up the `world-countries.topo.json` you'd find the country objects look like:\n", | |
"\n", | |
" \"objects\": {\n", | |
" \"world-countries\": {\n", | |
" \"Geometries\": [\n", | |
" {\n", | |
" ... geo fields first, then some identifying info ...\n", | |
" \"id\": \"AFG\",\n", | |
" \"properties\": {\n", | |
" \"name\": \"Afghanistan\"\n", | |
" },\n", | |
" },\n", | |
"\n", | |
"We can bind to the `id` but if we had names we could specify `properties.name` as the field to join against." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div id=\"vis70283322ba144e1c8364df1cdd1e8dba\"></div>\n", | |
"<script>\n", | |
" ( function() {\n", | |
" var _do_plot = function() {\n", | |
" if (typeof vg === 'undefined') {\n", | |
" window.addEventListener('vincent_libs_loaded', _do_plot)\n", | |
" return;\n", | |
" }\n", | |
" vg.parse.spec({\"axes\": [], \"data\": [{\"name\": \"table\", \"values\": [{\"x\": \"USA\", \"y\": 55}, {\"x\": \"MEX\", \"y\": 20}, {\"x\": \"CAN\", \"y\": 19}]}, {\"format\": {\"feature\": \"world-countries\", \"type\": \"topojson\"}, \"name\": \"countries\", \"transform\": [{\"as\": \"value\", \"default\": \"noval\", \"key\": \"data.id\", \"type\": \"zip\", \"with\": \"table\", \"withKey\": \"data.x\"}, {\"test\": \"d.path!='noval' && d.value!='noval'\", \"type\": \"filter\"}, {\"projection\": \"winkel3\", \"scale\": 500, \"translate\": [480, 250], \"type\": \"geopath\", \"value\": \"data\"}], \"url\": \"https://raw.githubusercontent.com/wrobstory/vincent_map_data/master/world-countries.topo.json\"}], \"height\": 500, \"legends\": [], \"marks\": [{\"from\": {\"data\": \"countries\"}, \"properties\": {\"enter\": {\"path\": {\"field\": \"path\"}, \"stroke\": {\"value\": \"#000000\"}, \"strokeOpacity\": {\"value\": 0.2}}, \"update\": {\"fill\": {\"field\": \"value.data.y\", \"scale\": \"color\"}}}, \"type\": \"path\"}], \"padding\": \"auto\", \"scales\": [{\"domain\": [19, 51.49999999999999], \"name\": \"color\", \"range\": [\"#f7fcf0\", \"#e0f3db\", \"#ccebc5\", \"#a8ddb5\", \"#7bccc4\", \"#4eb3d3\", \"#2b8cbe\", \"#0868ac\", \"#084081\"], \"type\": \"quantize\"}], \"width\": 960}, function(chart) {\n", | |
" chart({el: \"#vis70283322ba144e1c8364df1cdd1e8dba\"}).update();\n", | |
" });\n", | |
" };\n", | |
" _do_plot();\n", | |
" })();\n", | |
"</script>\n", | |
"<style>.vega canvas {width: 100%;}</style>\n", | |
" " | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"vis = vincent.Map(data=data_df, \n", | |
" geo_data=geo_data,\n", | |
" data_bind='Interest', \n", | |
" data_key='id',\n", | |
" map_key={'countries': 'id'},\n", | |
" scale=500,\n", | |
" )\n", | |
"vis.marks[0].properties.enter.stroke_opacity = vincent.ValueRef(value=0.2)\n", | |
"vis.display()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.10" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment