#第23回参議院議員通常選挙(2013) 比例代表結果
非拘束名簿式比例代表制(改選定数48)の結果です。
データソース -総務省 第23回参議院議員通常選挙結果調
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font: 11px sans-serif;
font-weight: bold;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.y.axis text {
font-weight: normal;
}
.x.axis path, .x.axis line {
display: none;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
</style>
<body>
<form>
<label><input type="radio" name="mode" value="parties">党派別得票数</label>
<label><input type="radio" name="mode" value="candidates" checked>名簿登載者別得票数</label>
<label><input type="radio" name="mode" value="winners">当選人数</label>
</form>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>
<script src="https://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 80};
var width = 860;
var height = 550;
var svg = d3.select('body')
.append('svg')
.attrs({
"width": width + margin.left + margin.right,
"height": height + margin.top + margin.bottom,
})
.append('g')
.attr('transform', 'translate('+margin.left+','+margin.top+')');
var x = d3.scaleBand()
.rangeRound([0, width])
.padding(.1);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var color = d3.scaleOrdinal(d3.schemeCategory20.reverse());
var partyColor = d3.scaleOrdinal(d3.schemeCategory10);
var quotient = function(d) { return d.total / d.denominator; };
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var partyKey = '政党';
var candidateKey = '名簿登録者';
var votesKey = '得票数';
var partyVotes;
var winners;
var pickTimer;
d3.csv('result.csv', function(error, data){
if (error) { throw error; }
data.forEach(function(d){
d.party = d[partyKey];
d.candidate = d[candidateKey];
d.votes = +d[votesKey];
});
var partyData = d3.nest()
.key(function(d){ return d.party; })
.key(function(d){ return d.candidate; })
// .sortKeys(function (a, b) { return d3.descending(a['得票数'], b['得票数']); })
// .rollup(function(d) { return +d[votesKey]; })
.entries(data);
// .map(data);
// var domain = d3.keys(data[0]).filter(function(d){return d !== partyKey});
partyData.forEach(function(d){
var y0 = 0;
d.values.sort(function(a,b){ return b.values[0].votes - a.values[0].votes; });
var candidates = d.values.map(function(v){
return {
party: d.key,
name: v.key,
votes: v.values[0].votes,
y0: y0,
y1: y0 += v.values[0].votes,
};
});
// candidates.sort(function(a,b){ return b.votes - a.votes; });
console.log(candidates);
d.candidates = candidates;
d.winners = [];
d.total = d3.sum(candidates, function(c){return c.votes;});
d.denominator = 1;
});
partyData.sort(function(a,b){ return b.total - a.total; });
partyData.forEach(function(d){
if (d.key.length > 6) {
d.key = d.key.substr(0, 3);
}
});
x.domain(partyData.map(function(d) { return d.key; }));
y.domain([0, d3.max(partyData.map(function(d){return d.total;}))]);
console.log(data);
console.log(partyData);
// console.log(d3.entries(partyData));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("x", "-2em")
.attr("y", y(y.ticks(10).pop()))
.attr("dy", "-2em")
.attr("text-anchor", "end")
.attr("fill", "#000")
.text(votesKey);
var g = svg.selectAll('.party')
.data(partyData)
.enter()
.append('g')
.attrs({
class: function(d){ return 'party ' + d.key; },
transform: function(d,i) { return 'translate('+ x(d.key) +', 0)' },
});
g.selectAll('.votes')
.data(function(d){ return d.candidates; })
.enter()
.append('rect')
.attrs({
class: 'votes',
x: 0,
y: function(d){ return y(d.y1); },
width: x.bandwidth(),
height: function(d){ return y(d.y0) - y(d.y1); },
fill: function(d){ return color(d.name); },
opacity: 1,
});
partyVotes = g.selectAll('.party-votes')
.data(function(d){ return [{
name: d.key,
total: d.total,
denominator: d.denominator,
}]; })
.enter()
.append('rect')
.attrs({
class: 'party-votes',
x: 0,
y: function(d){ return y(quotient(d)); },
width: 0,
height: function(d){ return y(0) - y(quotient(d)); },
fill: function(d){ return partyColor(d.name); },
});
});
function getFirstPartyVotes() {
var maxVotes = 0;
var firstParty;
partyVotes.nodes().forEach(function(d){
var party = d3.select(d);
if (quotient(party.data()[0]) > maxVotes) {
firstParty = party;
maxVotes = quotient(party.data()[0]);
}
});
// console.log(firstParty, maxVotes);
return firstParty;
}
function pickWinner() {
var numWinner = d3.selectAll('.winners').nodes().length;
if (numWinner >= 48) {
return;
}
// var q = d3.queue();
var firstPartyVotes = getFirstPartyVotes();
var party = d3.select(firstPartyVotes.node().parentNode);
var data = party.data()[0];
data.winners.push({
name: data.key,
votes: quotient(data),
order: numWinner+1,
});
var padding = 4;
var size = x.bandwidth() / 2 - padding * 2;
var winners = party.selectAll('.winners')
.data(function(d) {return d.winners; })
.enter()
.append('circle')
.attrs({
class: 'winners',
cx: function(d, i) { return padding + ((i % 2) + .5) * (size + padding); },
cy: function(d, i) { return padding + (Math.floor(i / 2) + .5) * (size + padding); },
r: 0,
stroke: '#fff',
'stroke-width': 2,
fill: function(d) { return partyColor(d.name); },
});
var timer = setTimeout(function(){
party.selectAll('.winners-order')
.data(function(d) {return d.winners; })
.enter()
.append('text')
.attrs({
class: 'winners-order',
x: function(d, i) { return padding + ((i % 2)+.5) * (size + padding); },
y: function(d, i) { return padding + (Math.floor(i / 2)+.6) * (size + padding); },
'text-anchor': 'middle',
'font-weight': 'bold',
fill: '#fff',
})
.text(function(d,i){return d.order;});
}, 250);
data.denominator++;
partyVotes
.data(function(d){ return [{
name: d.key,
total: d.total,
denominator: d.denominator,
}]; })
.transition()
.duration(250)
.attrs({
y: function(d){ return y(quotient(d)); },
height: function(d){ return y(0) - y(quotient(d)); },
});
winners
.transition()
.duration(250)
.attrs({
r: size / 2,
});
pickTimer = setTimeout(function(){
pickWinner();
}, 400);
}
d3.selectAll("input").on("change", change);
function change() {
removeWinners();
switch(this.value) {
case 'parties':
transitionParties();
break;
case 'candidates':
transitionCandidates();
break;
case 'winners':
transitionParties();
setTimeout(function(){
pickWinner();
}, 1000);
break;
}
}
function removeWinners() {
clearTimeout(pickTimer);
d3.selectAll('.party').data().forEach(function(d){
d.denominator = 1;
});
svg.selectAll('.party').data().forEach(function(d){
d.winners = [];
});
var winners = svg.selectAll('.winners, .winners-order')
.data([]);
winners.exit().remove();
}
function transitionParties(callback) {
svg.selectAll('.votes')
.transition()
.duration(1000)
.attrs({
fill: function(d){ return d3.hsl(partyColor(d.party)).brighter(); },
// fill: '#f0f0f0',
});
// svg.selectAll('.party-votes')
partyVotes
.data(function(d){ return [{
name: d.key,
total: d.total,
denominator: d.denominator,
}]; })
.transition()
.duration(1000)
.attrs({
width: x.bandwidth(),
y: function(d){ return y(quotient(d)); },
height: function(d){ return y(0) - y(quotient(d)); },
});
// .call(endall, callback);
}
function transitionCandidates() {
removeWinners();
svg.selectAll('.votes')
.transition()
.duration(1000)
.attrs({
fill: function(d){ return color(d.name); },
});
svg.selectAll('.party-votes')
.transition()
.duration(1000)
.attrs({
width: 0,
});
}
function endall(transition, callback) {
if (!callback) callback = function(){};
if (transition.size() === 0) { callback() }
var n = 0;
transition
.each(function() { ++n; })
.each("end", function() { if (!--n) callback.apply(this, arguments); });
}
d3.select(self.frameElement).style("height", height + margin.top + margin.bottom + "px");
</script>
</body>
</html>
Modified http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js to a secure url
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-selection-multi.v0.4.min.js
https://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js