index.html
<!DOCTYPE html>
<html>
<head>
<title>Argentina: Debt of Provinces to Federal Government</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.2.0/cerulean/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="//cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="d3.tip.js"></script>
<style type="text/css">
html, body{
width: 100%;
height: 100%;
}
#map {
width: 100%;
height: 95%;
}
.leaflet-tile-pane {
opacity: .4
}
.leaflet-container {
background-color: #fff;
}
.div-icon {
color: black;
line-height: 1.1;
font-size: 1.1em;
padding: 5px 15px 0 0;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.navbar {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand" href="#">Argentina: Debt of Provinces to Federal Government</a>
</div>
</div>
<div style="position:fixed;top:52px;z-index:1000;">
<div class="alert alert-info" ><strong>Size of bubbles</strong> represents population of provinces, <strong>color</strong> represents the debt to the federal government per capita.</div>
</div>
<div style="position:fixed;top:125px;z-index:1000;">
<div class="alert alert-info" style="float:left;">
<strong>Debt per capita</strong>:<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="#f00"></svg> high (upto 6700$)<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="yellow"></svg> average (1880$)<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="green"></svg> none (0$)
</div>
</div>
<div id="map"></div>
<script type="text/javascript">
var map = L.map('map',{zoomControl: false}).setView([-32.09673,-63.79409], 5);
L.tileLayer('//a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
attribution: 'CC-BY Michal Škop | Map tiles by CartoDB, under CC BY 3.0. Data by OpenStreetMap, under ODbL.'
}).addTo(map);
var color = d3.scale.linear()
.domain([0, 1880, 6700])
.range(["green", "yellow", "red"]);
d3.csv('argentina.csv', function(data) {
d3.json('argentina.json', function(json) {
function style(feature) {
return {
fillColor: "#3A87AD",
weight: 1,
opacity: 0.4,
color: '#3A87AD',
fillOpacity: 0.05
};
}
geojson = L.geoJson(json, {
style : style
}).addTo(map);
});
data.forEach(function(d,i) {
circle = L.circle([d.lat, d.lon], Math.sqrt(parseInt(d.population)*4000), {
color: color(d.debt),
fillColor: color(d.debt),
fillOpacity: 1,
weight: 1
}).addTo(map);
rnd = Math.round(d.population/1000)*1000;
description = '<div class="alert alert-info"><strong>'+d.name+'</strong><br>Population: '+rnd+'<br>Fed.Debt: '+d.debt+' $(pesos)/capita';
circle.bindPopup(description);
L.marker([d.lat, d.lon], {icon: L.divIcon({className: 'div-icon',html: d.name})}).addTo(map);
});
});
</script>
</body>
</html>
argentina.csv
name,slug,lat,lon,population,debt
Buenos Aires,buenosaires,-36.380504,-60.3888875,15625084,2093
Capital Federal,capital,-34.6160193,-58.4355560223,2890151,4
Catamarca,catamarca,-27.1910825,-67.105374,367828,3257
Chaco,chaco,-26.3829647,-60.8816092,1055259,1622
Chubut,chubut,-43.7127417,-68.7461847,509108,1946
Córdoba,cordoba,-32.0967361,-63.7940923,3308876,3773
Corrientes,corrientes,-28.5912315,-57.9394658,992595,1153
Entre Ríos,entrerios,-31.6252842,-59.3539578,1235994,2554
Formosa,formosa,-24.5955306,-60.4289718,530162,6709
Jujuy,jujuy,-23.19673745,-66.0589646499,673307,6170
La Pampa,lapampa,-37.2314643,-65.3972948,318951,31
La Rioja,larioja,-29.9729781,-67.0487944,333642,1073
Mendoza,mendoza,-34.8700721,-68.5479966,1738929,1571
Misiones,misiones,-26.737224,-54.4315257,1101593,2642
Neuquén,neuquen,-38.3533413,-69.8210841,551266,3532
Río Negro,rionegro,-40.4811973,-67.6145911,638645,5266
Salta,salta,-25.1089292,-64.3329697,1214441,980
San Juan,sanjuan,-30.7054363,-69.1988222,681055,1995
San Luis,sanluis,-33.3020349,-66.3369301,432310,0
Santa Cruz,santacruz,-48.5693327,-70.1606767,273964,1376
Santa Fe,santafe,-30.3154739,-61.1645076,3194537,0
Santiago del Estero,santiago,-27.6431016,-63.5408542,874006,0
Tierra del Fuego,tierradelfuego,-54.4071064,-67.8974895,127205,3137
Tucumán,tucuman,-26.5643582,-64.882397,1448188,2361
d3.tip.js
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['d3'], factory)
} else {
root.d3.tip = factory(root.d3)
}
}(this, function (d3) {
return function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if(args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = d3.select(node),
i = directions.length,
coords,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
nodel.html(content)
.style({ opacity: 1, 'pointer-events': 'all' })
while(i--) nodel.classed(directions[i], false)
coords = direction_callbacks.get(dir).apply(this)
nodel.classed(dir, true).style({
top: (coords.top + poffset[0]) + scrollTop + 'px',
left: (coords.left + poffset[1]) + scrollLeft + 'px'
})
return tip
}
tip.hide = function() {
nodel = d3.select(node)
nodel.style({ opacity: 0, 'pointer-events': 'none' })
return tip
}
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).attr(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.attr.apply(d3.select(node), args)
}
return tip
}
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).style(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.style.apply(d3.select(node), args)
}
return tip
}
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : d3.functor(v)
return tip
}
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : d3.functor(v)
return tip
}
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : d3.functor(v)
return tip
}
function d3_tip_direction() { return 'n' }
function d3_tip_offset() { return [0, 0] }
function d3_tip_html() { return ' ' }
var direction_callbacks = d3.map({
n: direction_n,
s: direction_s,
e: direction_e,
w: direction_w,
nw: direction_nw,
ne: direction_ne,
sw: direction_sw,
se: direction_se
}),
directions = direction_callbacks.keys()
function direction_n() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function direction_s() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function direction_e() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function direction_w() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function direction_nw() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function direction_ne() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function direction_sw() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function direction_se() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.e.x
}
}
function initNode() {
var node = d3.select(document.createElement('div'))
node.style({
position: 'absolute',
top: 0,
opacity: 0,
'pointer-events': 'none',
'box-sizing': 'border-box'
})
return node.node()
}
function getSVGNode(el) {
el = el.node()
if(el.tagName.toLowerCase() == 'svg')
return el
return el.ownerSVGElement
}
function getScreenBBox() {
var targetel = target || d3.event.target,
bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y
point.x = x
point.y = y
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
return tip
};
}));
geocode.py
import csv
import requests
import json
provinces = [{'slug':'buenosaires','name':'Buenos Aires'},
{'slug':'capital','name':'Capital Federal'},
{'slug':'catamarca','name':'Catamarca'},
{'slug':'cordoba','name':'Córdoba'},
{'slug':'corrientes','name':'Corrientes'},
{'slug':'chaco','name':'Chaco'},
{'slug':'chubut','name':'Chubut'},
{'slug':'entrerios','name':'Entre Ríos'},
{'slug':'formosa','name':'Formosa'},
{'slug':'jujuy','name':'Jujuy'},
{'slug':'lapampa','name':'La Pampa'},
{'slug':'larioja','name':'La Rioja'},
{'slug':'mendoza','name':'Mendoza'},
{'slug':'misiones','name':'Misiones'},
{'slug':'neuquen','name':'Neuquén'},
{'slug':'rionegro','name':'Río Negro'},
{'slug':'salta','name':'Salta'},
{'slug':'sanjuan','name':'San Juan'},
{'slug':'sanluis','name':'San Luis'},
{'slug':'santacruz','name':'Santa Cruz'},
{'slug':'santafe','name':'Santa Fe'},
{'slug':'santiago','name':'Santiago del Estero'},
{'slug':'tierradelfuego','name':'Tierra del Fuego'},
{'slug':'tucuman','name':'Tucumán'}]
outfile = open('geocoded.csv', 'wt')
outwriter = csv.writer(outfile, quoting=csv.QUOTE_NONNUMERIC)
for prov in provinces:
url = "http://nominatim.openstreetmap.org/search?country=Argentina&format=json&accept-language=es&state=" + prov['name']
r = requests.get(url)
djson = json.loads(r.text)
row = [prov['name'],prov['slug'],djson[0]['lat'],djson[0]['lon']]
outwriter.writerow(row)
print(prov['name'])
outfile.close()
index_bw.html
<!DOCTYPE html>
<html>
<head>
<title>Argentina: Debt of Provinces to Federal Government</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.2.0/paper/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="//cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="d3.tip.js"></script>
<style type="text/css">
html, body{
width: 100%;
height: 100%;
}
#map {
width: 100%;
height: 95%;
}
.leaflet-tile-pane {
opacity: .4
}
.leaflet-container {
background-color: #fff;
}
.div-icon {
color: white;
line-height: 1.1;
font-size: 2em;
padding: 5px 15px 0 0;
color: white;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.navbar {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand" href="#">Argentina: Dluh provincií vůči federální vládě</a>
</div>
</div>
<div style="position:fixed;top:52px;z-index:1000;">
<div class="h6" ><strong>Velikost bublin</strong> odpovídá počtu lidí v provincii, <strong>barva</strong> odpovídá zadluženosti vůči federální vládě per capita.</div>
</div>
<div style="position:fixed;top:125px;z-index:1000;">
<div class="h6" style="float:left;">
<strong>Dluh per capita</strong>:<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="black"></svg> vysoký (až 6700$)<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="#666"></svg> střední (1880$)<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="#bbb"></svg> žádný (0$)
</div>
</div>
<div id="map"></div>
<script type="text/javascript">
var map = L.map('map',{zoomControl: false}).setView([-32.09673,-63.79409], 5);
L.tileLayer('//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'CC-BY Michal Škop | © <a href="//osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var color = d3.scale.linear()
.domain([0, 1880, 6700])
.range(["black", "#666", "#bbb"]);
d3.csv('argentina.csv', function(data) {
d3.json('argentina.json', function(json) {
function style(feature) {
return {
fillColor: "#3A87AD",
weight: 1,
opacity: 0.4,
color: '#3A87AD',
fillOpacity: 0.05
};
}
geojson = L.geoJson(json, {
style : style
}).addTo(map);
});
data.forEach(function(d,i) {
circle = L.circle([d.lat, d.lon], Math.sqrt(parseInt(d.population)*4000), {
color: color(d.debt),
fillColor: color(d.debt),
fillOpacity: 1,
weight: 1
}).addTo(map);
rnd = Math.round(d.population/1000)*1000;
description = '<div class="alert alert-info"><strong>'+d.name+'</strong><br>Population: '+rnd+'<br>Fed.Debt: '+d.debt+' $(pesos)/capita';
circle.bindPopup(description);
L.marker([d.lat, d.lon], {icon: L.divIcon({className: 'div-icon',html: d.name})}).addTo(map);
});
});
</script>
</body>
</html>