block by michalskop 13a7e9f1bdf03b0faa7c0b1d5bcbc838

SK: Regional Elections 2017

Full Screen

Slovak Regional Elections 2017

Municipalities colored by the winning candidate:

SK: https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/

EN: https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/index_en.html

Voters’ turnout:

SK: https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/turnout.html

common parameters (optional)

Example: https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/turnout.html?wheel=1

Pictures:

https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/winners.png

https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/winners_en.png

https://bl.ocks.org/michalskop/raw/13a7e9f1bdf03b0faa7c0b1d5bcbc838/turnout.png

Analysis flow

  1. file tab06d from https://www.volbysr.sk/sk/download.html cut as source.csv
  2. prepare_data.py -> source_reordered.csv, actors.csv
  3. manually adjust BA and KE in source_reordered.csv
  4. add geocodes geocode.py -> municipalities.csv
  5. adjust actors.csv manually (colors)
  6. adjust index.html and index_en.html
  7. file turnout.csv manually from https://www.volbysr.sk/sk/download.html
  8. adjust tunout.html

actors.csv

region_id,id,name,party,abbreviation,color
7,7_Jozef Šváč,Jozef Šváč,NP,NP,#aaaaaa
7,7_Jozef Mihalčin,Jozef Mihalčin,ĽS Naše Slovensko,ĽS Naše Slovensko,#008000
7,7_Miroslav Škvarek,Miroslav Škvarek,SNS,SNS,#0076bc
7,7_Eduard Markovič,Eduard Markovič,NEKA,NEKA,#444444
7,7_Milan Majerský,Milan Majerský,"KDH, NOVA, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS",KDH,#00568f
7,7_František Bednár,František Bednár,NAJ,NAJ,#aaaaaa
7,7_Milan Šteiner,Milan Šteiner,SZS,SZS,#aaaaaa
7,7_Pavol Gašper,Pavol Gašper,NEKA,NEKA,#444444
7,7_Ján Garaj,Ján Garaj,NEKA,NEKA,#444444
7,7_Andrej Gmitter,Andrej Gmitter,NEKA,NEKA,#444444
7,7_František Oľha,František Oľha,ŠANCA,ŠANCA,#aaaaaa
7,7_Peter Chudík,Peter Chudík,SMER-SD,SMER-SD,#c4122f
8,8_Ján Struk,Ján Struk,STRANA MODERNÉHO SLOVENSKA (SMS),STRANA MODERNÉHO SLOVENSKA (SMS),#aaaaaa
8,8_Lukáš Sisák,Lukáš Sisák,KSS,KSS,#aaaaaa
8,8_Karol Pataky,Karol Pataky,"MOST - HÍD, SKOK - ELD",MOST - HÍD,#f58025
8,8_Róbert Bačinský,Róbert Bačinský,NEKA,NEKA,#444444
8,8_Jozef Bobík,Jozef Bobík,NEKA,NEKA,#444444
8,8_Oliver Petrík,Oliver Petrík,JEDNOTA-ĽSS,JEDNOTA-ĽSS,#aaaaaa
8,8_Rudolf Botka,Rudolf Botka,NP,NP,#aaaaaa
8,8_Jozef Červeňák,Jozef Červeňák,RIS,RIS,#aaaaaa
8,8_Štefan Surmánek,Štefan Surmánek,ĽS Naše Slovensko,ĽS Naše Slovensko,#008000
8,8_Rastislav Trnka,Rastislav Trnka,"KDH, NOVA, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS, ŠANCA",KDH,#00568f
8,8_Richard Raši,Richard Raši,"STAROSTOVIA A NEZÁVISLÍ KANDIDÁTI, SMER-SD, SMK-MKP, SZS",STAROSTOVIA A NEZÁVISLÍ KANDIDÁTI,#c4122f
8,8_Adam Šepetka,Adam Šepetka,NAJ,NAJ,#aaaaaa
8,8_Jaroslav Džunko,Jaroslav Džunko,NEKA,NEKA,#444444
8,8_Jarmila Tkáčová,Jarmila Tkáčová,SNS,SNS,#0076bc
8,8_Vladislav Stanko,Vladislav Stanko,NEKA,NEKA,#444444
4,4_Iván Farkas,Iván Farkas,SMK-MKP,SMK-MKP,#397c49
4,4_Milan Belica,Milan Belica,"MOST - HÍD, SNS, SMER-SD",SMER-SD,#c4122f
4,4_László Hajdu,László Hajdu,MKDA-MKDSZ,MKDA-MKDSZ,#aaaaaa
4,4_Renáta Kolenčíková,Renáta Kolenčíková,NEKA,NEKA,#444444
4,4_Milan Uhrík,Milan Uhrík,ĽS Naše Slovensko,ĽS Naše Slovensko,#008000
4,4_Ján Greššo,Ján Greššo,"KDH, NOVA, OKS, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), Demokrati Slovenska, SaS, ŠANCA",KDH,#00568f
4,4_Ján Marko,Ján Marko,NP,NP,#aaaaaa
4,4_Peter Oremus,Peter Oremus,NEKA,NEKA,#444444
2,2_Jaroslav Cehlárik,Jaroslav Cehlárik,NEKA,NEKA,#444444
2,2_Jozef Viskupič,Jozef Viskupič,"KDH, OKS, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS, Zmena zdola, DÚ",OĽANO,#b2c800
2,2_Tibor Mikuš,Tibor Mikuš,NEKA,NEKA,#444444
2,2_Konrád Rigó,Konrád Rigó,MOST - HÍD,MOST - HÍD,#f58025
2,2_József Berényi,József Berényi,SMK-MKP,SMK-MKP,#397c49
2,2_Márius Novák,Márius Novák,NP,NP,#aaaaaa
1,1_Lukáš Parízek,Lukáš Parízek,SNS,SNS,#0076bc
1,1_Andrej Trnovec,Andrej Trnovec,Slovenská ľudová strana (SĽS),Slovenská ľudová strana (SĽS),#9400D3
1,1_Rastislav Blaško,Rastislav Blaško,NEKA,NEKA,#444444
1,1_Daniel Krajcer,Daniel Krajcer,"MOST - HÍD, SZ, SKOK - ELD",MOST - HÍD,#f58025
1,1_Ľubomír Kolárik,Ľubomír Kolárik,SZSZO,SZSZO,#aaaaaa
1,1_Pavol Frešo,Pavol Frešo,NEKA,NEKA,#444444
1,1_Natália Hanulíková,Natália Hanulíková,SZS,SZS,#aaaaaa
1,1_Jozef Uhler,Jozef Uhler,NEKA,NEKA,#444444
1,1_Ľubomír Huďo,Ľubomír Huďo,NEKA,NEKA,#444444
1,1_Milan Ftáčnik,Milan Ftáčnik,NEKA,NEKA,#444444
1,1_Juraj Droba,Juraj Droba,"NOVA, OKS, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS, SMK-MKP, Zmena zdola, DÚ",SaS,#a6ce39
1,1_Martin Jakubec,Martin Jakubec,NEKA,NEKA,#444444
1,1_Jozef Danko,Jozef Danko,NEKA,NEKA,#444444
1,1_Rudolf Kusý,Rudolf Kusý,NEKA,NEKA,#444444
1,1_Milan Lopašovský,Milan Lopašovský,STRANA MODERNÉHO SLOVENSKA (SMS),STRANA MODERNÉHO SLOVENSKA (SMS),#aaaaaa
1,1_Jalal Suleiman,Jalal Suleiman,KSS,KSS,#aaaaaa
1,1_Ján Mrva,Ján Mrva,NEKA,NEKA,#444444
1,1_Marián Leinerovič,Marián Leinerovič,NP,NP,#aaaaaa
3,3_Jaroslav Baška,Jaroslav Baška,"MOST - HÍD, SNS, SMER-SD, SZ",SMER-SD,#c4122f
3,3_Igor Valko,Igor Valko,NP,NP,#aaaaaa
3,3_Štefan Škultéty,Štefan Škultéty,NEKA,NEKA,#444444
3,3_Nora Pániková,Nora Pániková,SZS,SZS,#aaaaaa
3,3_Renáta Kaščáková,Renáta Kaščáková,"KDH, NOVA, OKS, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS, Zmena zdola, DÚ",SaS,#a6ce39
3,3_Petra Hajšelová,Petra Hajšelová,SME RODINA - Boris Kollár,SME RODINA - Boris Kollár,#d90604
3,3_Ferdinand Vavrík,Ferdinand Vavrík,NEKA,NEKA,#444444
5,5_Kristián Hoffmann,Kristián Hoffmann,SZS,SZS,#aaaaaa
5,5_Stanislav Pirošík,Stanislav Pirošík,"KSS, VZDOR",KSS,#aaaaaa
5,5_Marián Murín,Marián Murín,NEKA,NEKA,#444444
5,5_Peter Cibulka,Peter Cibulka,NEKA,NEKA,#444444
5,5_Anton Martvoň,Anton Martvoň,NEKA,NEKA,#444444
5,5_Ján Mikolaj,Ján Mikolaj,SNS,SNS,#0076bc
5,5_Erika Jurinová,Erika Jurinová,"KDH, NOVA, OKS, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS",OĽANO,#b2c800
5,5_Peter Sagan,Peter Sagan,ĽS Naše Slovensko,ĽS Naše Slovensko,#008000
5,5_Juraj Blanár,Juraj Blanár,SMER-SD,SMER-SD,#c4122f
6,6_Ivan Saktor,Ivan Saktor,NEKA,NEKA,#444444
6,6_Zdenek Očovan,Zdenek Očovan,NAJ,NAJ,#aaaaaa
6,6_Stanislav Mičev,Stanislav Mičev,NEKA,NEKA,#444444
6,6_Miroslav Gálik,Miroslav Gálik,NaS - ns,NaS - ns,#aaaaaa
6,6_Michal Kantor,Michal Kantor,SZS,SZS,#aaaaaa
6,6_Jozef Sásik,Jozef Sásik,Slovenská ľudová strana (SĽS),Slovenská ľudová strana (SĽS),#9400D3
6,6_Igor Kašper,Igor Kašper,NEKA,NEKA,#444444
6,6_Ján Lunter,Ján Lunter,NEKA,NEKA,#ff002b
6,6_Pavel Greksa,Pavel Greksa,NEKA,NEKA,#444444
6,6_Martin Klus,Martin Klus,"KDH, NOVA, OKS, OBYČAJNÍ ĽUDIA a nezávislé osobnosti (OĽANO), SaS",KDH,#00568f
6,6_Marian Kotleba,Marian Kotleba,ĽS Naše Slovensko,ĽS Naše Slovensko,#008000
6,6_Martin Juhaniak,Martin Juhaniak,NEKA,NEKA,#444444
6,6_Alena Pivovarčiová,Alena Pivovarčiová,NP,NP,#aaaaaa
6,6_Vojtech Kökény,Vojtech Kökény,SRK,SRK,#aaaaaa
6,6_Milan Urbáni,Milan Urbáni,STRANA MODERNÉHO SLOVENSKA (SMS),STRANA MODERNÉHO SLOVENSKA (SMS),#aaaaaa
6,6_Viliam Baňák,Viliam Baňák,JEDNOTA-ĽSS,JEDNOTA-ĽSS,#aaaaaa
6,6_Jozef Šimko,Jozef Šimko,NEKA,NEKA,#444444

ba2016.csv

id,name,latitude,longitude,previous_size
528595,Bratislava - Staré Mesto,48.148598,17.1077475,24851
529311,Bratislava - Podunajské Biskupice,48.1251057,17.2107902,10435
529320,Bratislava - Ružinov,48.1575967,17.1627978,40442
529338,Bratislava - Vrakuňa,48.1421639,17.2129005,8927
529346,Bratislava - Nové Mesto,48.1671515,17.1368492,21692
529354,Bratislava - Rača,48.2120284,17.1546065,10883
529362,Bratislava - Vajnory,48.2030662,17.2052549,2549
529371,Bratislava - Devínska Nová Ves,48.2112712,16.9734671,8379
529389,Bratislava - Dúbravka,48.1888276,17.0290285,17381
529397,Bratislava - Karlova Ves,48.1591643,17.0518443,19097
529401,Bratislava - Devín,48.1737498,16.9844742,755
529419,Bratislava - Lamač,48.1938879,17.0474565,3993
529427,Bratislava - Záhorská Bystrica,48.241632,17.0387275,2140
529435,Bratislava - Čunovo,48.0307363,17.1994899,712
529443,Bratislava - Jarovce,48.0650577,17.1140119,1162
529460,Bratislava - Petržalka,48.1108879,17.1115635,55292
529494,Bratislava - Rusovce,48.0560336,17.1450367,1883

ba_reordered.csv

1,Bratislavský kraj,111,Volebný obvod č. 11,529435,Bratislava - Čunovo,466,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,0,43,0,97,1,60,10,53,87,0,0,63,1,1,49,0
1,Bratislavský kraj,108,Volebný obvod č. 8,529401,Bratislava - Devín,527,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,1,2,47,0,59,5,4,27,85,153,3,2,43,0,1,89,0
1,Bratislavský kraj,108,Volebný obvod č. 8,529371,Bratislava - Devínska Nová Ves,4519,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,11,18,448,7,516,59,95,197,785,1028,30,14,631,2,10,647,4
1,Bratislavský kraj,109,Volebný obvod č. 9,529389,Bratislava - Dúbravka,10313,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,38,15,14,862,4,838,88,164,450,1900,1931,43,20,2683,8,35,1213,7
1,Bratislavský kraj,111,Volebný obvod č. 11,529443,Bratislava - Jarovce,901,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,0,1,49,1,57,1,462,11,84,127,0,0,48,0,2,51,4
1,Bratislavský kraj,107,Volebný obvod č. 7,529397,Bratislava - Karlova Ves,10450,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,34,23,19,979,9,963,162,216,392,1850,2631,43,26,1340,8,41,1703,11
1,Bratislavský kraj,110,Volebný obvod č. 10,529419,Bratislava - Lamač,2654,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,11,7,3,198,2,249,21,38,82,493,466,12,4,675,3,6,384,0
1,Bratislavský kraj,105,Volebný obvod č. 5,529346,Bratislava - Nové Mesto,13132,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48,20,12,654,5,811,33,179,269,1483,2275,61,11,6039,9,15,1205,3
1,Bratislavský kraj,111,Volebný obvod č. 11,529460,Bratislava - Petržalka,28570,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,69,65,58,2049,26,2515,217,724,1169,5778,6133,127,71,5361,26,105,4041,36
1,Bratislavský kraj,104,Volebný obvod č. 4,529311,Bratislava - Podunajské Biskupice,5274,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,15,20,565,0,696,32,89,168,1063,1088,39,28,818,6,19,594,7
1,Bratislavský kraj,106,Volebný obvod č. 6,529354,Bratislava - Rača,6888,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,80,23,11,490,8,477,37,83,238,1267,1088,53,11,1054,3,18,1946,1
1,Bratislavský kraj,111,Volebný obvod č. 11,529494,Bratislava - Rusovce,1109,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,1,106,1,90,6,150,24,153,276,4,4,181,1,1,105,4
1,Bratislavský kraj,102,Volebný obvod č. 2,529320,Bratislava - Ružinov,22012,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,76,56,48,1674,15,1867,142,397,651,3937,5288,118,57,4421,18,60,3183,4
1,Bratislavský kraj,101,Volebný obvod č. 1,528595,Bratislava - Staré Mesto,13682,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,36,30,18,1068,9,1593,59,248,398,2563,3449,33,28,2311,21,45,1761,12
1,Bratislavský kraj,106,Volebný obvod č. 6,529362,Bratislava - Vajnory,1944,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,16,1,4,63,0,81,8,18,50,178,225,11,3,196,0,6,1083,1
1,Bratislavský kraj,103,Volebný obvod č. 3,529338,Bratislava - Vrakuňa,4541,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,12,16,448,10,453,41,78,178,799,1104,27,12,702,3,8,623,0
1,Bratislavský kraj,110,Volebný obvod č. 10,529427,Bratislava - Záhorská Bystrica,1974,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,2,6,218,2,162,20,35,52,308,431,12,5,488,1,6,220,1

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 if (typeof module === 'object' && module.exports) {
    // CommonJS
    module.exports = function(d3) {
      d3.tip = factory(d3)
      return d3.tip
    }
  } 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   = getNodeEl(),
          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() {
      var nodel = getNodeEl()
      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 getNodeEl().attr(n)
      } else {
        var args =  Array.prototype.slice.call(arguments)
        d3.selection.prototype.attr.apply(getNodeEl(), 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 getNodeEl().style(n)
      } else {
        var args =  Array.prototype.slice.call(arguments)
        d3.selection.prototype.style.apply(getNodeEl(), 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
    }

    // Public: destroys the tooltip and removes it from the DOM
    //
    // Returns a tip
    tip.destroy = function() {
      if(node) {
        getNodeEl().remove();
        node = null;
      }
      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 getNodeEl() {
      if(node === null) {
        node = initNode();
        // re-add node to DOM
        document.body.appendChild(node);
      };
      return d3.select(node);
    }

    // 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;

      while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {
          targetel = targetel.parentNode;
      }

      var 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
  };

}));

geocodes.py

# get geocodes from older files, geocode the rest
import csv
import requests
import time

older = {}
with open("municipalities2016.csv") as fin:
    dr = csv.DictReader(fin)
    for row in dr:
        older[row['id']] = row

newer = {}
url = "http://nominatim.openstreetmap.org/search"
headers = {
    "user-agent": "Python Requests Slovak Elections"
}
with open("source_reordered.csv") as fin:
    dr = csv.DictReader(fin)
    for row in dr:
        newer[row['muni_id']] = row
        try:
            newer[row['muni_id']]['latitude'] = older[row['muni_id']]['latitude']
            newer[row['muni_id']]['longitude'] = older[row['muni_id']]['longitude']
        except Exception:
            print(row['muni_id'])
            time.sleep(1)
            params = {
                "country": "Slovakia",
                "format": "json",
                "accept-language": "en",
                "city": row['municipality'],
                "county": row['region']
            }
            r = requests.get(url, params=params, headers=headers)
            try:
                print(row['muni_id'], r.json()[0]['lat'], r.json()[0]['lon'])
                newer[row['muni_id']]['latitude'] = r.json()[0]['lat']
                newer[row['muni_id']]['longitude'] = r.json()[0]['lon']
            except Exception:
                print(row['muni_id'])

# manually
# newer['556891']['latitude'] = 50.7353
# newer['556891']['longitude'] = 15.1002
# newer['999997']['latitude'] = 0
# newer['999997']['longitude'] = 0

header = ["region_id", "region", "subregion_id", "subregion", "id", "municipality", "latitude", "longitude", "population", "Jozef Šváč", "Jozef Mihalčin", "Miroslav Škvarek", "Eduard Markovič", "Milan Majerský", "František Bednár", "Milan Šteiner", "Pavol Gašper", "Ján Garaj", "Andrej Gmitter", "František Oľha", "Peter Chudík", "Ján Struk", "Lukáš Sisák", "Karol Pataky", "Róbert Bačinský", "Jozef Bobík", "Oliver Petrík", "Rudolf Botka", "Jozef Červeňák", "Štefan Surmánek", "Rastislav Trnka", "Richard Raši", "Adam Šepetka", "Jaroslav Džunko", "Jarmila Tkáčová", "Vladislav Stanko", "Iván Farkas", "Milan Belica", "László Hajdu", "Renáta Kolenčíková", "Milan Uhrík", "Ján Greššo", "Ján Marko", "Peter Oremus", "Jaroslav Cehlárik", "Jozef Viskupič", "Tibor Mikuš", "Konrád Rigó", "József Berényi", "Márius Novák", "Lukáš Parízek", "Andrej Trnovec", "Rastislav Blaško", "Daniel Krajcer", "Ľubomír Kolárik", "Pavol Frešo", "Natália Hanulíková", "Jozef Uhler", "Ľubomír Huďo", "Milan Ftáčnik", "Juraj Droba", "Martin Jakubec", "Jozef Danko", "Rudolf Kusý", "Milan Lopašovský", "Jalal Suleiman", "Ján Mrva", "Marián Leinerovič", "Jaroslav Baška", "Igor Valko", "Štefan Škultéty", "Nora Pániková", "Renáta Kaščáková", "Petra Hajšelová", "Ferdinand Vavrík", "Kristián Hoffmann", "Stanislav Pirošík", "Marián Murín", "Peter Cibulka", "Anton Martvoň", "Ján Mikolaj", "Erika Jurinová", "Peter Sagan", "Juraj Blanár", "Ivan Saktor", "Zdenek Očovan", "Stanislav Mičev", "Miroslav Gálik", "Michal Kantor", "Jozef Sásik", "Igor Kašper", "Ján Lunter", "Pavel Greksa", "Martin Klus", "Marian Kotleba", "Martin Juhaniak", "Alena Pivovarčiová", "Vojtech Kökény", "Milan Urbáni", "Viliam Baňák", "Jozef Šimko"]
with open("municipalities.csv", "w") as fout:
    dw = csv.DictWriter(fout, header)
    dw.writeheader()
    for k in newer:
        newer[k]['id'] = newer[k]['muni_id']
        del(newer[k]['muni_id'])
        dw.writerow(newer[k])


# manually join Pardubice and Ústí in municipalities !!!

ke2016.csv

id,name,latitude,longitude,previous_size,polling_stations
598119,Košice - Kavečany,48.7754061,21.2058674,544,1
598127,Košice - Ťahanovce,48.757492,21.2551353,758,2
598151,Košice - Sever,48.7366124,21.2461837,8799,18
598186,Košice - Staré Mesto,48.7223734,21.2570032,9282,19
598194,Košice - Lorinčík,48.6879213,21.1952577,259,1
598208,Košice - Pereš,48.6888583,21.211786,782,2
598216,Košice - Myslava,48.7091002,21.2045831,989,2
598224,Košice - Západ,48.7143063,21.2345873,16933,31
598682,Košice - Dargovských hrdinov,48.7442344,21.2771429,10046,24
599018,Košice - Košická Nová Ves,48.7334389,21.2977631,1036,2
599093,Košice - Barca,48.663056,21.241111,1614,3
599786,Košice - Šebastovce,48.6549691,21.2703882,300,1
599794,Košice - Krásna,48.6726061,21.3188165,1555,3
599816,Košice - Nad jazerom,48.6893403,21.2844607,9371,23
599824,Košice - Juh,48.7092508,21.2570841,9837,20
599841,Košice - Šaca,48.6370535,21.1713844,2019,3
599859,Košice - Poľov,48.6648877,21.1935779,473,1
599875,Košice - Sídlisko Ťahanovce,48.7539765,21.2676675,8433,18
599883,Košice - Sídlisko KVP,48.7164151,21.2148908,9885,18
599891,Košice - Džungľa,48.7372364,21.268109,200,1
599913,Košice - Vyšné Opátske,48.7164117,21.2799977,938,2
599972,Košice - Luník IX,48.6972038,21.2224101,222,2

ke_reordered.csv

8,Košický kraj,804,Volebný obvod č. 4,599093,Košice - Barca,1031,,,,,,,,,,,,,1,2,21,38,6,9,0,1,23,523,367,7,10,20,3
8,Košický kraj,803,Volebný obvod č. 3,598682,Košice - Dargovských hrdinov,5304,,,,,,,,,,,,,7,35,189,204,8,25,4,9,291,2750,1504,21,31,148,78
8,Košický kraj,801,Volebný obvod č. 1,599891,Košice - Džungľa,147,,,,,,,,,,,,,1,0,5,2,0,3,0,4,6,68,52,1,2,3,0
8,Košický kraj,804,Volebný obvod č. 4,599824,Košice - Juh,5864,,,,,,,,,,,,,7,43,218,290,10,19,6,5,203,3250,1582,19,68,119,25
8,Košický kraj,801,Volebný obvod č. 1,598119,Košice - Kavečany,286,,,,,,,,,,,,,2,2,4,9,1,2,1,0,12,196,46,1,0,6,4
8,Košický kraj,803,Volebný obvod č. 3,599018,Košice - Košická Nová Ves,573,,,,,,,,,,,,,1,3,9,16,0,1,0,1,21,314,182,4,3,15,3
8,Košický kraj,804,Volebný obvod č. 4,599794,Košice - Krásna,1028,,,,,,,,,,,,,2,6,23,36,3,5,1,1,39,625,240,3,7,34,3
8,Košický kraj,802,Volebný obvod č. 2,598194,Košice - Lorinčík,228,,,,,,,,,,,,,0,0,5,7,0,0,1,0,8,163,33,2,1,6,2
8,Košický kraj,802,Volebný obvod č. 2,599972,Košice - Luník IX,179,,,,,,,,,,,,,0,1,1,0,0,1,0,8,0,2,163,1,1,1,0
8,Košický kraj,802,Volebný obvod č. 2,598216,Košice - Myslava,650,,,,,,,,,,,,,1,4,6,18,4,0,0,1,33,375,184,1,2,17,4
8,Košický kraj,804,Volebný obvod č. 4,599816,Košice - Nad jazerom,5411,,,,,,,,,,,,,1,48,158,240,10,21,4,11,218,2588,1831,27,38,186,30
8,Košický kraj,802,Volebný obvod č. 2,598208,Košice - Pereš,659,,,,,,,,,,,,,3,5,15,23,2,4,1,2,25,374,190,4,3,6,2
8,Košický kraj,802,Volebný obvod č. 2,599859,Košice - Poľov,394,,,,,,,,,,,,,0,4,11,18,0,2,0,0,17,229,101,0,5,5,2
8,Košický kraj,802,Volebný obvod č. 2,599841,Košice - Šaca,813,,,,,,,,,,,,,1,6,29,34,2,10,1,5,47,360,282,7,7,17,5
8,Košický kraj,804,Volebný obvod č. 4,599786,Košice - Šebastovce,223,,,,,,,,,,,,,0,1,6,11,1,0,1,0,10,111,75,0,0,6,1
8,Košický kraj,801,Volebný obvod č. 1,598151,Košice - Sever,5599,,,,,,,,,,,,,11,27,205,153,10,15,2,11,198,3578,1164,42,27,137,19
8,Košický kraj,802,Volebný obvod č. 2,599883,Košice - Sídlisko KVP,5569,,,,,,,,,,,,,3,43,180,173,12,14,3,6,238,3503,1152,29,49,143,21
8,Košický kraj,801,Volebný obvod č. 1,599875,Košice - Sídlisko Ťahanovce,4640,,,,,,,,,,,,,6,30,149,210,11,21,0,7,189,2951,868,22,35,123,18
8,Košický kraj,801,Volebný obvod č. 1,598186,Košice - Staré Mesto,6264,,,,,,,,,,,,,19,21,233,169,11,22,6,10,195,3908,1461,23,38,127,21
8,Košický kraj,801,Volebný obvod č. 1,598127,Košice - Ťahanovce,521,,,,,,,,,,,,,0,2,16,28,2,3,0,1,12,318,111,1,5,16,6
8,Košický kraj,804,Volebný obvod č. 4,599913,Košice - Vyšné Opátske,687,,,,,,,,,,,,,0,1,18,33,1,1,1,3,34,399,183,0,5,8,0
8,Košický kraj,802,Volebný obvod č. 2,598224,Košice - Západ,9256,,,,,,,,,,,,,9,63,282,341,20,28,10,23,336,4949,2798,40,61,244,52

prepare_data.py

# transpose data
import csv

datamuni = {}
candidates = {}
candidates_arr = []
votes = {}
with open("source.csv") as fin:
    dr = csv.DictReader(fin)
    for row in dr:
        datamuni[row['muni_id']] = row
        try:
            votes[row['muni_id']]
        except Exception:
            votes[row['muni_id']] = {}
        votes[row['muni_id']][row['candidate']] = row['votes'].replace(',', '')
        try:
            candidates[row['region_id']]
        except Exception:
            candidates[row['region_id']] = {}
        try:
            candidates[row['region_id']][row['candidate']]
        except Exception:
            candidates[row['region_id']][row['candidate']] = row['party']
            candidates_arr.append(row['candidate'])


with open("source_reordered.csv", "w") as fout:
    header = ["region_id", "region", "subregion_id", "subregion", "muni_id", "municipality", "latitude", "longitude", "population"]
    for muni_id in candidates:
        for candidate in candidates[muni_id]:
            header.append(candidate)
    dw = csv.DictWriter(fout, header)
    dw.writeheader()
    for k in sorted(datamuni):
        row = datamuni[k]
        item = {
            "region_id": row['region_id'],
            "region": row['region'],
            "subregion_id": row['subregion_id'],
            "subregion": row["subregion"],
            "muni_id": row["muni_id"],
            "municipality": row["municipality"],
            "latitude": '',
            "longitude": ''
        }
        population = 0
        for candidate in candidates_arr:
            try:
                item[candidate] = votes[row['muni_id']][candidate]
                population += int(votes[row['muni_id']][candidate])
            except Exception:
                item[candidate] = ''
        item['population'] = population
        dw.writerow(item)
        # break


def party2color(p):
    if p == 'NOVA':
        return '#683C61'
    if p == 'NEKA':
        return '#444444'
    if p == 'MOST - HÍD':
        return '#f58025'
    if p == 'Slovenská ľudová strana (SĽS)':
        return '#9400D3'
    if p == 'KDH':
        return '#00568f'
    if p == 'SME RODINA - Boris Kollár':
        return '#d90604'
    if p == 'SMK-MKP':
        return '#397c49'
    if p == 'ĽS Naše Slovensko':
        return '#008000'
    if p == 'SMER-SD':
        return '#c4122f'
    if p == 'SNS':
        return '#0076bc'
    if p == 'STAROSTOVIA A NEZÁVISLÍ KANDIDÁTI':
        return '#c4122f'
    return '#aaaaaa'


with open("actors.csv", "w") as fout:
    header = ['region_id', 'id', 'name', 'party', 'abbreviation', 'color']
    dw = csv.DictWriter(fout, header)
    dw.writeheader()
    for region_id in candidates:
        for candidate in candidates[region_id]:
            item = {
                'region_id': region_id,
                'id': region_id + '_' + candidate,
                'name': candidate,
                'party': candidates[region_id][candidate],
                'abbreviation': candidates[region_id][candidate].split(',')[0],
                'color': party2color(candidates[region_id][candidate].split(',')[0])
            }
            dw.writerow(item)

prepare_data_bb.py

# transpose data
import csv

datamuni = {}
candidates = {}
candidates_arr = []
votes = {}
with open("source_bb.csv") as fin:
    dr = csv.DictReader(fin)
    for row in dr:
        datamuni[row['name']] = row
        try:
            votes[row['name']]
        except Exception:
            votes[row['name']] = {}
        votes[row['name']][row['candidate']] = row['votes'].replace(',', '')
        try:
            candidates[row['region_id']]
        except Exception:
            candidates[row['region_id']] = {}
        try:
            candidates[row['region_id']][row['candidate']]
        except Exception:
            candidates[row['region_id']][row['candidate']] = row['party']
            candidates_arr.append(row['candidate'])


with open("source_reordered_bb.csv", "w") as fout:
    header = ["region_id", "region", "subregion_id", "subregion", "muni_id", "municipality", "id", "name", "latitude", "longitude", "population"]
    for muni_id in candidates:
        for candidate in candidates[muni_id]:
            header.append(candidate)
    dw = csv.DictWriter(fout, header)
    dw.writeheader()
    for k in sorted(datamuni):
        row = datamuni[k]
        item = {
            "region_id": row['region_id'],
            "region": row['region'],
            "subregion_id": row['subregion_id'],
            "subregion": row["subregion"],
            "muni_id": row["muni_id"],
            "municipality": row["municipality"],
            "id": row['name'],
            "name": row['name'],
            "latitude": '',
            "longitude": ''
        }
        population = 0
        for candidate in candidates_arr:
            try:
                item[candidate] = votes[row['name']][candidate]
                population += int(votes[row['name']][candidate])
            except Exception:
                item[candidate] = ''
        item['population'] = population
        dw.writerow(item)
        # break


# def party2color(p):
#     if p == 'NOVA':
#         return '#683C61'
#     if p == 'NEKA':
#         return '#444444'
#     if p == 'MOST - HÍD':
#         return '#f58025'
#     if p == 'Slovenská ľudová strana (SĽS)':
#         return '#9400D3'
#     if p == 'KDH':
#         return '#00568f'
#     if p == 'SME RODINA - Boris Kollár':
#         return '#d90604'
#     if p == 'SMK-MKP':
#         return '#397c49'
#     if p == 'ĽS Naše Slovensko':
#         return '#008000'
#     if p == 'SMER-SD':
#         return '#c4122f'
#     if p == 'SNS':
#         return '#0076bc'
#     if p == 'STAROSTOVIA A NEZÁVISLÍ KANDIDÁTI':
#         return '#c4122f'
#     return '#aaaaaa'
#
#
# with open("actors.csv", "w") as fout:
#     header = ['region_id', 'id', 'name', 'party', 'abbreviation', 'color']
#     dw = csv.DictWriter(fout, header)
#     dw.writeheader()
#     for region_id in candidates:
#         for candidate in candidates[region_id]:
#             item = {
#                 'region_id': region_id,
#                 'id': region_id + '_' + candidate,
#                 'name': candidate,
#                 'party': candidates[region_id][candidate],
#                 'abbreviation': candidates[region_id][candidate].split(',')[0],
#                 'color': party2color(candidates[region_id][candidate].split(',')[0])
#             }
#             dw.writerow(item)