Estimates of numbers of people changing parties between Czech elections 2013-2017 based on ecological inference model.
Example (i: 1-8)
See overview chart
/json
): downloader.py
list_2017.csv
): scraper.py
data_filtered.csv
and data_filtered_random.csv
): join_data.py
matn_filtered.csv
, matp_filtered.csv
): ei_psp.py
calling ei.r
matn_filtered_adjusted.csv
matn_filtered_adjusted_reordered.csv
matn_chart.csv
list_2013_filtered.csv
and list_2017_filtered.csv
bubbles_psp.html
presnost.ods
?i=1
parameter, i: 1-8) index.html
and index_cs.html
generate.py
CC-BY Michal Škop
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<script src="https://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<style>
.mcontainer {
padding-left: 10px;
padding-right: 10px;
}
.header {
padding-left: 10px;
padding-right: 10px;
}
.h3 {
position: relative;
bottom: 20px;
}
.note {
padding: 10px;
}
.logo {
width: 64px;
height: 64px;
border-radius: 50%;
margin: 10px;
border: 1px solid #eee;
}
#chart {
border: 1px solid #eee;
}
.hithit {
font-size: 1.5em;
width: 100vw;
/*background-color: #fed201;*/
padding: 10px;
height: 100vh;
color: white;
}
</style>
<div class="header">
<h1 id="h1" class="text-center"><span id="h1pic"></span> <span id="h1name"></span></h1>
<h3 class="text-center h3">Gains and Losts of Voters in Czech Elections 2013 → 2017</h3>
<div class="row">
<div class="col-xs-4 col-xs-offset-1 text-center">
<strong>Came to <span class="shortname"></span></strong>
</div>
<div class="col-xs-4 col-xs-offset-2 text-center">
<strong>Left from <span class="shortname"></span></strong>
</div>
</div>
</div>
<div id="chart"></div>
<div class="note xbg-info">
<i class="fa fa-info-circle"></i> Estimated by Ecological Inference. Only streams with more than 25,000 people shown.<br />
CC-BY Michal Škop, KohoVolit.eu, VolebníKalkulačka.cz
</div>
<script>
var formatNumber = d3.format(",.0f");
d3.csv("list_2017_filtered.csv", function (er,d2017) {
d3.csv("list_2013_filtered.csv", function(err,d2013) {
d3.csv("matn_chart.csv", function(errr,source) {
var d13to17 = {};
var party2color = {};
d2013.forEach(function(d) {
d13to17[d['party']] = {}
party2color[d['party']] = d['color']
});
d2017.forEach(function(d) {
party2color[d['party']] = d['color']
});
var d17to13 = {};
source.forEach(function(d) {
d17to13[d['name']] = {}
for (k in d) {
if (k != 'name') {
d17to13[d['name']][k] = parseInt(d[k])
d13to17[k][d['name']] = parseInt(d[k])
}
}
})
var names = source['name'];
var i = QueryString.i;
if (i === undefined) {
i = 1;
}
var party = d2017[i]['party']
var prev_party = d2017[i]['previous']
var data = source[i];
d3.select("#h1name")
.html(d2017[i]['party_name']);
d3.select("#h1pic")
.html("<img class='logo' src='./" + d2017[i]['party'] + ".png' />");
d3.selectAll(".shortname")
.html(d2017[i]['party'])
var sumout = 0
for (k in d13to17[prev_party]) {
if (k != prev_party) {
sumout += d13to17[prev_party][k]
}
}
if (d2017[i]['votes'] > 1000000) {
var h = 700;
} else {
var h = 400;
}
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 930 - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var svg = d3.select("#chart").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 + ")");
maxsum = Math.max(sumout, d2017[i]['votes'])
var x = d3.scale.linear()
.domain([0, 100])
.range([0, width])
var y = d3.scale.linear()
.domain([0, maxsum * 1.1])
.range([0, height]);
// basic rectangle
var offset = (maxsum - d2017[i]['votes']) / 2;
svg.append("rect")
.attr("width", x(20))
.attr("height", y(d2017[i]['votes']))
.attr("x", x(40))
.attr("y", y(offset))
.attr("fill", d2017[i]['color']);
svg.append("text")
.attr("x", x(50))
.attr("y", function() {
return y(d2017[i]['votes']/2 + offset);
})
.attr("dy", 0)
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", "40px")
.text(party)
svg.append("text")
.attr("x", x(50))
.attr("y", function() {
return y(d2017[i]['votes']/2 * 1.3 + offset);
})
.attr("dy", 0)
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", "20px")
.text(formatNumber(d2017[i]['votes']))
// prepare out and in rectangles
var outs = []
for (k in d13to17[prev_party]) {
if ((d13to17[prev_party][k] > 25000) && (party != k)) {
outs.push({
'name': k,
'value': d13to17[prev_party][k],
'color': party2color[k]
})
}
}
outs.sort(function(a, b) {
return b.value - a.value;
});
var ins = []
for (k in d13to17) {
if ((d13to17[k][party] > 25000) && (prev_party != k)) {
ins.push({
'name': k,
'value': d13to17[k][party],
'color': party2color[k]
})
}
}
ins.sort(function(a, b) {
return b.value - a.value;
});
s = 0
outs.forEach(function (out,k) {
s += y(out['value'])
s += 15
})
s = s - 15
var offset = (y(maxsum) - s) / 2;
outs.forEach(function (out, k) {
outs[k]['y0'] = offset;
outs[k]['y1'] = offset + y(out['value'])
outs[k]['half'] = (outs[k]['y1'] + outs[k]['y0']) / 2
offset = outs[k]['y1'] + 15;
outs[k]['arrow'] = [
{"x": x(76.98), "y": outs[k]['y0']}, {"x": x(79), "y": outs[k]['half']}, {"x": x(76.98), "y": outs[k]['y1']}, {"x": x(76.98), "y": outs[k]['y0']}
]
});
s = 0
ins.forEach(function (out,k) {
s += y(out['value'])
s += 15
})
s = s - 15
var offset = (y(maxsum) - s) / 2;
ins.forEach(function (inn, k) {
ins[k]['y0'] = offset;
ins[k]['y1'] = offset + y(inn['value'])
ins[k]['half'] = (ins[k]['y1'] + ins[k]['y0']) / 2
offset = ins[k]['y1'] + 15;
ins[k]['arrow'] = [
{"x": x(34.95), "y": ins[k]['y0']}, {"x": x(37), "y": ins[k]['half']}, {"x": x(34.95), "y": ins[k]['y1']},
{"x": x(34.95), "y": ins[k]['y0']}
]
});
var arrowFunction = d3.svg.area()
.x(function(d) { return d.x; })
.y1(function(d) { return d.y; });
// arrows out
var rectouts = svg.selectAll(".rectout")
.data(outs)
.enter()
.append("rect")
.attr("width", x(14))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(63))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", d2017[i]['color']);
var arrowouts = svg.selectAll(".arrowout")
.data(outs)
.enter()
.append("path")
.attr("d", function(d) {
return arrowFunction(d['arrow']);
})
.attr("fill", d2017[i]['color']);
svg.selectAll(".textout")
.data(outs)
.enter()
.append("text")
.attr("x", x(70))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4.5), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4.5), 18)
})
.text(function(d) {
return formatNumber(my_round(d['value']))
})
//arrows in
svg.selectAll(".rectin")
.data(ins)
.enter()
.append("rect")
.attr("width", x(14))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(21))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".arrowin")
.data(ins)
.enter()
.append("path")
.attr("d", function(d) {
return arrowFunction(d['arrow']);
})
.attr("fill", function(d) {
return d['color']
});
svg.selectAll(".textin")
.data(ins)
.enter()
.append("text")
.attr("x", x(28))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return formatNumber(my_round(d['value']))
})
// outs
svg.selectAll(".rectend")
.data(outs)
.enter()
.append("rect")
.attr("width", x(16))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(84))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".textout")
.data(outs)
.enter()
.append("text")
.attr("x", x(92))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return d['name']
})
// ins
svg.selectAll(".rectstart")
.data(ins)
.enter()
.append("rect")
.attr("width", x(16))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(0))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".textstart")
.data(ins)
.enter()
.append("text")
.attr("x", x(8))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return d['name']
})
var pause = 0;
})
})
})
function my_round(n) {
if (n < 100000) {
return Math.round(n/10000)*10000;
}
return Math.round(n/20000)*20000;
}
var QueryString = function () {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = decodeURIComponent(pair[1]);
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(decodeURIComponent(pair[1]));
}
}
return query_string;
}();
</script>
</body>
</html>
<svg width="930" height="700">
<g transform="translate(10,10)">
<rect width="182" height="618.1818181818181" x="364" y="0" fill="#261060"></rect>
<text x="455" y="309.09090909090907" dy="0" text-anchor="middle" fill="white" font-size="40px">ANO</text>
<text x="455" y="401.8181818181818" dy="0" text-anchor="middle" fill="white" font-size="20px">1,500,113</text>
<rect width="127.4" height="59.28988501048073" x="573.3" y="188.1298752766685" fill="#261060"></rect>
<rect width="127.4" height="29.209363197669404" x="573.3" y="262.41976028714924" fill="#261060"></rect>
<rect width="127.4" height="26.03585681393821" x="573.3" y="306.62912348481865" fill="#261060"></rect>
<rect width="127.4" height="21.323605742912832" x="573.3" y="347.66498029875686" fill="#261060"></rect>
<rect width="127.4" height="20.603272129257164" x="573.3" y="383.9885860416697" fill="#261060"></rect>
<rect width="127.4" height="10.460084734222733" x="573.3" y="419.59185817092686" fill="#261060"></rect>
<path d="M700.518,188.1298752766685L718.9,217.7748177819089L700.518,247.41976028714924L700.518,188.1298752766685L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#261060"></path>
<path d="M700.518,262.41976028714924L718.9,277.02444188598395L700.518,291.62912348481865L700.518,262.41976028714924L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#261060"></path>
<path d="M700.518,306.62912348481865L718.9,319.6470518917878L700.518,332.66498029875686L700.518,306.62912348481865L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#261060"></path>
<path d="M700.518,347.66498029875686L718.9,358.3267831702133L700.518,368.9885860416697L700.518,347.66498029875686L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#261060"></path>
<path d="M700.518,383.9885860416697L718.9,394.2902221062983L700.518,404.59185817092686L700.518,383.9885860416697L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#261060"></path>
<path d="M700.518,419.59185817092686L718.9,424.8219005380382L700.518,430.0519429051496L700.518,419.59185817092686L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#261060"></path>
<text x="637" y="224.44148444857555" text-anchor="middle" fill="white" font-size="18">140,000</text>
<text x="637" y="283.69110855265063" text-anchor="middle" fill="white" font-size="18">70,000</text>
<text x="637" y="326.31371855845447" text-anchor="middle" fill="white" font-size="18">60,000</text>
<text x="637" y="364.99344983687996" text-anchor="middle" fill="white" font-size="18">50,000</text>
<text x="637" y="400.956888772965" text-anchor="middle" fill="white" font-size="18">50,000</text>
<text x="637" y="431.4885672047049" text-anchor="middle" fill="white" font-size="18">30,000</text>
<rect width="127.4" height="150.15947586493937" x="191.1" y="61.77709551941027" fill="#f1953e"></rect>
<rect width="127.4" height="84.93301989431944" x="191.1" y="226.93657138434963" fill="#888"></rect>
<rect width="127.4" height="82.25402171218252" x="191.1" y="326.8695912786691" fill="#8c0000"></rect>
<rect width="127.4" height="36.106928429573486" x="191.1" y="424.1236129908516" fill="#f51941"></rect>
<rect width="127.4" height="21.8873450927303" x="191.1" y="475.2305414204251" fill="#888"></rect>
<rect width="127.4" height="15.993219419894558" x="191.1" y="512.1178865131553" fill="#004494"></rect>
<rect width="127.4" height="13.29361672935795" x="191.1" y="543.1111059330499" fill="#e6ac21"></rect>
<path d="M318.045,61.77709551941027L336.7,136.85683345187994L318.045,211.93657138434963L318.045,61.77709551941027L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#f1953e"></path>
<path d="M318.045,226.93657138434963L336.7,269.4030813315094L318.045,311.8695912786691L318.045,226.93657138434963L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#888"></path>
<path d="M318.045,326.8695912786691L336.7,367.99660213476034L318.045,409.1236129908516L318.045,326.8695912786691L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#8c0000"></path>
<path d="M318.045,424.1236129908516L336.7,442.17707720563834L318.045,460.2305414204251L318.045,424.1236129908516L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#f51941"></path>
<path d="M318.045,475.2305414204251L336.7,486.17421396679026L318.045,497.1178865131554L318.045,475.2305414204251L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#888"></path>
<path d="M318.045,512.1178865131553L336.7,520.1144962231026L318.045,528.1111059330499L318.045,512.1178865131553L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#004494"></path>
<path d="M318.045,543.1111059330499L336.7,549.7579142977288L318.045,556.4047226624078L318.045,543.1111059330499L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#e6ac21"></path>
<text x="254.8" y="149.37012310729156" text-anchor="middle" fill="white" font-size="37.53986896623484">360,000</text>
<text x="254.8" y="276.48083298936933" text-anchor="middle" fill="white" font-size="21.233254973579868">200,000</text>
<text x="254.8" y="374.8511039441089" text-anchor="middle" fill="white" font-size="20.563505428045634">200,000</text>
<text x="254.8" y="448.843743872305" text-anchor="middle" fill="white" font-size="20">90,000</text>
<text x="254.8" y="492.84088063345695" text-anchor="middle" fill="white" font-size="20">50,000</text>
<text x="254.8" y="526.7811628897692" text-anchor="middle" fill="white" font-size="20">40,000</text>
<text x="254.8" y="556.4245809643954" text-anchor="middle" fill="white" font-size="20">30,000</text>
<rect width="145.6" height="59.28988501048073" x="764.4" y="188.1298752766685" fill="#888"></rect>
<rect width="145.6" height="29.209363197669404" x="764.4" y="262.41976028714924" fill="#888"></rect>
<rect width="145.6" height="26.03585681393821" x="764.4" y="306.62912348481865" fill="#000000"></rect>
<rect width="145.6" height="21.323605742912832" x="764.4" y="347.66498029875686" fill="#0066a5"></rect>
<rect width="145.6" height="20.603272129257164" x="764.4" y="383.9885860416697" fill="#004494"></rect>
<rect width="145.6" height="10.460084734222733" x="764.4" y="419.59185817092686" fill="#5d8c00"></rect>
<text x="837.2" y="224.44148444857555" text-anchor="middle" fill="white" font-size="20">nevoliči</text>
<text x="837.2" y="283.69110855265063" text-anchor="middle" fill="white" font-size="20">neparlamentní</text>
<text x="837.2" y="326.31371855845447" text-anchor="middle" fill="white" font-size="20">Piráti</text>
<text x="837.2" y="364.99344983687996" text-anchor="middle" fill="white" font-size="20">SPD</text>
<text x="837.2" y="400.956888772965" text-anchor="middle" fill="white" font-size="20">ODS</text>
<text x="837.2" y="431.4885672047049" text-anchor="middle" fill="white" font-size="20">STAN</text>
<rect width="145.6" height="150.15947586493937" x="0" y="61.77709551941027" fill="#f1953e"></rect>
<rect width="145.6" height="84.93301989431944" x="0" y="226.93657138434963" fill="#888"></rect>
<rect width="145.6" height="82.25402171218252" x="0" y="326.8695912786691" fill="#8c0000"></rect>
<rect width="145.6" height="36.106928429573486" x="0" y="424.1236129908516" fill="#f51941"></rect>
<rect width="145.6" height="21.8873450927303" x="0" y="475.2305414204251" fill="#888"></rect>
<rect width="145.6" height="15.993219419894558" x="0" y="512.1178865131553" fill="#004494"></rect>
<rect width="145.6" height="13.29361672935795" x="0" y="543.1111059330499" fill="#e6ac21"></rect>
<text x="72.8" y="149.37012310729156" text-anchor="middle" fill="white" font-size="37.53986896623484">ČSSD</text>
<text x="72.8" y="276.48083298936933" text-anchor="middle" fill="white" font-size="21.233254973579868">nevoliči</text>
<text x="72.8" y="374.8511039441089" text-anchor="middle" fill="white" font-size="20.563505428045634">KSČM</text>
<text x="72.8" y="448.843743872305" text-anchor="middle" fill="white" font-size="20">Úsvit</text>
<text x="72.8" y="492.84088063345695" text-anchor="middle" fill="white" font-size="20">neparlamentní</text>
<text x="72.8" y="526.7811628897692" text-anchor="middle" fill="white" font-size="20">ODS</text>
<text x="72.8" y="556.4245809643954" text-anchor="middle" fill="white" font-size="20">KDU-ČSL</text>
</g>
</svg>
<!DOCTYPE html>
<meta charset="utf-8">
<title>Volby 2017 a 2013</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<style>
.node rect {
cursor: move;
fill-opacity: .9;
shape-rendering: crispEdges;
}
.node text {
pointer-events: none;
text-shadow: 0 1px 0 #fff;
}
.link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
.link:hover {
stroke-opacity: .5;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
pointer-events: none;
max-width: 400px;
}
/* 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);
position: absolute;
pointer-events: none;
}
/* Northward tooltips */
.d3-tip:after {
content: "\25BC";
margin: -1px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
.stronger {
font-weight: bold;
color: yellow;
}
</style>
<body>
<div class="container">
<h1 id="h1"><span id="h1name"></span> <small>2013 → 2017</small></h1>
<h3>Volby 2017 vs. volby 2013</h3>
<p>Odhad počtu voličů, kteří volili stranu X ve volbách 2017 a zároveň stranu Y ve volbách 2013. Plocha jednotlivých bodů odpovídá počtu takových voličů (najetím myší na body zjistíte počty; lidé, kteří nevolili ani v jedněch z voleb, nejsou zobrazeni).
<p id="chart">
<p>Odhad pomocí statistické metody ekologické inference z výsledků voleb v jednotlivých volebních místnostech s výjimkou některých míst, kde se měnily volební okrsky (např. částečně v Ostravě, Brně, Plzni). Hrubý odhad chyby vypočtených čísel je +-15%.
<p>CC-BY-SA Michal Škop
</div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="./d3.tips.js"></script>
<script>
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatNumber = d3.format(",.0f"), // zero decimal places
format = function(d) { return formatNumber(Math.round(d/50)*50); },
color = d3.scale.category20();
// append the svg canvas to the page
var svg = d3.select("#chart").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 + ")");
// var nonvoters = {
// "name": "Nevoliči",
// "party": "Nevoliči",
// "color": "#444444",
// }
// var others = {
// "name": "Ostatní",
// "party": "Ostatní",
// "color": "#999999",
// }
// var plus = {
// "name": "Přibylí",
// "party": "Přibylí",
// "color": "#444444",
// }
// var minus = {
// "name": "Odešlí",
// "party": "Odešlí",
// "color": "#444444",
// }
d3.select("#h1name")
.html('Voličské přesuny');
var name2data = {};
// load the data
d3.csv("list_2017_filtered.csv", function (er,da) {
d3.csv("list_2013_filtered.csv", function(err,daa) {
parties = [];
daa.forEach(function(d) {
parties.push(d.party + " 13");
name2data[d.party + " 13"] = d;
});
// parties.push(others.name + " 13");
// name2data[others.name + " 13"] = others;
// parties.push(minus.name + " 13");
// name2data[minus.name + " 13"] = minus;
// parties.push(nonvoters.name + " 13");
// name2data[nonvoters.name + " 13"] = nonvoters;
cands = []
da.forEach(function (d) {
cands.push(d.party + " 17");
name2data[d.party + " 17"] = d;
});
// cands.push(others.name + " 17");
// name2data[others.name + " 17"] = others;
// cands.push(plus.name + " 17");
// name2data[plus.name + " 17"] = plus;
// cands.push(nonvoters.name + " 17");
// name2data[nonvoters.name + " 17"] = nonvoters;
//set up scales
var x = d3.scale.linear()
.domain([-5,parties.length])
.range([0, width])
var y = d3.scale.linear()
.domain([-3,cands.length])
.range([0, height]);
var r = d3.scale.linear()
.domain([0,Math.sqrt(1500000)])
.range([0,50]);
d3.text("matn_filtered_adjusted_reordered.csv", function(text) {
var dat = d3.csv.parseRows(text).map(function(row) {
return row.map(function(value) {
return +value;
});
});
points = [];
i = 0;
len = dat.length;
dat.forEach(function (d) {
len2 = d.length;
d.forEach(function (dd,ii) {
if (((i + 1) < len) || ((ii + 1) < len2)) {
points.push({
'i': i,
'j': ii,
'value': dd,
'd1': name2data[cands[ii]],
'd2': name2data[parties[i]]
})
}
});
i++;
});
/* Initialize tooltip */
function my_round(n) {
if (n < 100000) {
return Math.round(n/10000)*10000;
}
return Math.round(n/20000)*20000;
}
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
return "<span>zhruba <span class='stronger'>" + my_round(d["value"]) + "</span> lidí volilo zároveň:<br><br><span class='stronger'>" + d.d1.party + "</span> v roce 2017<br><span class='stronger'>" + d.d2.party + "</span> v roce 2013<br>";
});
/* Invoke the tip in the context of your visualization */
svg.call(tip);
var circles = svg.selectAll(".circle")
.data(points)
.enter()
.append("circle")
.attr("cx",function(d) {
return x(d.i);
})
.attr("cy",function(d) {
return y(d.j);
})
.attr("r", function(d) {
return r(Math.sqrt(d.value));
})
.attr("title", function(d) {
return Math.round(d/50)*50;
})
.attr("fill", function(d) {
return d.d1.color;
})
// .attr("stroke",function(d) {
// return d.d1.color;
// })
// .attr("stroke-width", function (d) {
// return Math.sqrt(d.value/100);
// })
.attr("fill-opacity", function(d) {
return d.value/200000;
})
// .attr("stroke-opacity", function(d) {
// return d.value/2000;
// })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
;
var cands_names = svg.selectAll(".text")
.data(cands)
.enter()
.append("text")
.attr("x", function() {
return (x(-0.5));
})
.attr("y", function(d,i) {
return y(i)+6;
})
.attr("text-anchor", "end")
.attr("font-size",12)
.text(function(d) {
return d;
});
var parties_names = svg.selectAll(".text")
.data(parties)
.enter()
.append("text")
.attr("x", function(d,i) {
return (x(i));
})
.attr("y", function(d,i) {
return y(-0.5);
})
.attr("transform", function(d,i) {
return "rotate(-45,"+x(i)+","+y(-0.5)+")";
})
// .attr("text-anchor", "end")
.attr("font-size",12)
.text(function(d) {
return d;
})
});
});
});
</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>
</body>
</html>
<svg width="930" height="400">
<g transform="translate(10,10)">
<rect width="182" height="158.54860350066403" x="364" y="93.45297097694069" fill="#f1953e"></rect>
<text x="455" y="172.7272727272727" dy="0" text-anchor="middle" fill="white" font-size="40px">ČSSD</text>
<text x="455" y="196.50956325237232" dy="0" text-anchor="middle" fill="white" font-size="20px">368,347</text>
<rect width="127.4" height="156.84322903835096" x="573.3" y="-5.268486660833162" fill="#f1953e"></rect>
<rect width="127.4" height="112.21510309146976" x="573.3" y="166.5747423775178" fill="#f1953e"></rect>
<rect width="127.4" height="30.08595628276032" x="573.3" y="293.78984546898755" fill="#f1953e"></rect>
<rect width="127.4" height="11.847230363630672" x="573.3" y="338.8758017517479" fill="#f1953e"></rect>
<path d="M700.518,-5.268486660833162L718.9,73.15312785834232L700.518,151.5747423775178L700.518,-5.268486660833162L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#f1953e"></path>
<path d="M700.518,166.5747423775178L718.9,222.68229392325267L700.518,278.78984546898755L700.518,166.5747423775178L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#f1953e"></path>
<path d="M700.518,293.78984546898755L718.9,308.8328236103677L700.518,323.8758017517479L700.518,293.78984546898755L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#f1953e"></path>
<path d="M700.518,338.8758017517479L718.9,344.7994169335632L700.518,350.72303211537854L700.518,338.8758017517479L700.518,0L700.518,0L718.9,0L700.518,0Z" fill="#f1953e"></path>
<text x="637" y="84.77114482414609" text-anchor="middle" fill="white" font-size="34.85405089741132">360,000</text>
<text x="637" y="230.99452378188005" text-anchor="middle" fill="white" font-size="24.93668957588217">260,000</text>
<text x="637" y="315.4994902770344" text-anchor="middle" fill="white" font-size="18">70,000</text>
<text x="637" y="351.46608360022987" text-anchor="middle" fill="white" font-size="18">30,000</text>
<rect width="127.4" height="21.355919724296513" x="191.1" y="148.94787657907924" fill="#888"></rect>
<rect width="127.4" height="11.2028725720904" x="191.1" y="185.30379630337575" fill="#8c0000"></rect>
<path d="M318.045,148.94787657907924L336.7,159.62583644122748L318.045,170.30379630337575L318.045,148.94787657907924L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#888"></path>
<path d="M318.045,185.30379630337575L336.7,190.90523258942096L318.045,196.50666887546615L318.045,185.30379630337575L318.045,0L318.045,0L336.7,0L318.045,0Z" fill="#8c0000"></path>
<text x="254.8" y="166.29250310789413" text-anchor="middle" fill="white" font-size="20">50,000</text>
<text x="254.8" y="197.57189925608762" text-anchor="middle" fill="white" font-size="20">30,000</text>
<rect width="145.6" height="156.84322903835096" x="764.4" y="-5.268486660833162" fill="#261060"></rect>
<rect width="145.6" height="112.21510309146976" x="764.4" y="166.5747423775178" fill="#888"></rect>
<rect width="145.6" height="30.08595628276032" x="764.4" y="293.78984546898755" fill="#0066a5"></rect>
<rect width="145.6" height="11.847230363630672" x="764.4" y="338.8758017517479" fill="#8c0000"></rect>
<text x="837.2" y="86.22339694487157" text-anchor="middle" fill="white" font-size="39.21080725958774">ANO</text>
<text x="837.2" y="232.03355251420848" text-anchor="middle" fill="white" font-size="28.053775772867443">nevoliči</text>
<text x="837.2" y="315.4994902770344" text-anchor="middle" fill="white" font-size="20">SPD</text>
<text x="837.2" y="351.46608360022987" text-anchor="middle" fill="white" font-size="20">KSČM</text>
<rect width="145.6" height="21.355919724296513" x="0" y="148.94787657907924" fill="#888"></rect>
<rect width="145.6" height="11.2028725720904" x="0" y="185.30379630337575" fill="#8c0000"></rect>
<text x="72.8" y="166.29250310789413" text-anchor="middle" fill="white" font-size="20">nevoliči</text>
<text x="72.8" y="197.57189925608762" text-anchor="middle" fill="white" font-size="20">KSČM</text>
</g>
</svg>
// 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 = 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() {
var 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;
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
};
}));
# download all data
import json
import requests
import xmltodict
next = True
i = 1
j = 0
while (next):
print(i)
url = "https://www.volby.cz/pls/ps2017/vysledky_okrsky?davka=" + str(i)
try:
r = requests.get(url)
o = xmltodict.parse(r.text)
try:
o["VYSLEDKY_OKRSKY"]["CHYBA"]["@KOD_CHYBY"]
next = False
except Exception:
with open('json/' + str(i) + ".json", "w") as fin:
o = xmltodict.parse(r.text)
json.dump(o, fin)
# next = False
i += 1
j = 0
except Exception:
tryagain = True
j += 1
if j >= 10:
next = False
library("Zelig")
library("ZeligEI")
sink()
sink("/dev/null") # Suppress output after command or script run in R console
ncalc = 5 # number of repetitions of the calculcations (to get better means)
mats = list()
data = read.csv(par_input, header = TRUE, fileEncoding = "utf-8", encoding = "utf-8")
variables = names(data)
As = variables[which(grepl("A", variables) == TRUE)]
Bs = variables[which(grepl("B", variables) == TRUE)]
for (i in 1:ncalc) {
z.out = zeirxc$new()
eval(parse(text = paste0( "z.out$zelig(cbind(" , paste(Bs, collapse = ", "), ") ~ cbind(", paste(As, collapse = ", "), "), N='ZeligN', data = data)")))
mat = matrix(apply(as.matrix(z.out$getcoef()[[1]][[3]]),2,'mean'),ncol=length(Bs))
mats[[i]] = mat
}
# z.out$zelig(cbind(K2_2, K2_7, K2_9) ~ cbind(K1_1, K1_2, K1_3, K1_4, K1_5, K1_6, K1_7, K1_8, K1_9), N="ZeligN", data = data)
# eval(parse(text = paste0("z.out <- zelig(cbind(", paste(parties2016, collapse = ", "), ") ~ ", paste(parties2012, collapse = " + "), ", covar = NULL, model = 'ei.RxC', data = data)")))
matsd = matrix(apply(as.matrix(z.out$getcoef()[[1]][[3]]),2,'sd'),ncol=length(Bs))
mat_ave = apply(simplify2array(mats),1:2,mean)
matp = mat_ave / apply(mat_ave,1,'sum')
sink()
z.out = zeirxc$new()
#matp = mat / apply(mat,1,'sum')
# calculate ecological inference
import csv
import numpy
import rpy2.robjects as robjects
r = robjects.r
path = "/home/michal/dev/anal2017/scraper/"
robjects.globalenv["par_input"] = path + "data_filtered_random.csv"
try:
r.source("ei.r")
with open(path + "matp_filtered.csv", "w") as fout:
csvw = csv.writer(fout)
for row in numpy.array(robjects.globalenv['matp']):
csvw.writerow(list(row))
with open(path + "matn_filtered.csv", "w") as fout:
csvw = csv.writer(fout)
for row in numpy.array(robjects.globalenv['mat_ave']):
csvw.writerow(list(row))
except Exception:
print("skipping")
import os
for i in range(8, 9):
command = "chromium-browser --headless --disable-gpu --screenshot --hide-scrollbars --window-size=952,756 --save-to-png=q50.png http://localhost/michal/dev/anal2017/scraper/changes.html?i=" + str(i)
# command = "chromium-browser --headless --disable-gpu --screenshot --hide-scrollbars --window-size=952,1065 --save-to-png=q50.png http://localhost/michal/dev/anal2017/scraper/changes.html?i=" + str(i)
os.system(command)
command = "cp screenshot.png parties/party_c_" + str(i) + ".png"
os.system(command)
print(i)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<script src="https://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<style>
.mcontainer {
padding-left: 10px;
padding-right: 10px;
}
.header {
padding-left: 10px;
padding-right: 10px;
}
.h3 {
position: relative;
bottom: 20px;
}
.note {
padding: 10px;
}
.logo {
width: 64px;
height: 64px;
border-radius: 50%;
margin: 10px;
border: 1px solid #eee;
}
#chart {
border: 1px solid #eee;
}
.hithit {
font-size: 1.5em;
width: 100vw;
/*background-color: #fed201;*/
padding: 10px;
height: 100vh;
color: white;
}
</style>
<div class="header">
<h1 id="h1" class="text-center"><span id="h1pic"></span> <span id="h1name"></span></h1>
<h3 class="text-center h3">Zisky a ztráty voličů 2013 → 2017</h3>
<div class="row">
<div class="col-xs-4 col-xs-offset-1 text-center">
<strong>Přišli k <span class="shortname"></span></strong>
</div>
<div class="col-xs-4 col-xs-offset-2 text-center">
<strong>Odešli od <span class="shortname"></span></strong>
</div>
</div>
</div>
<div id="chart"></div>
<div class="note xbg-info">
<i class="fa fa-info-circle"></i> Odhady metodou ekologické inference. Zobrazeny přesuny voličů mezi stranami přesahující 25 000 lidí.<br />
CC-BY Michal Škop, KohoVolit.eu, VolebníKalkulačka.cz
</div>
<div class="hithit text-center bg-primary">
<h3></h3>
<h3>Podpořte Volební kalkulačku pro prezidentské volby!</h3>
<h3>www.Hithit.cz/VolebniKalkulacka</h3>
</div>
<script>
var formatNumber = d3.format(",.0f");
d3.csv("list_2017_filtered.csv", function (er,d2017) {
d3.csv("list_2013_filtered.csv", function(err,d2013) {
d3.csv("matn_chart.csv", function(errr,source) {
var d13to17 = {};
var party2color = {};
d2013.forEach(function(d) {
d13to17[d['party']] = {}
party2color[d['party']] = d['color']
});
d2017.forEach(function(d) {
party2color[d['party']] = d['color']
});
var d17to13 = {};
source.forEach(function(d) {
d17to13[d['name']] = {}
for (k in d) {
if (k != 'name') {
d17to13[d['name']][k] = parseInt(d[k])
d13to17[k][d['name']] = parseInt(d[k])
}
}
})
var names = source['name'];
var i = QueryString.i;
if (i === undefined) {
i = 1;
}
var party = d2017[i]['party']
var prev_party = d2017[i]['previous']
var data = source[i];
d3.select("#h1name")
.html(d2017[i]['party_name']);
d3.select("#h1pic")
.html("<img class='logo' src='./" + d2017[i]['party'] + ".png' />");
d3.selectAll(".shortname")
.html(d2017[i]['party'])
var sumout = 0
for (k in d13to17[prev_party]) {
if (k != prev_party) {
sumout += d13to17[prev_party][k]
}
}
if (d2017[i]['votes'] > 1000000) {
var h = 700;
} else {
var h = 400;
}
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 930 - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var svg = d3.select("#chart").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 + ")");
maxsum = Math.max(sumout, d2017[i]['votes'])
var x = d3.scale.linear()
.domain([0, 100])
.range([0, width])
var y = d3.scale.linear()
.domain([0, maxsum * 1.1])
.range([0, height]);
// basic rectangle
var offset = (maxsum - d2017[i]['votes']) / 2;
svg.append("rect")
.attr("width", x(20))
.attr("height", y(d2017[i]['votes']))
.attr("x", x(40))
.attr("y", y(offset))
.attr("fill", d2017[i]['color']);
svg.append("text")
.attr("x", x(50))
.attr("y", function() {
return y(d2017[i]['votes']/2 + offset);
})
.attr("dy", 0)
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", "40px")
.text(party)
svg.append("text")
.attr("x", x(50))
.attr("y", function() {
return y(d2017[i]['votes']/2 * 1.3 + offset);
})
.attr("dy", 0)
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", "20px")
.text(formatNumber(d2017[i]['votes']))
// prepare out and in rectangles
var outs = []
for (k in d13to17[prev_party]) {
if ((d13to17[prev_party][k] > 25000) && (party != k)) {
outs.push({
'name': k,
'value': d13to17[prev_party][k],
'color': party2color[k]
})
}
}
outs.sort(function(a, b) {
return b.value - a.value;
});
var ins = []
for (k in d13to17) {
if ((d13to17[k][party] > 25000) && (prev_party != k)) {
ins.push({
'name': k,
'value': d13to17[k][party],
'color': party2color[k]
})
}
}
ins.sort(function(a, b) {
return b.value - a.value;
});
s = 0
outs.forEach(function (out,k) {
s += y(out['value'])
s += 15
})
s = s - 15
var offset = (y(maxsum) - s) / 2;
outs.forEach(function (out, k) {
outs[k]['y0'] = offset;
outs[k]['y1'] = offset + y(out['value'])
outs[k]['half'] = (outs[k]['y1'] + outs[k]['y0']) / 2
offset = outs[k]['y1'] + 15;
outs[k]['arrow'] = [
{"x": x(76.98), "y": outs[k]['y0']}, {"x": x(79), "y": outs[k]['half']}, {"x": x(76.98), "y": outs[k]['y1']}, {"x": x(76.98), "y": outs[k]['y0']}
]
});
s = 0
ins.forEach(function (out,k) {
s += y(out['value'])
s += 15
})
s = s - 15
var offset = (y(maxsum) - s) / 2;
ins.forEach(function (inn, k) {
ins[k]['y0'] = offset;
ins[k]['y1'] = offset + y(inn['value'])
ins[k]['half'] = (ins[k]['y1'] + ins[k]['y0']) / 2
offset = ins[k]['y1'] + 15;
ins[k]['arrow'] = [
{"x": x(34.95), "y": ins[k]['y0']}, {"x": x(37), "y": ins[k]['half']}, {"x": x(34.95), "y": ins[k]['y1']},
{"x": x(34.95), "y": ins[k]['y0']}
]
});
var arrowFunction = d3.svg.area()
.x(function(d) { return d.x; })
.y1(function(d) { return d.y; });
// arrows out
var rectouts = svg.selectAll(".rectout")
.data(outs)
.enter()
.append("rect")
.attr("width", x(14))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(63))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", d2017[i]['color']);
var arrowouts = svg.selectAll(".arrowout")
.data(outs)
.enter()
.append("path")
.attr("d", function(d) {
return arrowFunction(d['arrow']);
})
.attr("fill", d2017[i]['color']);
svg.selectAll(".textout")
.data(outs)
.enter()
.append("text")
.attr("x", x(70))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4.5), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4.5), 18)
})
.text(function(d) {
return formatNumber(my_round(d['value']))
})
//arrows in
svg.selectAll(".rectin")
.data(ins)
.enter()
.append("rect")
.attr("width", x(14))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(21))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".arrowin")
.data(ins)
.enter()
.append("path")
.attr("d", function(d) {
return arrowFunction(d['arrow']);
})
.attr("fill", function(d) {
return d['color']
});
svg.selectAll(".textin")
.data(ins)
.enter()
.append("text")
.attr("x", x(28))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4.5), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4.5), 18)
})
.text(function(d) {
return formatNumber(my_round(d['value']))
})
// outs
svg.selectAll(".rectend")
.data(outs)
.enter()
.append("rect")
.attr("width", x(16))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(84))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".textout")
.data(outs)
.enter()
.append("text")
.attr("x", x(92))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return d['name']
})
// ins
svg.selectAll(".rectstart")
.data(ins)
.enter()
.append("rect")
.attr("width", x(16))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(0))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".textstart")
.data(ins)
.enter()
.append("text")
.attr("x", x(8))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return d['name']
})
var pause = 0;
})
})
})
function my_round(n) {
if (n < 100000) {
return Math.round(n/10000)*10000;
}
return Math.round(n/20000)*20000;
}
var QueryString = function () {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = decodeURIComponent(pair[1]);
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(decodeURIComponent(pair[1]));
}
}
return query_string;
}();
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<script src="https://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<style>
.mcontainer {
padding-left: 10px;
padding-right: 10px;
}
.header {
padding-left: 10px;
padding-right: 10px;
}
.h3 {
position: relative;
bottom: 20px;
}
.note {
padding: 10px;
}
.logo {
width: 64px;
height: 64px;
border-radius: 50%;
margin: 10px;
border: 1px solid #eee;
}
#chart {
border: 1px solid #eee;
}
.hithit {
font-size: 1.5em;
width: 100vw;
/*background-color: #fed201;*/
padding: 10px;
height: 100vh;
color: white;
}
</style>
<div class="header">
<h1 id="h1" class="text-center"><span id="h1pic"></span> <span id="h1name"></span></h1>
<h3 class="text-center h3">Zisky a ztráty voličů 2013 → 2017</h3>
<div class="row">
<div class="col-xs-4 col-xs-offset-1 text-center">
<strong>Přišli k <span class="shortname"></span></strong>
</div>
<div class="col-xs-4 col-xs-offset-2 text-center">
<strong>Odešli od <span class="shortname"></span></strong>
</div>
</div>
</div>
<div id="chart"></div>
<div class="note xbg-info">
<i class="fa fa-info-circle"></i> Odhady metodou ekologické inference. Zobrazeny přesuny voličů mezi stranami přesahující 25 000 lidí.<br />
CC-BY Michal Škop, KohoVolit.eu, VolebníKalkulačka.cz
</div>
<div class="hithit text-center bg-primary">
<h3></h3>
<h3>Podpořte Volební kalkulačku pro prezidentské volby!</h3>
<h3>www.Hithit.cz/VolebniKalkulacka</h3>
</div>
<script>
// var formatNumber = d3.format(",.0f");
d3.csv("list_2017_filtered.csv", function (er,d2017) {
d3.csv("list_2013_filtered.csv", function(err,d2013) {
d3.csv("matn_chart.csv", function(errr,source) {
var d13to17 = {};
var party2color = {};
d2013.forEach(function(d) {
d13to17[d['party']] = {}
party2color[d['party']] = d['color']
});
d2017.forEach(function(d) {
party2color[d['party']] = d['color']
});
var d17to13 = {};
source.forEach(function(d) {
d17to13[d['name']] = {}
for (k in d) {
if (k != 'name') {
d17to13[d['name']][k] = parseInt(d[k])
d13to17[k][d['name']] = parseInt(d[k])
}
}
})
var names = source['name'];
var i = QueryString.i;
if (i === undefined) {
i = 1;
}
var party = d2017[i]['party']
var prev_party = d2017[i]['previous']
var data = source[i];
d3.select("#h1name")
.html(d2017[i]['party_name']);
d3.select("#h1pic")
.html("<img class='logo' src='./" + d2017[i]['party'] + ".png' />");
d3.selectAll(".shortname")
.html(d2017[i]['party'])
var sumout = 0
for (k in d13to17[prev_party]) {
if (k != prev_party) {
sumout += d13to17[prev_party][k]
}
}
if (d2017[i]['votes'] > 1000000) {
var h = 700;
} else {
var h = 400;
}
var margin = {top: 100, right: 10, bottom: 10, left: 10},
width = 930 - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var svg = d3.select("#chart").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 + ")");
maxsum = Math.max(sumout, d2017[i]['votes'])
var x = d3.scale.linear()
.domain([0, 100])
.range([0, width])
var y = d3.scale.linear()
.domain([0, maxsum * 1.1])
.range([0, height]);
// basic rectangle
var offset = (maxsum - d2017[i]['votes']) / 2;
svg.append("rect")
.attr("width", x(20))
.attr("height", y(d2017[i]['votes']))
.attr("x", x(40))
.attr("y", y(offset))
.attr("fill", d2017[i]['color']);
svg.append("text")
.attr("x", x(50))
.attr("y", function() {
return y(d2017[i]['votes']/2 + offset);
})
.attr("dy", 0)
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", "40px")
.text(party)
svg.append("text")
.attr("x", x(50))
.attr("y", function() {
return y(d2017[i]['votes']/2 * 1.3 + offset);
})
.attr("dy", 0)
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", "20px")
.text(customFormat(d2017[i]['votes']))
// prepare out and in rectangles
var outs = []
for (k in d13to17[prev_party]) {
if ((d13to17[prev_party][k] > 25000) && (party != k)) {
outs.push({
'name': k,
'value': d13to17[prev_party][k],
'color': party2color[k]
})
}
}
outs.sort(function(a, b) {
return b.value - a.value;
});
var ins = []
for (k in d13to17) {
if ((d13to17[k][party] > 25000) && (prev_party != k)) {
ins.push({
'name': k,
'value': d13to17[k][party],
'color': party2color[k]
})
}
}
ins.sort(function(a, b) {
return b.value - a.value;
});
s = 0
outs.forEach(function (out,k) {
s += y(out['value'])
s += 15
})
s = s - 15
var offset = (y(maxsum) - s) / 2;
outs.forEach(function (out, k) {
outs[k]['y0'] = offset;
outs[k]['y1'] = offset + y(out['value'])
outs[k]['half'] = (outs[k]['y1'] + outs[k]['y0']) / 2
offset = outs[k]['y1'] + 15;
outs[k]['arrow'] = [
{"x": x(76.98), "y": outs[k]['y0']}, {"x": x(79), "y": outs[k]['half']}, {"x": x(76.98), "y": outs[k]['y1']}, {"x": x(76.98), "y": outs[k]['y0']}
]
});
s = 0
ins.forEach(function (out,k) {
s += y(out['value'])
s += 15
})
s = s - 15
var offset = (y(maxsum) - s) / 2;
ins.forEach(function (inn, k) {
ins[k]['y0'] = offset;
ins[k]['y1'] = offset + y(inn['value'])
ins[k]['half'] = (ins[k]['y1'] + ins[k]['y0']) / 2
offset = ins[k]['y1'] + 15;
ins[k]['arrow'] = [
{"x": x(34.95), "y": ins[k]['y0']}, {"x": x(37), "y": ins[k]['half']}, {"x": x(34.95), "y": ins[k]['y1']},
{"x": x(34.95), "y": ins[k]['y0']}
]
});
var arrowFunction = d3.svg.area()
.x(function(d) { return d.x; })
.y1(function(d) { return d.y; });
// arrows out
var rectouts = svg.selectAll(".rectout")
.data(outs)
.enter()
.append("rect")
.attr("width", x(14))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(63))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", d2017[i]['color']);
var arrowouts = svg.selectAll(".arrowout")
.data(outs)
.enter()
.append("path")
.attr("d", function(d) {
return arrowFunction(d['arrow']);
})
.attr("fill", d2017[i]['color']);
svg.selectAll(".textout")
.data(outs)
.enter()
.append("text")
.attr("x", x(70))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4.5), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4.5), 18)
})
.text(function(d) {
return customFormat(my_round(d['value']))
})
//arrows in
svg.selectAll(".rectin")
.data(ins)
.enter()
.append("rect")
.attr("width", x(14))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(21))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".arrowin")
.data(ins)
.enter()
.append("path")
.attr("d", function(d) {
return arrowFunction(d['arrow']);
})
.attr("fill", function(d) {
return d['color']
});
svg.selectAll(".textin")
.data(ins)
.enter()
.append("text")
.attr("x", x(28))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4.5), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4.5), 18)
})
.text(function(d) {
return customFormat(my_round(d['value']))
})
.attr("class", "number")
// outs
svg.selectAll(".rectend")
.data(outs)
.enter()
.append("rect")
.attr("width", x(16))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(84))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".textout")
.data(outs)
.enter()
.append("text")
.attr("x", x(92))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return d['name']
})
// ins
svg.selectAll(".rectstart")
.data(ins)
.enter()
.append("rect")
.attr("width", x(16))
.attr("height", function(d) {
return d['y1'] - d['y0'];
})
.attr("x", x(0))
.attr("y", function(d) {
return d['y0'];
})
.attr("fill", function(d){
return d['color'];
});
svg.selectAll(".textstart")
.data(ins)
.enter()
.append("text")
.attr("x", x(8))
.attr("y", function(d){
return d['half'] + Math.max(y(d['value'] / 4), 20)/3
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("font-size", function(d) {
return Math.max(y(d['value'] / 4), 20)
})
.text(function(d) {
return d['name']
})
svg.append("text")
.text(function (d) { return "Přišli k " + party;})
.attr("text-anchor", "middle")
.attr("x", x(20))
.attr("y", -30)
.attr("class", "label-small")
.style("font-size", "1.2em")
.style("font-weight", "bold")
svg.append("text")
.text(function (d) { return "Odešli od " + party;})
.attr("text-anchor", "middle")
.attr("x", x(80))
.attr("y", -30)
.attr("class", "label-small")
.style("font-size", "1.2em")
.style("font-weight", "bold")
var pause = 0;
})
})
})
function my_round(n) {
if (n < 100000) {
return Math.round(n/10000)*10000;
}
return Math.round(n/20000)*20000;
}
function customFormat(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ' ' + '$2');
}
return x1 + x2;
}
var QueryString = function () {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = decodeURIComponent(pair[1]);
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(decodeURIComponent(pair[1]));
}
}
return query_string;
}();
</script>
</body>
</html>
# join the 2013 and 2017 data for ei
import csv
import random
def n2(n):
if n < 10:
return "0" + str(n)
else:
return str(n)
def n(s):
if s == '':
return 0
else:
return int(s)
# data rows
d = {
'2013': {},
'2017': {}
}
# stations in municipality for matching in changed numbering municipality
stations = {
'2013': {},
'2017': {}
}
# selected data, filtered out 6 % of polling stations
data = {}
for y in d:
with open("data_" + y + ".csv") as fin:
dr = csv.DictReader(fin)
for row in dr:
try:
stations[y][row['OBEC']]
except Exception:
stations[y][row['OBEC']] = []
d[y][row['OBEC']] = {}
stations[y][row['OBEC']].append(row['OKRSEK'])
d[y][row['OBEC']][row['OKRSEK']] = row
for muni in d['2017']:
same = True
for okr in stations['2017'][muni]:
try:
d['2013'][muni][okr]
except Exception:
same = False
if same:
data[muni] = {}
for okr in stations['2017'][muni]:
data[muni][okr] = {}
data[muni][okr]['2013'] = d['2013'][muni][okr]
data[muni][okr]['2017'] = d['2017'][muni][okr]
else:
try:
if len(stations['2013'][muni]) == len(stations['2017'][muni]):
data[muni] = {}
for i in range(0, len(stations['2013'][muni])):
o2017 = stations['2017'][muni][i]
o2013 = stations['2013'][muni][i]
data[muni][o2017] = {}
data[muni][o2017]['2013'] = d['2013'][muni][o2013]
data[muni][o2017]['2017'] = d['2017'][muni][o2017]
else:
print(muni, len(stations['2017'][muni]), '::not the same number or stations')
except Exception:
print(muni, len(stations['2017'][muni]), '::not in 2013')
# filter parties, randomly select some districts to be able to perfomr EI
parties = {
'2013': [1, 3, 4, 6, 11, 17, 19, 20],
'2017': [1, 4, 7, 8, 15, 20, 21, 24, 29]
}
with open("data_filtered_random.csv", "w") as foutR:
select = 0.25
header = []
for k in parties['2013']:
header.append('A' + str(k))
header.append('A997')
header.append('A998')
header.append('A999')
for k in parties['2017']:
header.append('B' + str(k))
header.append('B997')
header.append('B998')
header.append('B999')
drR = csv.DictWriter(foutR, header)
drR.writeheader()
with open("data_filtered.csv", "w") as fout:
dr = csv.DictWriter(fout, header)
dr.writeheader()
for muni in data:
for okr in data[muni]:
row = {}
for y in parties:
if y == '2013':
code = 'A'
else:
code = 'B'
s = 0
for k in parties[y]:
try:
num = int(data[muni][okr][y]['HLASY_' + n2(k)])
except Exception:
num = 0
s += num
row[code + str(k)] = num
row[code + '997'] = int(data[muni][okr][y]['HLASY']) - s
row[code + '999'] = int(data[muni][okr][y]['VOLICI']) - int(data[muni][okr][y]['HLASY'])
if int(data[muni][okr]['2013']['VOLICI']) >= int(data[muni][okr]['2017']['VOLICI']):
row['B998'] = int(data[muni][okr]['2013']['VOLICI']) - int(data[muni][okr]['2017']['VOLICI'])
row['A998'] = 0
else:
row['A998'] = int(data[muni][okr]['2017']['VOLICI']) - int(data[muni][okr]['2013']['VOLICI'])
row['B998'] = 0
if (1.25 * int(data[muni][okr]['2013']['VOLICI']) >= int(data[muni][okr]['2017']['VOLICI'])) and (0.8 * int(data[muni][okr]['2013']['VOLICI']) <= int(data[muni][okr]['2017']['VOLICI'])):
dr.writerow(row)
if random.random() < select:
drR.writerow(row)
party_id,party_name,party,color,party_group
20,Komunistická strana Čech a Moravy,KSČM,#8c0000,KSČM
17,Úsvit přímé demokracie Tomia Okamury,Úsvit,#f51941,Úsvit
1,Česká strana sociálně demokratická,ČSSD,#F07D00,ČSSD
19,ANO 2011,ANO,#261060,ANO
11,Křesťanská a demokratická unie - Československá strana lidová,KDU-ČSL,#e6ac21,KDU-ČSL
6,Občanská demokratická strana,ODS,#004494,ODS
4,TOP 09,TOP 09,#723769,TOP 09
3,Česká pirátská strana,Piráti,#000000,Piráti
,,neparlamentní,#888,neparlamentní
,,odešlí,#888,přibylí
,,nevoliči,#888,nevoliči
party_id,party_name,party,color,party_group,votes,previous
8,Komunistická strana Čech a Moravy,KSČM,#8c0000,KSČM,393100,KSČM
29,Strana přímé demokracie - Tomio Okamura,SPD,#eb1b26,SPD,538574,Úsvit
4,Česká strana sociálně demokratická,ČSSD,#f1953e,ČSSD,368347,ČSSD
21,ANO 2011,ANO,#261060,ANO,1500113,ANO
24,Křesťanská a demokratická unie – ČS strana lidová,KDU-ČSL,#e6ac21,KDU-ČSL,293643,KDU-ČSL
1,Občanská demokratická strana,ODS,#004494,ODS,572962,ODS
20,TOP 09,TOP 09,#723769,TOP 09,268811,TOP 09
15,Česká pirátská strana,Piráti,#000000,Piráti,546393,Piráti
7,Starostové a nezávislí,STAN,#5d8c00,STAN,262157,STAN
,,neparlamentní,#888,ostatní,,neparlamentní
,,přibylí,#888,přibylí,,přibylí
,,nevoliči,#888,nevoliči,,nevoliči
name,KSČM,Úsvit,ČSSD,ANO,KDU-ČSL,ODS,TOP 09,Piráti,neparlamentní,odešlí,nevoliči
KSČM,254240.33761823,15254.9561311596,27524.0801666488,14661.461412228,7060.6503764015,6606.2215657717,6568.8162519496,4881.4612660556,8067.301072003,3819.8452305577,48180.5033989776
SPD,110885.659896705,102298.917625353,69897.7099995061,51745.5319231317,10481.6355602412,9642.1208214317,7085.8426458823,14201.0764789418,35216.8066028686,8504.0678863227,114819.093021927
ČSSD,26027.692578728,10271.9827739147,201700.891754245,13883.3915585773,18187.6621206604,8014.9992964658,8493.4192920129,7679.1331630617,17825.4570580152,4538.6671493368,49615.6937885127
ANO,199602.379621616,87619.3887537366,364385.497673393,448372.098296437,32259.8820710975,38810.3232289038,21723.3494718457,14646.9676159827,53113.7528059145,11588.66300895,206103.405374292
KDU-ČSL,5723.693363904,4347.5584599632,9448.3688663844,8447.6461234501,194148.336745684,4634.886935861,6218.3882643493,3161.7924101176,6494.4974140694,3102.5589235842,48981.0005014631
ODS,9045.7136077175,8432.0079495786,12695.1988701911,49997.2769304596,9825.6369130624,153956.22451832,177851.93713776,8351.0393541643,21743.7598107156,19463.2396303026,81557.2191297929
TOP 09,5654.6431691234,4507.6845616574,8908.426337364,9894.8788829583,5535.0040007416,14451.3395811804,98583.1795880245,4474.3548491156,9338.7020503307,8143.5039505982,81205.3848081083
Piráti,9132.1926171196,10774.8796716244,17668.2869795353,63180.8567209001,13854.1200037068,67327.5909964825,136266.805220292,22911.8646555925,82126.7378611841,19571.7803315446,80233.9498011818
STAN,6919.8442976441,8893.7432758664,10577.9310669867,25383.5938004626,8602.9328431908,10030.9107825919,52475.0714498077,10841.9986740398,13936.1247669976,9637.8447953855,106021.841124621
neparlamentní,9901.9249809547,15330.2605191835,14246.8744935569,70881.6883821733,12669.9896863278,19399.0535416654,34513.2854022375,15159.558361107,56409.178921035,7667.6580360965,50522.604393226
přibylí,4200.4368488644,2984.0157325085,6524.984061325,5791.5965389629,3144.8998992596,3072.5851775286,4029.4459053668,1726.0335401903,4024.1169427956,914.8328495339,169625.640379655
nevoliči,101635.193285955,71227.9390835938,260703.397920503,143876.398961153,24791.0494570795,37682.669833029,17508.9503145272,19989.9403941614,163677.13974441,55406.4116310692,2304456.46399612
2989.94479034,47251.2306124,2495.26104718,4714.8540045,3565.87812321,2005.56249396,80688.4879505,1994.16697752,21837.2806654,4052.78713092,1508.76734299,50790.7788611
1508.65575994,1640.80223916,1870.27715993,1270.10237013,4138.77222821,889.299273267,2477.55523198,724.748618985,1678.3766394,3061.8225035,397.51562821,8884.07234729
38141.0559569,2081.77357675,11976.5702724,1517.64820612,28864.6769857,21748.1172909,5337.10663514,1548.40207754,2106.97843566,9457.16867432,949.864402243,3640.63748627
34680.6474202,2336.58433847,2130.41564824,1313.7006982,13671.8135917,4232.52470632,6872.81078384,1210.36486191,2330.15410934,5595.35670959,731.718394687,8190.90873747
2983.14187624,3303.68042038,1990.39210102,1787.84873116,2968.59559378,1203.6569198,7878.93725438,42917.6641845,2944.7033865,2584.11837734,765.758189562,4596.50296539
2022.74613451,2312.86673277,1912.57375247,2991.02923104,2305.82377917,977.834866268,15428.7907021,960.29936823,20408.1726844,5165.61682707,639.979413203,21107.2665087
7312.45183629,3238.67819045,4342.53659128,2717.56106356,18010.0563922,2177.48719272,104564.168867,1902.92009048,13938.4982848,8572.50951205,1240.97135079,33992.1606287
1839.39335322,4233.97028765,1551.10144317,58791.1063417,2267.30971872,1192.2509042,44418.9260869,1209.21526072,23463.4839941,2879.71601754,880.168906612,22911.3576855
9289.94796685,3334.07490133,3608.63850677,2050.05066606,19217.9756943,1801.40441592,11851.639111,1478.8036064,5216.85767907,13890.7818534,940.606379454,32541.2192195
4432.56497908,1010.91171362,2149.6930467,781.558184067,3370.23691826,1950.86243265,3541.13767382,722.790913216,2323.22643162,2115.39922455,181.874084583,11386.7443979
18125.4437052,10911.7504037,24635.7642524,10642.2444212,18171.663722,17652.6645527,46436.502369,10936.4205079,23005.2125702,11030.007683,37688.7178887,515679.607924
12695.1988701911,201700.891754245,10577.9310669867,27524.0801666488,17668.2869795353,8908.426337364,364385.497673393,9448.3688663844,69897.7099995061,14246.8744935569,6524.984061325,260703.397920503
8351.0393541643,7679.1331630617,10841.9986740398,4881.4612660556,22911.8646555925,4474.3548491156,14646.9676159827,3161.7924101176,14201.0764789418,15159.558361107,1726.0335401903,19989.9403941614
177851.93713776,8493.4192920129,52475.0714498077,6568.8162519496,136266.805220292,98583.1795880245,21723.3494718457,6218.3882643493,7085.8426458823,34513.2854022375,4029.4459053668,17508.9503145272
153956.22451832,8014.9992964658,10030.9107825919,6606.2215657717,67327.5909964825,14451.3395811804,38810.3232289038,4634.886935861,9642.1208214317,19399.0535416654,3072.5851775286,37682.669833029
9825.6369130624,18187.6621206604,8602.9328431908,7060.6503764015,13854.1200037068,5535.0040007416,32259.8820710975,194148.336745684,10481.6355602412,12669.9896863278,3144.8998992596,24791.0494570795
8432.0079495786,10271.9827739147,8893.7432758664,15254.9561311596,10774.8796716244,4507.6845616574,87619.3887537366,4347.5584599632,102298.917625353,15330.2605191835,2984.0157325085,71227.9390835938
49997.2769304596,13883.3915585773,25383.5938004626,14661.461412228,63180.8567209001,9894.8788829583,448372.098296437,8447.6461234501,51745.5319231317,70881.6883821733,5791.5965389629,143876.398961153
9045.7136077175,26027.692578728,6919.8442976441,254240.33761823,9132.1926171196,5654.6431691234,199602.379621616,5723.693363904,110885.659896705,9901.9249809547,4200.4368488644,101635.193285955
21743.7598107156,17825.4570580152,13936.1247669976,8067.301072003,82126.7378611841,9338.7020503307,53113.7528059145,6494.4974140694,35216.8066028686,56409.178921035,4024.1169427956,163677.13974441
19463.2396303026,4538.6671493368,9637.8447953855,3819.8452305577,19571.7803315446,8143.5039505982,11588.66300895,3102.5589235842,8504.0678863227,7667.6580360965,914.8328495339,55406.4116310692
81557.2191297929,49615.6937885127,106021.841124621,48180.5033989776,80233.9498011818,81205.3848081083,206103.405374292,48981.0005014631,114819.093021927,50522.604393226,169625.640379655,2304456.46399612
254240.33761823,110885.659896705,26027.692578728,199602.379621616,5723.693363904,9045.7136077175,5654.6431691234,9132.1926171196,6919.8442976441,9901.9249809547,4200.4368488644,101635.193285955
15254.9561311596,102298.917625353,10271.9827739147,87619.3887537366,4347.5584599632,8432.0079495786,4507.6845616574,10774.8796716244,8893.7432758664,15330.2605191835,2984.0157325085,71227.9390835938
27524.0801666488,69897.7099995061,201700.891754245,364385.497673393,9448.3688663844,12695.1988701911,8908.426337364,17668.2869795353,10577.9310669867,14246.8744935569,6524.984061325,260703.397920503
14661.461412228,51745.5319231317,13883.3915585773,448372.098296437,8447.6461234501,49997.2769304596,9894.8788829583,63180.8567209001,25383.5938004626,70881.6883821733,5791.5965389629,143876.398961153
7060.6503764015,10481.6355602412,18187.6621206604,32259.8820710975,194148.336745684,9825.6369130624,5535.0040007416,13854.1200037068,8602.9328431908,12669.9896863278,3144.8998992596,24791.0494570795
6606.2215657717,9642.1208214317,8014.9992964658,38810.3232289038,4634.886935861,153956.22451832,14451.3395811804,67327.5909964825,10030.9107825919,19399.0535416654,3072.5851775286,37682.669833029
6568.8162519496,7085.8426458823,8493.4192920129,21723.3494718457,6218.3882643493,177851.93713776,98583.1795880245,136266.805220292,52475.0714498077,34513.2854022375,4029.4459053668,17508.9503145272
4881.4612660556,14201.0764789418,7679.1331630617,14646.9676159827,3161.7924101176,8351.0393541643,4474.3548491156,22911.8646555925,10841.9986740398,15159.558361107,1726.0335401903,19989.9403941614
8067.301072003,35216.8066028686,17825.4570580152,53113.7528059145,6494.4974140694,21743.7598107156,9338.7020503307,82126.7378611841,13936.1247669976,56409.178921035,4024.1169427956,163677.13974441
3819.8452305577,8504.0678863227,4538.6671493368,11588.66300895,3102.5589235842,19463.2396303026,8143.5039505982,19571.7803315446,9637.8447953855,7667.6580360965,914.8328495339,55406.4116310692
48180.5033989776,114819.093021927,49615.6937885127,206103.405374292,48981.0005014631,81557.2191297929,81205.3848081083,80233.9498011818,106021.841124621,50522.604393226,169625.640379655,2304456.46399612
0.0133542276082,0.211041919705,0.0111447823631,0.0210583264678,0.0159265643413,0.00895760286722,0.360385394718,0.00890670616816,0.0975335789786,0.0181012846688,0.00673872727389,0.226850884839
0.0528573947145,0.0574872902795,0.0655271936071,0.0444994173544,0.145006384564,0.0311575668582,0.0868038410755,0.0253923557909,0.0588037502416,0.107274280131,0.0139273922013,0.311263133182
0.299450859362,0.0163443006732,0.0940297579685,0.0119152720902,0.226620687648,0.170747564504,0.0419023838827,0.0121567251122,0.0165421876082,0.0742495774069,0.00745752062686,0.0285831631174
0.416349297336,0.0280512424033,0.0255761389755,0.0157712846585,0.16413332523,0.0508124507044,0.0825097036369,0.0145307137342,0.0279740459961,0.0671735681908,0.00878445075677,0.098333778377
0.039290640451,0.0435124191028,0.026215240053,0.0235475631367,0.039099052931,0.0158532356905,0.103772634236,0.565263933941,0.0387843712413,0.0340351449107,0.010085718664,0.0605400456422
0.0265337338752,0.0303394426662,0.0250885279665,0.0392353604219,0.0302470554637,0.012826923593,0.202389919092,0.012596898564,0.267707852038,0.067760901802,0.00839504431419,0.276878340203
0.0361984646121,0.0160322666722,0.0214966417072,0.0134526066212,0.0891542814327,0.0107791059488,0.517618775638,0.00941993015436,0.0689990509618,0.0424360651059,0.00614311841387,0.168269692731
0.0111048995594,0.0255615878461,0.00936440577143,0.354937311135,0.0136883427639,0.00719793105567,0.268168693699,0.00730034932034,0.141655199858,0.0173856000286,0.0053138102767,0.138321868686
0.0882890266945,0.031686100828,0.0342954753452,0.0194830992194,0.182642182189,0.0171200358853,0.112634611687,0.0140541294254,0.0495795335487,0.132014045099,0.00893925585385,0.309262504225
0.1304962163,0.0297615837023,0.063287692369,0.0230093380065,0.0992209178985,0.0574340516575,0.104252294104,0.0212792096216,0.0683965740753,0.062278070614,0.00535443473321,0.335229616918
0.024332198134,0.0146482964572,0.0330718688448,0.0142865026677,0.024394245421,0.0236975236841,0.0623379043665,0.0146814144251,0.0308829620657,0.0148070489599,0.0505945876967,0.692265447277
# prepage basic csv
import csv
import json
def n2(n):
if n < 10:
return "0" + str(n)
else:
return str(n)
with open("data_2017.csv", "w") as fout:
header = ['OBEC', 'OKRSEK', 'VOLICI', 'OBALKY_VYDANE', 'OBALKY_ODEVZDANE', 'HLASY']
for j in range(1, 32):
header.append("HLASY_" + n2(j))
dw = csv.DictWriter(fout, header)
dw.writeheader()
for i in range(1, 70):
with open("json/" + str(i) + ".json") as fin:
js = json.load(fin)
if not isinstance(js['VYSLEDKY_OKRSKY']['OKRSEK'], list):
js['VYSLEDKY_OKRSKY']['OKRSEK'] = [js['VYSLEDKY_OKRSKY']['OKRSEK']]
for item in js['VYSLEDKY_OKRSKY']['OKRSEK']:
d = {
"OBEC": item['@CIS_OBEC'],
"OKRSEK": item['@CIS_OKRSEK'],
"VOLICI": item['UCAST_OKRSEK']['@ZAPSANI_VOLICI'],
"OBALKY_VYDANE": item['UCAST_OKRSEK']['@VYDANE_OBALKY'],
"OBALKY_ODEVZDANE": item['UCAST_OKRSEK']['@ODEVZDANE_OBALKY'],
"HLASY": item['UCAST_OKRSEK']['@PLATNE_HLASY']
}
for j in range(1, 32):
d["HLASY_" + n2(j)] = ''
try:
if not isinstance(item['HLASY_OKRSEK'], list):
item['HLASY_OKRSEK'] = [item['HLASY_OKRSEK']]
for p in item['HLASY_OKRSEK']:
d["HLASY_" + n2(int(p['@KSTRANA']))] = p['@HLASY']
except Exception:
nothing = None
dw.writerow(d)