Last active
January 2, 2016 13:19
-
-
Save michalskop/8309367 to your computer and use it in GitHub Desktop.
CZ Presidential Elections: 4+ and 2- votes (stacked chart)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"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}}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"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}}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"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}}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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