Skip to content

Instantly share code, notes, and snippets.

@michalskop
Last active January 2, 2016 13:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michalskop/8309367 to your computer and use it in GitHub Desktop.
Save michalskop/8309367 to your computer and use it in GitHub Desktop.
CZ Presidential Elections: 4+ and 2- votes (stacked chart)
# -*- 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)
[{"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}}]
[{"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}}]
[{"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}}]
<!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="http://d3js.org/d3.v3.min.js"></script>
<!--<script src="http://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="http://volebnikalkulacka.cz/volba-prezidenta-cr-2013/kalkulacka-vyzkum.php">research</a> conducted among users of voting advice application <a href="http://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="http://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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment