block by michalskop 8309367

CZ Presidential Elections: 4+ and 2- votes (stacked chart)

Full Screen

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<title>Alternative voting system for Czech presidential elections 2013</title>
<style>

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
  fill: steelblue;
}

.x.axis path {
  display: none;
}

.opaque {
  fill-opacity: 0.25;
}

.negative {
  fill-color:red;
}

.zeman {
  fill: Red;
}

.dienstbier {
  fill: DarkOrange;
}
.sobotka {
  fill: Blue;
}
.fischer {
  fill: CornflowerBlue;
}
.kscm {
  fill: DarkRed;
}
.schwarzenberg {
  fill: DarkViolet;
}
.roithova {
  fill: Gold;
}
.fischerova {
  fill: Green;
}
.franz {
  fill: Black;
}
.bobosikova {
  fill: Yellow;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<!--<script src="//code.jquery.com/jquery-1.8.2.min.js"></script>-->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <a class="navbar-brand" href="#">Alternative voting system for Czech presidential elections 2013</a>
        </div>
      </div>
    </div>



<div style="position:fixed;top:50px;z-index:1000;">
      <div class="alert alert-info" >The alternative electoral system with 4 positive and 2 negative votes<br/>
      The data is from <a href="//volebnikalkulacka.cz/volba-prezidenta-cr-2013/kalkulacka-vyzkum.php">research</a> conducted among users of voting advice application <a href="//volebnikalkulacka.cz">Volební kalkulačka</a>. It is weighted so the 1st round of the real elections and the 2nd round of the real elections match the 1st and last round of the potentional <a href="//en.wikipedia.org/wiki/Instant-runoff_voting">instant-runoff voting (alternative vote) electoral system</a>.</div>
</div>
<div style="padding-bottom:130px"></div>

<script>

var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 700 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var color = d3.scale.ordinal()
    .range(["#080", "#0b0", "#0f0","#4f4"]);
var color2 = d3.scale.ordinal()
    .range(["darkred", "red"]);
var color3 = d3.scale.ordinal()
    .range(["green", "black"]);

function reorder(o) {
  sorted = []
  for (k in o) {
    sorted.push({
      key: k,
      val: o[k]
    })
  }
  sorted = sorted.sort(
    function(a, b){
      if(a.key < b.key) return -1;
      if(a.key > b.key) return 1;
      return 0;
    });
  out = {};
  for (k in sorted) {
    out[sorted[k].key] = sorted[k].val;
  }
  return out;
}


d3.json("d42chart.json", function(error, data) {
  
  var names = [];
  nnames = [];
  positive = [];
  negative = [];
  totals = [];
  sort_ar = [];
  ndata = [];
  var tot = {};
  for (var key in data) {
    sort_ar.push({
      key:data[key].name,
      tot:data[key].total.t1,
      nname:data[key].nname,
      positive:data[key]['positive'],
      negative:data[key]['negative'],
      totals:data[key]['total'],
      data:data[key]
    });
  }
  sort_ar = sort_ar.sort(function(x,y){return y.tot - x.tot});
  for (var i=0;i<sort_ar.length;i++) {
    names.push(sort_ar[i].key);
    nnames.push(sort_ar[i].nname);
    tot[sort_ar[i].key] = Math.round(100*sort_ar[i].tot) + "%";
    positive.push(reorder(sort_ar[i].positive));
    negative.push(reorder(sort_ar[i].negative));
    totals.push(sort_ar[i].totals);
    ndata.push(sort_ar[i].data);
  }
  
  data = ndata;
  
  var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .25) //the 2nd number is the width of gap
    .domain(nnames);
    
  var y = d3.scale.linear()
    .rangeRound([height, 0])
    .domain([-0.6,0.7]);
    
  var x2 = d3.scale.linear()
    .rangeRound([0, width])
    .domain([0,100]);
    
  var x3 = d3.scale.ordinal()
    .rangeRoundBands([0, width])
    .domain(names);
    
  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");
    
  var xAxis2 = d3.svg.axis()
    .scale(x2)
    .orient("bottom")
    .ticks(0);
    
  var xAxis3 = d3.svg.axis()
    .scale(x3)
    .orient("bottom")
    .tickFormat(function (d) {
      return tot[d]
    });

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    //.tickFormat(d3.format(".2s")); 
    .ticks(10, "%");

  var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
  
  svg.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(0," + y(0) + ")")
      .call(xAxis2); 
      
  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0,10)")
      .call(xAxis3);    
      
  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end");
      //.text("Hlasy");

  color.domain(d3.keys(positive[0]));
  color2.domain(d3.keys(negative[0]));
  color3.domain(d3.keys(totals[0]));

  positive.forEach(function(d) {
    var y0 = 0;
    d.ages = color.domain().map(function(name) { return {
      name: name, 
      y0: y0, 
      y1: y0 += +d[name]
    }; });
    d.total = d.ages[d.ages.length - 1].y1;
  });
  
  Object.keys(data)
      .sort()
      .forEach(function(v, i) {
          console.log(v, data[v]);
       });
  
  negative.forEach(function(d) {
    var y0 = 0;
    d.ages = color2.domain().map(function(name) { return {
      name: name, 
      y0: y0,
      y1: y0 += +d[name]
    }; });
    d.total = d.ages[d.ages.length - 1].y1;
  });
  
  totals.forEach(function(d) {
    var y0 = 0;
    d.ages = color3.domain().map(function(name) { return {
      name: name, 
      y0: y0,
      y1: y0 += +d[name]
    }; });
    d.total = d.ages[d.ages.length - 1].y1;
  });
  
  breakpoint=1;
  
  //positive.sort(function(a, b) { return b.total - a.total; });
  
  for (var key in positive) {
    data[key].positive.total = positive[key].total
    data[key].positive.ages = positive[key].ages
    data[key].negative.total = negative[key].total
    data[key].negative.ages = negative[key].ages
    data[key].total.total = totals[key].total
    data[key].total.ages = totals[key].ages
  }
  
  
  
  x.domain(data.map(function(d) { return d.name; }));
  y.domain([-0.6, 0.7]);
  
  var state = svg.selectAll(".name")
      .data(data)
    .enter().append("g")
      .attr("class", "g")
      .attr("transform", function(d) { return "translate(" + x(d.name) + ",0)"; });
      
   state.selectAll(".rect1")
        .data(function(d) {return d.positive.ages; })
      .enter().append("rect")
        .attr("x", function (d) {return -x.rangeBand()/5;})
        .attr("class", function(d) {return "bar opaque";})
        .attr("width", x.rangeBand())
        .attr("y", function(d) { 
          return y(d.y1); 
        })
        .attr("height", function(d) { return y(d.y0) - y(d.y1); })
        .style("fill", function(d) { return color(d.name); });
        
   state.selectAll(".rect2")
        .data(function(d) {
          return d.negative.ages; 
        })
      .enter().append("rect")
        .attr("x", function (d) {return -x.rangeBand()/5;})
        .attr("class", function(d) {return "bar opaque";})
        .attr("width", x.rangeBand())
        .attr("y", function(d) { 
          return y(-d.y0); 
        })
        .attr("height", function(d) { return y(d.y0) - y(d.y1) + 1; }) //to compansate for gap that occured sometimes
        .style("fill", function(d) { return color2(d.name); });
        
   state.selectAll(".rect3")
        .data(function(d) {
          for (k in d.total.ages) {
            d.total.ages[k].nam = d.name;
          }
          return d.total.ages; 
        })
      .enter().append("rect")
        .attr("class", function(d) {
          return d.name;
        })
        .attr("width", x.rangeBand())
        .attr("class", function(d) {
          return d.nam;
        })
        .attr("y", function(d) { 
          if (d.y1 > 0)
            return y(d.y1); 
          else
            return y(d.y0)
        })
        .attr("height", function(d) { return Math.abs(y(d.y0) - y(d.y1)); })
        //.style("fill", function(d) { return color3(d.name); });
  
});

</script>
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-8592359-13', 'ocks.org');
  ga('send', 'pageview');

</script>

calc4.py

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

#
#

import pickle
import csv
import json

with open("responsesw", 'rb') as f:
  responses = pickle.load(f)

names = {
  'zeman': "Zeman",
  'schwarzenberg': "Schwarzenberg",
  'fischer': "Fischer",
  'dienstbier': 'Dientsbier',
  'roithova': 'Roithová',
  'sobotka': 'Sobotka',
  'fischerova': 'Fischerová',
  'franz': 'Franz',
  'bobosikova': 'Bobošíková'
}
  
out = {}
total = 0
for item in responses:
  total = total + float(item['weight'])
  for keyo in item['order']:
    val = item['order'][keyo]
    if ((val <= 4) or (val >= 8)):
      try:
        out[keyo]
      except:
        out[keyo] = {}
      try:
        out[keyo][val]
      except:
        out[keyo][val] = float(item['weight'])
      else:
        out[keyo][val] = out[keyo][val] + float(item['weight'])

for item in responses:
  if (item['info']['input-negative_vote'] != ''):
      try:
        out[item['info']['input-negative_vote']]['X']
      except:
        out[item['info']['input-negative_vote']]['X'] = float(item['weight'])
      else:
        out[item['info']['input-negative_vote']]['X'] = out[item['info']['input-negative_vote']]['X'] + float(item['weight'])
print out

writer = csv.writer(open('d42.csv', 'wb'))
for name in sorted(out):
  vals = []
  vals.append(name)
  for key in sorted(out[name]):
    vals.append(out[name][key])
  #print vals
  writer.writerow(vals)

# for chart:

with open('d11chart.json', 'w') as outfile:      

  cout = []
  for name in sorted(out):
    item = {
      'nname': names[name],
      'name': name,
      'positive':{'p1': out[name][1]/total},
      'negative':{'n1': out[name][9]/total},
      'total':{'t1': (out[name][1]-out[name][9])/total}
    }
    cout.append(item)
  json.dump(cout, outfile)

d11chart.json

[{"positive": {"p1": 0.022894774961726785}, "total": {"t1": -0.3339168118016037}, "name": "bobosikova", "nname": "Bobo\u0161\u00edkov\u00e1", "negative": {"n1": 0.3568115867633305}}, {"positive": {"p1": 0.1593809782584065}, "total": {"t1": 0.11900558407553352}, "name": "dienstbier", "nname": "Dientsbier", "negative": {"n1": 0.04037539418287298}}, {"positive": {"p1": 0.16289010893977462}, "total": {"t1": 0.0806058812357787}, "name": "fischer", "nname": "Fischer", "negative": {"n1": 0.08228422770399593}}, {"positive": {"p1": 0.03262757655222617}, "total": {"t1": -0.0257161521727664}, "name": "fischerova", "nname": "Fischerov\u00e1", "negative": {"n1": 0.05834372872499257}}, {"positive": {"p1": 0.06802294919422315}, "total": {"t1": -0.09293702476426496}, "name": "franz", "nname": "Franz", "negative": {"n1": 0.16095997395848813}}, {"positive": {"p1": 0.04865790188454359}, "total": {"t1": -0.0045327548005767914}, "name": "roithova", "nname": "Roithov\u00e1", "negative": {"n1": 0.05319065668512038}}, {"positive": {"p1": 0.2339284930109916}, "total": {"t1": 0.1397106149278545}, "name": "schwarzenberg", "nname": "Schwarzenberg", "negative": {"n1": 0.09421787808313711}}, {"positive": {"p1": 0.028356104736141603}, "total": {"t1": -0.03792312160896208}, "name": "sobotka", "nname": "Sobotka", "negative": {"n1": 0.06627922634510368}}, {"positive": {"p1": 0.24324111246204322}, "total": {"t1": 0.15570378490900305}, "name": "zeman", "nname": "Zeman", "negative": {"n1": 0.08753732755304015}}]

d21chart.json

[{"positive": {"p2": 0.03312099660679414, "p1": 0.022894774961726785}, "total": {"t1": -0.3007958151948096}, "name": "bobosikova", "nname": "Bobo\u0161\u00edkov\u00e1", "negative": {"n1": 0.3568115867633305}}, {"positive": {"p2": 0.1377458959503866, "p1": 0.1593809782584065}, "total": {"t1": 0.25675148002592013}, "name": "dienstbier", "nname": "Dientsbier", "negative": {"n1": 0.04037539418287298}}, {"positive": {"p2": 0.13352514081411135, "p1": 0.16289010893977462}, "total": {"t1": 0.21413102204989007}, "name": "fischer", "nname": "Fischer", "negative": {"n1": 0.08228422770399593}}, {"positive": {"p2": 0.07689906596739708, "p1": 0.03262757655222617}, "total": {"t1": 0.05118291379463069}, "name": "fischerova", "nname": "Fischerov\u00e1", "negative": {"n1": 0.05834372872499257}}, {"positive": {"p2": 0.1121636583834586, "p1": 0.06802294919422315}, "total": {"t1": 0.019226633619193613}, "name": "franz", "nname": "Franz", "negative": {"n1": 0.16095997395848813}}, {"positive": {"p2": 0.08970444072117809, "p1": 0.04865790188454359}, "total": {"t1": 0.08517168592060127}, "name": "roithova", "nname": "Roithov\u00e1", "negative": {"n1": 0.05319065668512038}}, {"positive": {"p2": 0.16356162603378968, "p1": 0.2339284930109916}, "total": {"t1": 0.30327224096164423}, "name": "schwarzenberg", "nname": "Schwarzenberg", "negative": {"n1": 0.09421787808313711}}, {"positive": {"p2": 0.08308938486745902, "p1": 0.028356104736141603}, "total": {"t1": 0.04516626325849694}, "name": "sobotka", "nname": "Sobotka", "negative": {"n1": 0.06627922634510368}}, {"positive": {"p2": 0.17018979065549553, "p1": 0.24324111246204322}, "total": {"t1": 0.32589357556449855}, "name": "zeman", "nname": "Zeman", "negative": {"n1": 0.08753732755304015}}]

d42chart.json

[{"positive": {"p2": 0.03312099660679414, "p3": 0.05772401054374347, "p1": 0.022894774961726785, "p4": 0.06195749446040702}, "total": {"t1": -0.35589424876050546}, "name": "bobosikova", "nname": "Bobo\u0161\u00edkov\u00e1", "negative": {"n1": 0.3568115867633305, "n2": 0.1747799385698464}}, {"positive": {"p2": 0.1377458959503866, "p3": 0.13076860715569652, "p1": 0.1593809782584065, "p4": 0.12349933342380673}, "total": {"t1": 0.41752643867003225}, "name": "dienstbier", "nname": "Dientsbier", "negative": {"n1": 0.04037539418287298, "n2": 0.09349298193539109}}, {"positive": {"p2": 0.13352514081411135, "p3": 0.1315120938448177, "p1": 0.16289010893977462, "p4": 0.11292145233323476}, "total": {"t1": 0.3715116682794703}, "name": "fischer", "nname": "Fischer", "negative": {"n1": 0.08228422770399593, "n2": 0.08705289994847223}}, {"positive": {"p2": 0.07689906596739708, "p3": 0.11172389091436516, "p1": 0.03262757655222617, "p4": 0.13289148180383634}, "total": {"t1": 0.16671770372626946}, "name": "fischerova", "nname": "Fischerov\u00e1", "negative": {"n1": 0.05834372872499257, "n2": 0.1290805827865627}}, {"positive": {"p2": 0.1121636583834586, "p3": 0.11311816247632296, "p1": 0.06802294919422315, "p4": 0.11385655256264096}, "total": {"t1": 0.14097018880028345}, "name": "franz", "nname": "Franz", "negative": {"n1": 0.16095997395848813, "n2": 0.10523115985787408}}, {"positive": {"p2": 0.08970444072117809, "p3": 0.10313440339431522, "p1": 0.04865790188454359, "p4": 0.13057483044040982}, "total": {"t1": 0.2074371162268366}, "name": "roithova", "nname": "Roithov\u00e1", "negative": {"n1": 0.05319065668512038, "n2": 0.11144380352848972}}, {"positive": {"p2": 0.16356162603378968, "p3": 0.12545041902948537, "p1": 0.2339284930109916, "p4": 0.09731445827492145}, "total": {"t1": 0.44829542962317215}, "name": "schwarzenberg", "nname": "Schwarzenberg", "negative": {"n1": 0.09421787808313711, "n2": 0.07774168864287902}}, {"positive": {"p2": 0.08308938486745902, "p3": 0.11346671101737715, "p1": 0.028356104736141603, "p4": 0.13693838860140511}, "total": {"t1": 0.17244585499750445}, "name": "sobotka", "nname": "Sobotka", "negative": {"n1": 0.06627922634510368, "n2": 0.12312550787977478}}, {"positive": {"p2": 0.17018979065549553, "p3": 0.11310170162394342, "p1": 0.24324111246204322, "p4": 0.09004600809940413}, "total": {"t1": 0.43098984843706906}, "name": "zeman", "nname": "Zeman", "negative": {"n1": 0.08753732755304015, "n2": 0.09805143685077707}}]