Skip to content

Instantly share code, notes, and snippets.

@pm5
Last active August 29, 2015 14:07
Show Gist options
  • Save pm5/000aa9ceb0506eb1f34f to your computer and use it in GitHub Desktop.
Save pm5/000aa9ceb0506eb1f34f to your computer and use it in GitHub Desktop.
Amount of Confiscated Deposits in Taiwanese Election

Amount of Confiscated Deposits in Taiwanese Election

歷年選舉被沒收的保證金(2004 年~2014 年)

[DAY 18] 延續 DAY 3 「選舉保證金」視覺化,把 2004 年至今各級選舉,因得票率未達法定門檻而遭到沒收的保證金額與人數計算出來。

網址:http://bl.ocks.org/pm5/000aa9ceb0506eb1f34f 資料來源:網址內有列出

註:根據維基百科 http://zh.wikipedia.org/wiki/%E9%81%B8%E8%88%89%E6%8C%89%E9%87%91 ,村里長選舉從 2005 年公職人員選舉罷免法修法後,也需要繳交選舉保證金。 註:中選會網站缺乏 2000 年以前的選舉資料。此外因為資料搜集不易,這張圖也沒有包含各地方政府的選舉資料。歡迎提供資料或 patch。

資料來源

cec_id people_count
20120101A2 109
20120101A1 1
20101101B1 3
20101101B2 69
20101101B3 251
20091201C1 17
20091201C2 30
20080101A2 126
20080301A1 0
20061201B1 7
20061201B2 37
20050501A9 0
20051201C1 24
20051201C2 117
20041201A2 104
20040301A1 0
country position year amount currency reference cec_id
TW 總統 2004 15000000 NTD http://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=D0020053 20040301A1
TW 立法委員 2004 200000 NTD http://web.cec.gov.tw/ezfiles/0/1000/attach/41/20071026214657_961026-2.doc 20041201A2
TW 任務型國大代表 2005 100000 NTD http://web.cec.gov.tw/ezfiles/0/1000/attach/87/20061101172056_a29.doc 20050501A9
TW 縣巿長 2005 200000 NTD 20051201C1
TW 縣巿議員 2005 120000 NTD 20051201C2
TW 直轄巿巿長 2006 2000000 NTD http://web.cec.gov.tw/ezfiles/0/1000/attach/22/20061031175849_n7.doc 20061201B1
TW 直轄巿議員 2006 200000 NTD http://web.cec.gov.tw/ezfiles/0/1000/attach/22/20061031175849_n7.doc 20061201B2
TW 立法委員 2008 200000 NTD http://web.cec.gov.tw/ezfiles/0/1000/attach/41/20071026214657_961026-2.doc 20080101A2
TW 總統 2008 15000000 NTD http://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=D0020053 20080301A1
TW 縣巿長 2009 200000 NTD 20091201C1
TW 縣巿議員 2009 120000 NTD 20091201C2
TW 直轄巿巿長 2010 2000000 NTD http://web.cec.gov.tw/files/15-1000-22840,c4466-1.php 20101101B1
TW 直轄巿議員 2010 200000 NTD http://web.cec.gov.tw/files/15-1000-22840,c4466-1.php 20101101B2
TW 直轄巿里長 2010 50000 NTD http://web.cec.gov.tw/files/15-1000-22840,c4466-1.php 20101101B3
TW 總統 2012 15000000 NTD http://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=D0020053 20120101A1
TW 立法委員 2012 200000 NTD http://web.cec.gov.tw/files/15-1000-14724,c3383-1.php 20120101A2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>選舉中因得票率未達標準不予返還的保證金數目(2004 ~ 2012)</title>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
</head>
<body>
<div id="canvas">
</div>
<script>
function confiscatedChart() {
var margin = { left: 100, top: 50, right: 180, bottom: 30 };
var spacing = 20;
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var xScale = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var yScale = d3.scale.linear()
.range([height, 0]);
var positions = [ "總統", "立法委員", "縣巿長", "縣巿議員", "直轄巿巿長", "直轄巿議員", "直轄巿里長", "任務型國大代表" ];
var color = d3.scale.category20().domain(positions);
var xAxis = d3.svg.axis()
.orient("bottom")
.scale(xScale);
var yAxis = d3.svg.axis()
.orient("left")
.scale(yScale);
var barTip = d3.tip()
.attr("class", "tip")
.offset([-10, 0])
.html(function (d) {
return '<div class="title">' + d.position + '</div><span>' + d.people_count + '人 ' + d.amount + '元</span>';
});
var lineTip = d3.tip()
.attr("class", "tip")
.offset([4, 0])
.html(function (d) {
return '<div class="title">' + d.year + '年</div><span>累計 ' + d.sum + ' 元</span>';
});
var stack = d3.layout.stack()
.values(function (d) { return d.values; })
.x(function (d) { return d.year; })
.y(function (d) { return d.amount; });
function joinData(done) {
d3.csv('deposit.csv', function (depositData) {
d3.csv('confiscated.csv', function (confisData) {
confisData.forEach(function (d) {
confisData[d.cec_id] = d;
});
var data = {};
data.entries = depositData.map(function (d) {
d.amount = +d.amount * +confisData[d.cec_id].people_count;
d.year = +d.year;
d.people_count = +confisData[d.cec_id].people_count;
return d;
}).sort(function (a, b) {
return a.year - b.year;
});
data.yearRange = [
d3.min(data.entries, function (d) { return d.year; }),
d3.max(data.entries, function (d) { return d.year; }) + 1
];
var sum = 0;
data.sum = d3.range(data.yearRange[0], data.yearRange[1]).map(function (year) {
var amount = data.entries
.filter(function (d) { return d.year == year; })
.reduce(function (prev, v) { return prev + v.amount; }, 0);
sum += amount;
return {
year: year,
amount: amount,
prevSum: sum - amount,
sum: sum
};
});
done(data);
});
});
}
function buildLayers(data) {
var layers = [];
positions.forEach(function (pos) {
var values = data.entries.filter(function (d) { return d.position === pos; });
i = 0;
for (var year = data.yearRange[0]; year < data.yearRange[1]; year++) {
if (values[i] === undefined || values[i].year !== year) {
values.splice(i, 0, {
"year": year,
"position": pos,
"amount": 0,
"currency": "NTD"
});
}
++i;
};
layers.push({
"position": pos,
"values": values
});
});
return layers;
}
function drawBarChart(selection, data) {
var layers = stack(buildLayers(data));
var layer = selection.selectAll("g.layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.attr("fill", function (d) { return color(d.position); });
var rect = layer.selectAll("rect.year")
.data(function (d) { return d.values; })
.enter().append("rect")
.attr("class", function (d) { return "year " + d.year; })
.attr("x", function (d) { return xScale(d.year); })
.attr("y", function (d) { return yScale(d.y0 + d.y); })
.attr("width", xScale.rangeBand())
.attr("height", function (d) { return yScale(d.y0) - yScale(d.y0 + d.y); })
.on("mouseover", barTip.show)
.on("mouseout", barTip.hide);
};
function drawLineChart(selection, data) {
var lines = selection.append("g")
.attr("class", "sum");
var sum = data.sum.slice().splice(1);
var line = lines.selectAll("line.sum")
.data(sum)
.enter().append("line")
.attr("x1", function (d) { return xScale(d.year - 1); })
.attr("y1", function (d) { return yScale(d.prevSum); })
.attr("x2", function (d) { return xScale(d.year); })
.attr("y2", function (d) { return yScale(d.sum); })
.attr("transform", "translate(" + (xScale.rangeBand() * 0.5) + ",0)");
var dot = lines.selectAll("g.sum")
.data(data.sum)
.enter().append("g")
.attr("class", "sum")
.attr("transform", "translate(" + (xScale.rangeBand() * 0.5) + ",0)");
dot.append("circle")
.attr("class", "sum")
.attr("cx", function (d) { return xScale(d.year); })
.attr("cy", function (d) { return yScale(d.sum); })
.attr("r", 2);
dot.append("circle")
.attr("class", "track")
.attr("cx", function (d) { return xScale(d.year); })
.attr("cy", function (d) { return yScale(d.sum); })
.attr("r", 16)
.on("mouseover", lineTip.show)
.on("mouseout", lineTip.hide);
};
function drawAxis(selection) {
selection.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height +")")
.call(xAxis)
.append("text")
.attr("transform", "translate(" + width + ",16)")
.style("text-anchor", "middle")
.text("年");
selection.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.text("金額")
.attr("transform", "translate(-8,4)")
.style("text-anchor", "end");
}
function draw(selection) {
var svg = selection.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 + ")")
.call(barTip)
.call(lineTip);
joinData(function (data) {
console.log(data);
xScale.domain(d3.range(data.yearRange[0], data.yearRange[1]));
yScale.domain([0, d3.max(data.sum, function (d) { return d.sum; }) * 1.1]);
drawBarChart(svg, data);
drawLineChart(svg, data);
drawAxis(svg);
});
return draw;
}
draw.width = function (value) {
if (!arguments.length) { return width; }
width = value;
return draw;
};
draw.height = function (value) {
if (!arguments.length) { return height; }
height = value;
return draw;
};
draw.margin = function (value) {
if (!arguments.length) { return margin; }
margin = value;
return draw;
}
draw.legend = function (selection) {
var legend = selection.append("div")
.attr("id", "legend")
.attr("style", "bottom: " + margin.bottom + "px; right: " + spacing + "px; width: " + (margin.right - margin.left * 3) + "px;");
legend.selectAll("div")
.data(positions)
.enter().append("div")
.attr("style", function (d) { return "background-color: " + color(d) + "; padding: 5px;"; })
.text(function (d) { return d; });
return draw;
};
draw.caption = function (selection) {
var caption = selection.append("div")
.text("歷年選舉被沒收的保證金(2004 年~2014 年)")
.attr("class", "caption")
.attr("style", "position: absolute; top: " + spacing + "px; left: " + (width / 2) + "px;");
};
return draw;
}
var chart = confiscatedChart();
d3.select("#canvas")
.call(chart)
.call(chart.legend)
.call(chart.caption);
</script>
<style>
body {
margin: 0;
padding: 0;
}
#canvas {
position: relative;
width: 960px;
height: 500px;
}
#canvas rect {
shape-rendering: crispEdges;
}
#canvas rect:hover {
fill: rgba(0, 0, 0, 0.5);
}
#legend {
position: absolute;
}
#canvas .sum line {
stroke: #000;
stroke-width: 1;
}
#canvas .sum circle.sum {
stroke: #000;
stroke-width: 1;
fill: #fff;
}
#canvas .sum circle.track {
fill-opacity: 0;
stroke-opacity: 0;
}
#canvas .axis text {
font: 10px sans-serif;
}
#canvas .axis path,
#canvas .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.tip {
line-height: 1;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
font: 10px sans-serif;
}
.tip .title {
font-weight: bold;
font: 12px sans-serif;
}
.tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
.tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment