xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Stadt-Land/Urbanisierung</title>
</head>
<body>
<div id="container">
<div class="desc">Ein möglicher Unterschied zwischen Stadt und Land in Österreich lässt sich anhand des Urbanisierungsgrades überprüfen: Die Einteilung basiert auf den Kategorien der Europäischen Kommission, die zwei Faktoren berücksichtigt, Bevölkerungszahl pro km² und Bevölkerungszahl der Gemeinde insgesamt. Sie teilt das Gebiet in Rasterzellen, die jeweils einen km² groß sind, darauf bauen die Definitionen auf: <ul><li>ländlich: weniger als 50 Prozent der Bevölkerung leben in einer Rasterzelle mit 300 EinwohnerInnen, Gesamtbevölkerung unter 5.000</li>
<li>mittel: mehr als 50 Prozent der Bevölkerung leben in einer Rasterzelle mit mehr als 300 EinwohnerInnen, aber weniger als 50 Prozent wohnen in einer urbanen Rasterzelle (siehe unten); Gesamtbevölkerung mindestens 5.000</li>
<li>städtisch: mehr als 50 Prozent der Bevölkerung leben in einem Raster mit mehr als 1.500 Menschen, Gesamtbevölkerung mindestens 50.000</li></ul>
Gut 80 Prozent der österreichischen Gemeinden gelten in dieser Logik als "ländlich", es gibt insgesamt nur sechs städtische Regionen: Wien, Graz, Linz, Salzburg, Innsbruck und Klagenfurt.<br><br>
Die erste Grafik zeigt den <span style="color: #e34a33; text-decoration: underline">Auszählungsgrad</span> (=Summe der Wahlberechtigten in den bis jetzt ausgezählten Gemeinden) für jede der drei Kategorien sowie insgesamt, die <span style="color: #fee8c8; text-decoration: underline">Balken im Hintergrund</span> stehen für den Anteil der Kategorie an allen Wahlberechtigten (also z.B. der ländlichen Regionen an ganz Österreich).
</div>
<div id="azg">
</div>
<div class="desc">
Die zweite Grafik zeigt das Ergebnis der Parteien in ländlichen, mittleren und städtischen Gemeinden im Verhältnis zum Gesamtergebnis (jeweils ohne Wahlkarten).
</div>
<div id="chart">
<div id="legend">
</div>
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var percent = d3.formatLocale({"decimal":",", "thousands":".","grouping":[3],"currency":["€", ""]});
var margin = { top: 20, right: 20, bottom: 30, left: 20 };
var width = parseInt(d3.select("#chart").style("width"), 10) - margin.left - margin.right;
var height = window.innerHeight - margin.top - margin.bottom - 40 - parseInt(d3.selectAll(".desc").style("height"), 10);
//TODO: Mindestmaße festlegen
if (height < 400) height = 400;
var parties = ["spoe", "oevp", "fpoe", "gruene", "neos", "frank", "kpoe"]; //sollte aus der db kommen
var labels = {"spoe": "SPÖ", "oevp": "ÖVP", "fpoe": "FPÖ", "gruene": "GRÜNE", "neos": "NEOS", "frank": "FRANK", "kpoe": "KPÖ"};
var color = {"oevp": "#191919", "spoe": "#ca5670", "fpoe": "#638ccc", "gruene": "#72a555", "kpoe": "#9F000F", "neos": "#F52887", "frank": "#E9AB17", "bzoe": "#F87431", "tie": "grey"};
var urbanisierung, gemeinden;
var wbr = {"total": 0, "land": 0, "mittel": 0, "stadt": 0}; //wahlberechtigte für den auszählungsgrad
var current = {}; //auszählungsgrade
var gueltig = {"total": 0, "land": 0, "mittel": 0, "stadt": 0}; //gültige stimmen für das ergebnis
var results = [];
var offset_x = 75; //abstand balken links;
//TODO: bei der scale überlegen, ob 100% oder nicht
//azg: offset rechts zwecks beschriftung?
var scale = {"result": d3.scaleLinear().domain([0, 1]).range([0, width - offset_x]), "y": d3.scaleBand().domain(parties).rangeRound([margin.top, height - margin.bottom]).paddingOuter(0).paddingInner(0.3), "classes": d3.scaleBand().domain(d3.range(3)).paddingOuter(0.2).paddingInner(0.1), "azg": d3.scaleLinear().range([0, width - offset_x - 15]), "azg_y": d3.scaleBand().rangeRound([0, 200]).paddingOuter(0).paddingInner(0.1)};
scale.classes.rangeRound([0, scale.y.bandwidth()]);
var svg = d3.select("#chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id", "svg")
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
var legend = d3.select("#legend")
.append("svg")
.attr("width", scale.classes.bandwidth() * 3 + 60)
.attr("height", scale.y.bandwidth() + 15)
.attr("id", "svg_legend");
var azg = d3.select("#azg")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 200 + margin.top + margin.bottom) //variable höhe?
.attr("id", "svg_azg")
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
//TODO: ein gemeinsames resize?
window.onresize = resize;
var q = d3.queue();
q.defer(d3.tsv, "daten_2013in2017.txt");
q.defer(d3.tsv, "urbanisierung.txt");
q.awaitAll(function(error)
{
if (!error)
{
gemeinden = arguments[1][0].filter(function(d) { return (d.gkz.slice(-2) != "00" && d.gkz.slice(-2) != "99" && d.gkz.slice(0, 2) != "G9") || (d.gkz == "G90001"); });
urbanisierung = d3.nest().key(function(d) { return "G" + d.gkz; }).object(arguments[1][1]);
gemeinden.forEach(function(d)
{
d.urbanisierung = urbanisierung[d.gkz][0].urbanisierung;
});
wbr.total = +arguments[1][0].filter(function(d) { return d.gkz == "G00000"; })[0].wahlberechtigte;
wbr.stadt = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "1"; }), function(d) { return d.wahlberechtigte; });
wbr.mittel = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "2"; }), function(d) { return d.wahlberechtigte; });
wbr.land = wbr.total - wbr.stadt - wbr.mittel;
//fiktive auszählungsgrade
current.stadt = Math.round(wbr.stadt * Math.random());
current.mittel = Math.round(wbr.mittel * Math.random());
current.land = Math.round(wbr.land * Math.random());
current.total = current.stadt + current.mittel + current.land;
scale.azg.domain([0, wbr.total]);
gueltig.total = +arguments[1][0].filter(function(d) { return d.gkz == "G00000"; })[0].gueltig;
gueltig.stadt = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "1"; }), function(d) { return d.gueltig; });
gueltig.mittel = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "2"; }), function(d) { return d.gueltig; });
gueltig.land = gueltig.total - gueltig.stadt - gueltig.mittel;
for (var i = 0, len = parties.length; i < len; i++)
{
var p = parties[i];
var obj = {};
obj.p = p;
obj.total = d3.sum(gemeinden, function(d) { return +d[p]; }) / gueltig.total;
obj.classes = [];
obj.classes.push(d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "3"; }), function(d) { return d[p]; }) / gueltig.land);
obj.classes.push(d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "2"; }), function(d) { return d[p]; }) / gueltig.mittel);
obj.classes.push(d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "1"; }), function(d) { return d[p]; }) / gueltig.stadt);
results.push(obj);
}
draw();
}
});
function draw()
{
var azgs = ["total", "land", "mittel", "stadt"];
var classes = ["ländlich", "mittel", "städtisch"];
scale.azg_y.domain(azgs);
azg.selectAll(".bg_rect")
.data(azgs)
.enter()
.append("rect")
.attr("x", offset_x)
.attr("y", function(d) { return scale.azg_y(d); })
.attr("width", function(d) { return scale.azg(wbr[d]); })
.attr("height", scale.azg_y.bandwidth())
.attr("class", "bg_rect")
.style("fill", "#ece7f2");
azg.selectAll(".azg_rect")
.data(azgs)
.enter()
.append("rect")
.attr("x", offset_x)
.attr("y", function(d) { return scale.azg_y(d) + 10; })
.attr("width", function(d) { return scale.azg(current[d]); })
.attr("height", scale.azg_y.bandwidth() - 20)
.attr("class", "azg_rect")
.style("fill", "#2b8cbe");
azg.selectAll(".parties")
.data(azgs)
.enter()
.append("text")
.attr("x", 0)
.attr("y", function(d, i) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; })
.attr("dy", "0.35em")
.text(function(d, i) { return ["gesamt"].concat(classes)[i]; });
azg.selectAll(".values")
.data(azgs)
.enter()
.append("text")
.attr("x", function(d) { return scale.azg(wbr[d]) + offset_x + 2; })
.attr("y", function(d, i) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; })
.attr("dy", "0.35em")
.attr("class", "values")
.text(function(d) { return percent.format(",.0%")(current[d] / wbr[d]); });
legend.append("line")
.attr("x1", 60 + scale.classes.bandwidth() * 1.5)
.attr("x2", 60 + scale.classes.bandwidth() * 1.5)
.attr("y1", 15)
.attr("y2", scale.y.bandwidth() + 15)
.style("stroke", color.spoe);
legend.append("text")
.attr("x", 60 + scale.classes.bandwidth() * 1.5)
.attr("y", 12)
.attr("class", "legtext")
.style("text-anchor", "middle")
.text("gesamt");
for (var i = 0; i < 3; i++)
{
legend.append("text")
.attr("x", 0)
.attr("y", scale.classes(i) + scale.classes.bandwidth() / 2 + 15)
.attr("dy", "0.35em")
.attr("class", "legtext")
.text(classes[i]);
legend.append("rect")
.attr("x", 60)
.attr("y", scale.classes(i) + 15)
.attr("width", scale.classes.bandwidth() * 3)
.attr("height", scale.classes.bandwidth())
.style("fill", color.spoe)
.style("fill-opacity", 0.3 + 0.3 * i);
}
var g = svg.selectAll(".gs")
.data(results)
.enter()
.append("g")
.attr("class", "gs")
.attr("transform", function(d) { return "translate(0, " + scale.y(d.p) + ")"; });
g.append("text")
.attr("x", 0)
.attr("y", scale.classes.bandwidth() * 2)
.attr("class", "parties")
.attr("dy", "0.3em")
.text(function(d) { return labels[d.p]; });
//TODO
//Gesamt-Wert = nur Gemeinden, oder inkl. Wahlkarten? Am Wahltag egal?
g.append("line")
.attr("x1", function(d) { return offset_x + scale.result(d.total); })
.attr("x2", function(d) { return offset_x + scale.result(d.total); })
.attr("y1", 0)
.attr("y2", scale.y.bandwidth())
.attr("class", "grid")
.style("stroke", function(d) { return color[d.p]; });
g.selectAll(".bars")
.data(function(d) { return d.classes; })
.enter()
.append("rect")
.attr("x", offset_x)
.attr("y", function(d, i) { return scale.classes(i); })
.attr("width", function(d) { return scale.result(d); })
.attr("height", scale.classes.bandwidth())
.attr("class", "bars")
.style("fill", function(d) { var p = d3.select(this.parentNode).datum().p; return color[p]; })
.style("fill-opacity", function(d, i) { return 0.3 + 0.3 * i; });
g.selectAll(".result")
.data(function(d) { return d.classes; })
.enter()
.append("text")
.attr("x", function(d) { return offset_x + scale.result(d) + 4; })
.attr("y", function(d, i) { return scale.classes(i) + scale.classes.bandwidth() / 2; })
.attr("dy", "0.35em")
.attr("class", "result")
.text(function(d) { return percent.format(",.1%")(d); });
}
function resize()
{
width = parseInt(d3.select("#chart").style("width"), 10) - margin.left - margin.right;
height = window.innerHeight - margin.top - margin.bottom - 40 - parseInt(d3.selectAll(".desc").style("height"), 10);
if (height < 400) height = 400;
scale.result.range([0, width - offset_x]);
scale.y.rangeRound([margin.top, height - margin.bottom]);
scale.classes.rangeRound([0, scale.y.bandwidth()]);
scale.azg.range([0, width - offset_x - 15]);
scale.azg_y.rangeRound([0, 200]).paddingOuter(0).paddingInner(0.1);
d3.select("#svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.select("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
d3.select("#svg_azg")
.attr("width", width + margin.left + margin.right)
.select("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
azg.selectAll(".bg_rect")
.attr("y", function(d) { return scale.azg_y(d); })
.attr("width", function(d) { return scale.azg(wbr[d]); })
.attr("height", scale.azg_y.bandwidth());
azg.selectAll(".azg_rect")
.attr("y", function(d) { return scale.azg_y(d) + 10; })
.attr("width", function(d) { return scale.azg(current[d]); })
.attr("height", scale.azg_y.bandwidth() - 20);
azg.selectAll(".parties")
.attr("y", function(d) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; })
azg.selectAll(".values")
.attr("x", function(d) { return scale.azg(wbr[d]) + offset_x + 2; })
.attr("y", function(d) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; });
var g = svg.selectAll(".gs");
g.attr("transform", function(d) { return "translate(0, " + scale.y(d.p) + ")"; });
g.selectAll(".parties")
.attr("y", scale.classes.bandwidth() * 2);
g.selectAll(".grid")
.attr("x1", function(d) { return offset_x + scale.result(d.total); })
.attr("x2", function(d) { return offset_x + scale.result(d.total); })
.attr("y1", 0)
.attr("y2", scale.y.bandwidth());
g.selectAll(".bars")
.attr("y", function(d, i) { return scale.classes(i); })
.attr("width", function(d) { return scale.result(d); })
.attr("height", scale.classes.bandwidth());
g.selectAll(".result")
.attr("x", function(d) { return offset_x + scale.result(d) + 4; })
.attr("y", function(d, i) { return scale.classes(i) + scale.classes.bandwidth() / 2; });
}
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js