Skip to content

Instantly share code, notes, and snippets.

@michalskop
Last active March 5, 2020 00:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michalskop/0f6fe50f727499421a44fa80aef74ab5 to your computer and use it in GitHub Desktop.
Save michalskop/0f6fe50f727499421a44fa80aef74ab5 to your computer and use it in GitHub Desktop.
CZ: support by age

Distribution of voters' support by age

Czechia, 10-11/2019

party strength age value
ČSSD core 18-19 0
ČSSD core 20-29 0
ČSSD core 30-39 1
ČSSD core 40-49 2
ČSSD core 50-59 2
ČSSD core 60-69 2
ČSSD core 70-79 2
ČSSD core 80-… 0
ČSSD weak 18-19 0
ČSSD weak 20-29 0
ČSSD weak 30-39 1
ČSSD weak 40-49 2
ČSSD weak 50-59 2
ČSSD weak 60-69 2
ČSSD weak 70-79 1
ČSSD weak 80-… 0
ODS core 18-19 0
ODS core 20-29 1
ODS core 30-39 3
ODS core 40-49 4
ODS core 50-59 3
ODS core 60-69 2
ODS core 70-79 1
ODS core 80-… 1
ODS weak 18-19 0
ODS weak 20-29 1
ODS weak 30-39 2
ODS weak 40-49 3
ODS weak 50-59 2
ODS weak 60-69 2
ODS weak 70-79 1
ODS weak 80-… 0
KSČM core 18-19 0
KSČM core 20-29 1
KSČM core 30-39 1
KSČM core 40-49 1
KSČM core 50-59 2
KSČM core 60-69 3
KSČM core 70-79 5
KSČM core 80-… 2
KSČM weak 18-19 0
KSČM weak 20-29 0
KSČM weak 30-39 0
KSČM weak 40-49 0
KSČM weak 50-59 0
KSČM weak 60-69 1
KSČM weak 70-79 1
KSČM weak 80-… 1
KDU-ČSL core 18-19 0
KDU-ČSL core 20-29 1
KDU-ČSL core 30-39 1
KDU-ČSL core 40-49 1
KDU-ČSL core 50-59 1
KDU-ČSL core 60-69 1
KDU-ČSL core 70-79 1
KDU-ČSL core 80-… 1
KDU-ČSL weak 18-19 0
KDU-ČSL weak 20-29 0
KDU-ČSL weak 30-39 0
KDU-ČSL weak 40-49 1
KDU-ČSL weak 50-59 0
KDU-ČSL weak 60-69 1
KDU-ČSL weak 70-79 0
KDU-ČSL weak 80-… 1
TOP 09 core 18-19 0
TOP 09 core 20-29 1
TOP 09 core 30-39 1
TOP 09 core 40-49 1
TOP 09 core 50-59 0
TOP 09 core 60-69 0
TOP 09 core 70-79 0
TOP 09 core 80-… 0
TOP 09 weak 18-19 0
TOP 09 weak 20-29 1
TOP 09 weak 30-39 1
TOP 09 weak 40-49 1
TOP 09 weak 50-59 0
TOP 09 weak 60-69 0
TOP 09 weak 70-79 0
TOP 09 weak 80-… 0
ANO core 18-19 1
ANO core 20-29 4
ANO core 30-39 6
ANO core 40-49 7
ANO core 50-59 7
ANO core 60-69 9
ANO core 70-79 8
ANO core 80-… 2
ANO weak 18-19 1
ANO weak 20-29 1
ANO weak 30-39 2
ANO weak 40-49 3
ANO weak 50-59 3
ANO weak 60-69 3
ANO weak 70-79 3
ANO weak 80-… 1
Piráti core 18-19 1
Piráti core 20-29 4
Piráti core 30-39 3
Piráti core 40-49 2
Piráti core 50-59 1
Piráti core 60-69 0
Piráti core 70-79 0
Piráti core 80-… 0
Piráti weak 18-19 1
Piráti weak 20-29 6
Piráti weak 30-39 5
Piráti weak 40-49 3
Piráti weak 50-59 1
Piráti weak 60-69 1
Piráti weak 70-79 0
Piráti weak 80-… 0
SPD core 18-19 0
SPD core 20-29 1
SPD core 30-39 1
SPD core 40-49 1
SPD core 50-59 1
SPD core 60-69 1
SPD core 70-79 0
SPD core 80-… 0
SPD weak 18-19 0
SPD weak 20-29 0
SPD weak 30-39 1
SPD weak 40-49 1
SPD weak 50-59 1
SPD weak 60-69 1
SPD weak 70-79 0
SPD weak 80-… 0
STAN core 18-19 0
STAN core 20-29 0
STAN core 30-39 1
STAN core 40-49 0
STAN core 50-59 0
STAN core 60-69 0
STAN core 70-79 0
STAN core 80-… 0
STAN weak 18-19 0
STAN weak 20-29 0
STAN weak 30-39 1
STAN weak 40-49 1
STAN weak 50-59 1
STAN weak 60-69 1
STAN weak 70-79 0
STAN weak 80-… 0
Ostatní/neví core 18-19 0
Ostatní/neví core 20-29 0
Ostatní/neví core 30-39 0
Ostatní/neví core 40-49 0
Ostatní/neví core 50-59 0
Ostatní/neví core 60-69 0
Ostatní/neví core 70-79 0
Ostatní/neví core 80-… 0
Ostatní/neví weak 18-19 0
Ostatní/neví weak 20-29 5
Ostatní/neví weak 30-39 4
Ostatní/neví weak 40-49 4
Ostatní/neví weak 50-59 2
Ostatní/neví weak 60-69 3
Ostatní/neví weak 70-79 2
Ostatní/neví weak 80-… 0
Nevoliči weak 18-19 5
Nevoliči weak 20-29 20
Nevoliči weak 30-39 26
Nevoliči weak 40-49 29
Nevoliči weak 50-59 22
Nevoliči weak 60-69 19
Nevoliči weak 70-79 11
Nevoliči weak 80-… 7
<!DOCTYPE html>
<html lang="cs">
<meta charset="utf-8" />
<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Kalam&display=swap" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<style>
html {
font-family: 'Kalam', cursive;
}
.weak {
opacity: 0.5
}
</style>
<script>
let bins = 6
let binLabels = ['Koalice']
var margin = {top: 100, right: 30, bottom: 100, left: 60}
var svg = d3.select("svg")
.attr('width', 1500 + margin.left + margin.right)
.attr('height', 300 + margin.top + margin.bottom),
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleLinear()
.domain([0, 100])
.range([0, width]),
y = d3.scaleLinear()
.domain([0, 8])
.range([height, 0])
function age2y(age) {
return parseInt(age[0])
}
function addProperties( obj, arr , property ) {
let merged = obj
arr.forEach((item, i) => {
if (item[property] == obj[property]) {
merged = {...obj, ...item}
// console.log(merged)
}
});
return merged
}
function compare( a, b, property, reverse=1 ) {
if ( a[property] < b[property] ){
return -1 * reverse;
}
if ( a[property] > b[property] ){
return 1 * reverse;
}
return 0;
}
function rebin(obj) {
let reobj = obj
if (parseInt(obj.bin) == 1 && obj.strength == 'weak') {
reobj.bin = 2
}
if (parseInt(obj.bin) == 5 && obj.strength == 'weak') {
reobj.bin = 4
}
reobj.bin = parseInt(obj.bin)
return reobj
}
function getAgeGroups(data) {
let ag = []
data.forEach((item, i) => {
if (!ag.includes(item.age)) {
ag.push(item.age)
}
});
return ag
}
d3.csv("data200_2.csv", function(error, data) {
d3.csv("parties.csv", function(e, parties) {
if (error) throw error;
var g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// PREPARE DATA
// join data, re-bin weak data
let displayData = data.map(function (obj) {
// console.log(addProperties(obj, parties, 'party'))
return rebin(addProperties(obj, parties, 'party'))
})
// order data
displayData.sort((a, b) => compare(a, b, 'order', -1))
displayData.sort((a, b) => compare(a, b, 'age', -1))
displayData.sort((a, b) => compare(a, b, 'strength'))
displayData.sort((a, b) => compare(a, b, 'bin'))
// get age groups
ageGroups = getAgeGroups(displayData)
// indexes
indexes = {}
ageGroups.forEach((item, i) => {
indexes[item] = {}
for (i = 1; i <= bins; i++) {
indexes[item][i] = 0
}
});
// prepare points
let points = []
let lines = [18, 25, 35, 47, 65]
let centers = [lines[0] / 2]
for (i = 0; i < (bins - 2); i++) {
centers.push((lines[i] + lines[i + 1]) / 2)
}
centers.push((lines[i] + 90) / 2)
displayData.forEach((item, i) => {
for (i = 0; i < parseInt(item['value']); i++) {
let newItem = Object.assign({}, item)
if (item.bin == 1) {
newItem.x = lines[0] - indexes[item.age][item.bin]
}
if (item.bin == 2) {
newItem.x = lines[1] - indexes[item.age][item.bin]
}
if (item.bin == 3) {
newItem.x = (lines[2] + lines[1]) / 2 + ((indexes[item.age][item.bin] % 2) * 2 - 1) * Math.round(indexes[item.age][item.bin] / 2)
}
if (item.bin == 4) {
newItem.x = lines[2] + 1 + indexes[item.age][item.bin]
}
if (item.bin == 5) {
newItem.x = lines[3] + 1 + indexes[item.age][item.bin]
}
if (item.bin == 6) {
newItem.x = lines[4] + 1 + indexes[item.age][item.bin]
}
indexes[item.age][item.bin]++
newItem.y = age2y(item.age)
points.push(newItem)
}
})
// DISPLAY points
g.selectAll(".icon")
.data(points)
.enter()
.append("text")
.attr('font-family', 'FontAwesome')
.attr('font-size', 30)
.attr('fill', function(d) {return d.color})
.attr('class', function(d) { return d.strength })
.attr('stroke-width', 1)
.attr('stroke', '#aaa')
.attr('text-anchor',"middle")
.attr('x',function(d) {return x(d.x)})
.attr('y',function(d) {return y(d.y)})
.text('\uf183')
// display counts
counts = []
for (i = 0; i < bins; i++) {
c = {
'count': 0,
'x': centers[i]
}
counts.push(c)
}
for(var a in indexes) {
for(var b in indexes[a]) {
counts[b - 1].count = counts[b - 1].count + indexes[a][b]
}
}
svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll(".counts")
.data(counts)
.enter()
.append("text")
.attr("x", function(d) { return x(d.x) })
.attr("y", function() { return y(-1) })
.attr('text-anchor',"middle")
.attr("font-size", 48)
.attr("font-weight", "bold")
.attr("fill", function(d, i) {
if (i == counts.length - 1) {
return "gray"
} else {
return "green"
}
})
.text(function(d) { return d.count })
// bins
let dlines = lines
dlines[0]++
dlines[1]++
svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll(".bins")
.data(dlines)
.enter()
.append("line")
.attr("x1", function(d) { return x(d) })
.attr("y1", function() { return y(-1)})
.attr("x2", function(d) { return x(d) })
.attr("y2", function() { return y(10)})
.attr("stroke", "green")
.attr("stroke-width", 1)
.attr("stroke-dasharray", 4)
// display ages
svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll(".ages")
.data(ageGroups)
.enter()
.append("text")
.attr("x", function() { return x(0) })
.attr("y", function(d, i) { return y(ageGroups.length - i) })
.attr('text-anchor',"end")
.attr("font-size", 24)
.text(function(d) { return d })
svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll(".ages")
.data(ageGroups)
.enter()
.append("line")
.attr("x1", function() { return x(-2) })
.attr("y1", function(d, i) { return y(ageGroups.length - i - 0.2)})
.attr("x2", function() { return x(100) })
.attr("y2", function(d, i) { return y(ageGroups.length - i - 0.2)})
.attr("stroke", "#aaaaaa")
.attr("stroke-width", 1)
.attr("stroke-dasharray", 4)
svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append("line")
.attr("x1", function() { return x(lines[lines.length - 1]) })
.attr("y1", function() { return y(-1)})
.attr("x2", function() { return x(lines[lines.length - 1]) })
.attr("y2", function() { return y(10)})
.attr("stroke", "#aaaaaa")
.attr("stroke-width", 5)
})
})
</script>
</html>
party color side order bin
ANO #261060 left 1 1
KSČM #8c0000 left 2 1
ČSSD #F07D00 left 6 1
SPD #ea2329 middle1 3 3
Ostatní/neví #888888 middle1 1 3
ODS #004494 right 5 5
KDU-ČSL #e6ac21 right 4 5
TOP 09 #723769 right 3 5
STAN #5d8c00 right 2 5
Piráti #000000 right 1 5
Nevoliči #888888 0 6
This file has been truncated, but you can view the full file.
View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment