block by michalskop a9a5a6f506b79a373023

AR: Debt to Federal Government

Full Screen

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"/>
	<!--<script src="//code.jquery.com/jquery-1.8.2.min.js"></script>-->
	<!--<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">-->
	<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%;
		  /*margin: 0;
		  padding: 0;*/
		}
		#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 tips */  
        .d3-tip {
          line-height: 1;
          font-weight: bold;
          padding: 12px;
          background: rgba(0, 0, 0, 0.8);
          color: #fff;
          border-radius: 2px;
        }
        /* Creates a small triangle extender for the tooltip */
        .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;
        }
        /* Style northward tooltips differently */
        .d3-tip.n:after {
          margin: -1px 0 0 0;
          top: 100%;
          left: 0;
        }
        
        /*overwrite bootstrap*/
        .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">
      // Create the map
      var map = L.map('map',{zoomControl: false}).setView([-32.09673,-63.79409], 5);
      // add an OpenStreetMap tile layer
      // also see //wiki.openstreetmap.org/wiki/Tiles
	  //L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
	  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);
	  
	  //color scale
	  var color = d3.scale.linear()
        .domain([0, 1880, 6700])
        .range(["green", "yellow", "red"]);
	  
	  //add circles
	  d3.csv('argentina.csv', function(data) {
	  
	      //highlight country:
          ////oramind.com/country-border-highlighting-with-leaflet-js/
          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, {
		        //onEachFeature: onEachFeature,
		        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;
		  //because of bug in Leaflet, the following does not work properly (the overlays are always appended after the circles):
		  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

// d3.tip
// Copyright (c) 2013 Justin Palmer
//
// Tooltips for d3.js SVG visualizations

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module with d3 as a dependency.
    define(['d3'], factory)
  } else {
    // Browser global.
    root.d3.tip = factory(root.d3)
  }
}(this, function (d3) {

  // Public - contructs a new tooltip
  //
  // Returns a tip
  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)
    }
  
    // Public - show the tooltip on the screen
    //
    // Returns a tip
    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
    }
  
    // Public - hide the tooltip
    //
    // Returns a tip
    tip.hide = function() {
      nodel = d3.select(node)
      nodel.style({ opacity: 0, 'pointer-events': 'none' })
      return tip
    }
  
    // Public: Proxy attr calls to the d3 tip container.  Sets or gets attribute value.
    //
    // n - name of the attribute
    // v - value of the attribute
    //
    // Returns tip or attribute value
    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
    }
  
    // Public: Proxy style calls to the d3 tip container.  Sets or gets a style value.
    //
    // n - name of the property
    // v - value of the property
    //
    // Returns tip or style property value
    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
    }
  
    // Public: Set or get the direction of the tooltip
    //
    // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
    //     sw(southwest), ne(northeast) or se(southeast)
    //
    // Returns tip or direction
    tip.direction = function(v) {
      if (!arguments.length) return direction
      direction = v == null ? v : d3.functor(v)
  
      return tip
    }
  
    // Public: Sets or gets the offset of the tip
    //
    // v - Array of [x, y] offset
    //
    // Returns offset or
    tip.offset = function(v) {
      if (!arguments.length) return offset
      offset = v == null ? v : d3.functor(v)
  
      return tip
    }
  
    // Public: sets or gets the html value of the tooltip
    //
    // v - String value of the tip
    //
    // Returns html value or 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
    }
  
    // Private - gets the screen coordinates of a shape
    //
    // Given a shape on the screen, will return an SVGPoint for the directions
    // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
    // sw(southwest).
    //
    //    +-+-+
    //    |   |
    //    +   +
    //    |   |
    //    +-+-+
    //
    // Returns an Object {n, s, e, w, nw, sw, ne, se}
    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

# -*- coding: utf-8 -*-

# geocoding using open street map (centers)
# http://wiki.openstreetmap.org/wiki/Nominatim

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']]
  #raise(Exception,'')
  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"/>
	<!--<script src="//code.jquery.com/jquery-1.8.2.min.js"></script>-->
	<!--<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">-->
	<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%;
		  /*margin: 0;
		  padding: 0;*/
		}
		#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 tips */  
        .d3-tip {
          line-height: 1;
          font-weight: bold;
          padding: 12px;
          background: rgba(0, 0, 0, 0.8);
          color: #fff;
          border-radius: 2px;
        }
        /* Creates a small triangle extender for the tooltip */
        .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;
        }
        /* Style northward tooltips differently */
        .d3-tip.n:after {
          margin: -1px 0 0 0;
          top: 100%;
          left: 0;
        }
        
        /*overwrite bootstrap*/
        .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">
      // Create the map
      var map = L.map('map',{zoomControl: false}).setView([-32.09673,-63.79409], 5);
      // add an OpenStreetMap tile layer
      // also see //wiki.openstreetmap.org/wiki/Tiles
	  //L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
	  L.tileLayer('//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
	    attribution: 'CC-BY Michal Škop | &copy; <a href="//osm.org/copyright">OpenStreetMap</a> contributors'
	  }).addTo(map);
	  
	  //color scale
	  var color = d3.scale.linear()
        .domain([0, 1880, 6700])
        .range(["black", "#666", "#bbb"]);
	  
	  //add circles
	  d3.csv('argentina.csv', function(data) {
	  
	      //highlight country:
          ////oramind.com/country-border-highlighting-with-leaflet-js/
          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, {
		        //onEachFeature: onEachFeature,
		        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;
		  //because of bug in Leaflet, the following does not work properly (the overlays are always appended after the circles):
		  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>