Skip to content

Instantly share code, notes, and snippets.

@sugi2000
Last active August 29, 2015 14:19
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 sugi2000/44ba4882404d8c0be4a2 to your computer and use it in GitHub Desktop.
Save sugi2000/44ba4882404d8c0be4a2 to your computer and use it in GitHub Desktop.
2015-04-12 Hokkaido Gubernatorial Election

2015年4月12日執行の北海道知事選挙の市区町村ごとの得票状況です。

市区町村の色分け
全道の得票率を基準に、高橋候補の得票率が高い地域をオレンジ、佐藤候補の得票率が高い地域をグリーンにしています。

棒グラフの見方
オレンジ・グリーンの帯の高さが投票率です。つまり、グレーの面積が大きいほど棄権者数の比率が高いことをあらわしています。

Source:北海道選挙管理委員会

市区町村 高橋はるみ 佐藤のりゆき 有権者数 投票率
中央区 60117 44737 189045 0.5619
北区 73777 59961 229670 0.5879
東区 66299 51877 212078 0.5627
白石区 52209 41217 174922 0.5394
厚別区 36244 31017 107259 0.6333
豊平区 57866 44365 181571 0.5691
清田区 32403 25653 92748 0.6314
南区 43650 32609 118767 0.6489
西区 59049 46382 175913 0.6055
手稲区 38455 32682 115540 0.6213
札幌市 520069 410500 1597513 0.5885
函館市 64014 59641 226349 0.5503
小樽市 32033 29032 106037 0.5809
旭川市 80891 71463 287074 0.5340
室蘭市 22925 21262 74717 0.5969
釧路市 46055 34549 147047 0.5522
帯広市 44024 34483 136736 0.5792
北見市 34555 25730 100398 0.6046
夕張市 3170 2343 8409 0.6624
岩見沢市 21957 18251 71481 0.5660
網走市 11644 8101 30448 0.6537
留萌市 7957 5169 19106 0.6921
苫小牧市 43555 32392 140555 0.5441
稚内市 10796 6726 30354 0.5811
美唄市 7821 4714 20544 0.6139
芦別市 5246 3827 13364 0.6832
江別市 29625 26772 97859 0.5803
赤平市 3422 2802 9892 0.6335
紋別市 7463 4950 19594 0.6392
士別市 6235 4736 17298 0.6370
名寄市 9194 5919 23658 0.6431
三笠市 2926 2363 8270 0.6453
根室市 7666 4658 23060 0.5391
千歳市 27920 14758 74844 0.5746
滝川市 11770 8889 34436 0.6034
砂川市 5313 4772 15130 0.6721
歌志内市 1300 1056 3410 0.6978
深川市 6024 5309 18869 0.6046
富良野市 6766 4561 18798 0.6056
登別市 11811 10952 41678 0.5495
恵庭市 20198 12170 54884 0.5937
伊達市 8799 7774 29674 0.5634
北広島市 15670 14219 48371 0.6227
石狩市 14603 12760 48238 0.5706
北斗市 12013 9358 38338 0.5622
市 計 1165430 926961 3636433 0.5803
南幌町 2554 1756 6814 0.6360
奈井江町 1936 1421 4938 0.6825
上砂川町 1027 979 3053 0.6649
由仁町 2251 1487 4760 0.7923
長沼町 3979 2210 9596 0.6510
栗山町 3989 2786 10574 0.6446
月形町 1351 803 3073 0.7120
浦臼町 728 463 1764 0.6778
新十津川町 2743 1490 5765 0.7368
妹背牛町 1236 731 2785 0.7112
秩父別町 1018 615 2222 0.7377
雨竜町 1100 607 2221 0.7732
北竜町 775 563 1738 0.7723
沼田町 1329 961 2854 0.8063
空知総合振興局 計 26016 16872 62157 0.6947
当別町 5910 3461 14334 0.6589
新篠津村 1385 527 2761 0.6961
石狩振興局 計 7295 3988 17095 0.6649
島牧村 640 334 1422 0.6894
寿都町 1021 659 2707 0.6254
黒松内町 1118 682 2511 0.7226
蘭越町 1814 1334 4172 0.7595
ニセコ町 1375 1295 3855 0.6961
真狩村 855 526 1801 0.7729
留寿都村 655 360 1501 0.6778
喜茂別町 833 570 2011 0.7031
京極町 1321 658 2627 0.7583
倶知安町 4751 3248 11945 0.6733
共和町 2373 1060 5106 0.6741
岩内町 4920 2192 11458 0.6230
泊村 905 245 1472 0.7860
神恵内村 531 153 822 0.8337
積丹町 871 448 2026 0.6560
古平町 1263 585 3004 0.6172
仁木町 1161 821 2953 0.6783
余市町 4953 4222 16824 0.5479
赤井川村 416 260 909 0.7481
後志総合振興局 計 31776 19652 79126 0.6535
豊浦町 1291 823 3589 0.5958
壮瞥町 813 569 2215 0.6282
白老町 5195 3708 15675 0.5736
厚真町 1859 1038 3948 0.7368
洞爺湖町 2897 2123 8087 0.6248
安平町 2436 1947 7070 0.6257
むかわ町 2909 2003 7466 0.6604
胆振総合振興局 計 17400 12211 48050 0.6209
日高町 3856 2492 10521 0.6083
平取町 1908 1293 4389 0.7342
新冠町 1898 1156 4622 0.6657
浦河町 3963 3246 10747 0.6739
様似町 1697 1126 3999 0.7099
えりも町 1931 997 4124 0.7153
新ひだか町 6767 5189 19702 0.6111
日高振興局 計 22020 15499 58104 0.6501
松前町 3005 1359 7214 0.6056
福島町 1676 796 4067 0.6101
知内町 1653 773 3991 0.6108
木古内町 1692 1017 4106 0.6620
七飯町 7184 6558 23597 0.5846
鹿部町 1261 733 3512 0.5699
森町 4927 3223 13927 0.5886
八雲町 4884 3708 14635 0.5906
長万部町 2061 1463 4861 0.7282
渡島総合振興局 計 28343 19630 79910 0.6030
江差町 2705 2003 7058 0.6728
上ノ国町 2113 1160 4586 0.7214
厚沢部町 1805 886 3606 0.7511
乙部町 1632 956 3429 0.7592
奥尻町 1351 529 2474 0.7676
今金町 2242 1427 4798 0.7680
せたな町 4233 1888 7548 0.8176
檜山振興局 計 16081 8849 33499 0.7500
鷹栖町 1913 1579 5796 0.6092
東神楽町 2527 2251 7925 0.6061
当麻町 1987 1600 5727 0.6303
比布町 1215 1026 3368 0.6658
愛別町 1242 695 2637 0.7351
上川町 1135 1141 3386 0.6784
東川町 1962 1845 6340 0.6032
美瑛町 3205 2429 8836 0.6416
上富良野町 3904 1900 9069 0.6428
中富良野町 1901 1009 4256 0.6877
南富良野町 926 675 2214 0.7448
占冠村 313 376 948 0.7310
和寒町 1536 906 3130 0.7819
剣淵町 1102 901 2819 0.7209
下川町 1310 913 2956 0.7579
美深町 1723 1196 3980 0.7389
音威子府村 207 296 600 0.8403
中川町 719 407 1452 0.7782
幌加内町 697 350 1293 0.8105
上川総合振興局 計 29524 21495 76732 0.6693
増毛町 1887 1168 4135 0.7429
小平町 1499 841 2853 0.8321
苫前町 1484 781 2845 0.8011
羽幌町 2879 1865 6380 0.7469
初山別村 622 301 1085 0.8512
遠別町 1268 657 2417 0.8007
天塩町 1476 737 2740 0.8126
留萌振興局 計 11115 6350 22455 0.7827
猿払村 1060 556 2135 0.7653
浜頓別町 1412 921 3196 0.7406
中頓別町 731 492 1606 0.7634
枝幸町 3102 1585 7107 0.6638
豊富町 1422 965 3444 0.6981
礼文町 1281 482 2303 0.7677
利尻町 1143 446 1912 0.8447
利尻富士町 1403 524 2281 0.8571
幌延町 1066 393 1996 0.7361
宗谷総合振興局 計 12620 6364 25980 0.7373
美幌町 6865 3938 17144 0.6331
津別町 1546 1180 4472 0.6135
斜里町 3857 2541 9938 0.6474
清里町 1582 1167 3611 0.7699
小清水町 1638 1162 4308 0.6529
訓子府町 1722 1172 4374 0.6663
置戸町 1071 869 2668 0.7309
佐呂間町 2079 1098 4582 0.6948
遠軽町 6935 5079 17502 0.6911
湧別町 3726 1930 7847 0.7259
滝上町 1106 856 2415 0.8177
興部町 1600 864 3302 0.7496
西興部村 538 249 958 0.8340
雄武町 1691 827 3822 0.6609
大空町 2434 1561 6277 0.6395
オホーツク総合振興局 計 38390 24493 93220 0.6785
音更町 11700 9790 35698 0.6059
士幌町 2173 1442 5126 0.7089
上士幌町 1492 1265 4068 0.6815
鹿追町 2057 1190 4409 0.7460
新得町 2043 1831 5317 0.7371
清水町 3167 2235 8198 0.6641
芽室町 5784 3953 15029 0.6519
中札内村 1360 998 3207 0.7437
更別村 1299 785 2657 0.7852
大樹町 2344 1155 4763 0.7375
広尾町 2650 1502 6152 0.6794
幕別町 7688 6823 22272 0.6545
池田町 2021 2043 6131 0.6675
豊頃町 1290 882 2833 0.7725
本別町 2463 2103 6379 0.7199
足寄町 2289 2232 6061 0.7498
陸別町 956 778 2171 0.8056
浦幌町 1959 1240 4432 0.7262
十勝総合振興局 計 54735 42247 144903 0.6736
釧路町 5448 3607 16381 0.5551
厚岸町 3820 1799 8306 0.6809
浜中町 2341 1275 5123 0.7088
標茶町 2565 1955 6530 0.6961
弟子屈町 2504 1860 6568 0.6692
鶴居村 983 553 2014 0.7655
白糠町 2891 1815 7293 0.6498
釧路総合振興局 計 20552 12864 52215 0.6435
別海町 5350 2913 12335 0.6736
中標津町 6327 4224 18948 0.5593
標津町 2048 1071 4373 0.7162
羅臼町 1893 890 4575 0.6118
根室振興局 計 15618 9098 40231 0.6174
町 村 計 331485 219612 833677 0.6652
合計 1496915 1146573 4470110 0.5962
<!DOCTYPE html>
<meta charset="utf-8">
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
<!--
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="crossfilter.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.min.js"></script>
<style src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.css" />
-->
<style type="text/css">
.label {
fill: #333;
font-size: 9px;
text-anchor: middle;
}
svg text.legend, text.area-desc, text.legend-choson {
font-size: 14px;
font-weight: bold;
}
svg text.result {
font-size: 11px;
fill: #fff;
}
svg text.bar-label {
font-size: 11px;
fill: #f00;
}
svg path.map-path {
stroke: #fff;
stroke-width: 1px;
}
svg text::selection { background: none; }
</style>
<body>
<script>
var width = 960,
height = 640;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
//.append("g");
var g = svg.append("g");
//var mapfilepath = 'hokkaido.topojson';
var mapfilepath = '/sugi2000/raw/0c17316fee7dba5f7187/hokkaido.topojson';
var csvpath = 'hokkaido.csv';
var hokkaido;
var votes = [];
var candidates = [];
var results = [];
var candidateColors = d3.scale.ordinal().range(["hsla(30, 90%, 50%, 0.8)", "hsla(160, 90%, 40%, 0.8)"]);
var resultSizes = [];
for (var i = 0; i < results.length; i++) {
resultSizes.push(Math.sqrt(results[i]) * 0.2);
}
var zoom = d3.behavior.zoom()
.scaleExtent([1, 8])
.on("zoom", zoomed);
svg.call(zoom)
.call(zoom.event);
var color = d3.scale.ordinal()
.range(['hsla(0, 70%, 50%, 1.0)', 'hsla(210, 70%, 50%, 1.0)', 'hsla(60, 70%, 50%, 1.0)', 'hsla(90, 0%, 50%, 1.0)']);
g.selectAll('circle.legend')
.data(candidates)
.enter()
.append('circle')
.attr('class', 'legend')
.attr('cx', 100)
.attr('cy', function(d,i) {
var margin = 100;
for (var j = 0; j < i; j++) {
margin += resultSizes[j];
}
return margin;
})
.attr('r', function(d,i) { return resultSizes[i] / 2; })
.style('fill', function(d) { return color(d); });
var areaColors = ['hsla(30, 70%, 90%, 1.0)', 'hsla(160, 70%, 90%, 1.0)'];
var threshold = 0.5662651012601533;
var alpha = d3.scale.linear()
.domain([0.0, 0.3, threshold, 0.7, 1.0])
.range([1.0, 1.0, 0.2, 1.0, 1.0]);
var areaColor = function(d) {
var total = +d.properties[candidates[0]] + +d.properties[candidates[1]];
var ratio = +d.properties[candidates[0]] / total;
if (ratio >= threshold) {
return 'hsla(30, 100%, 50%, ' + alpha(ratio).toFixed(1) + ')';
} else {
return 'hsla(160, 100%, 40%, ' + alpha(ratio).toFixed(1) + ')';
}
}
queue(1)
.defer(d3.json, mapfilepath)
.defer(d3.csv, csvpath)
.await(ready);
function ready(error, map, rows) {
if (error) {
return console.warn(error);
}
renderMap(map);
renderRows(rows);
updateMap(candidates[0]);
}
function initCandidates(rows) {
// init candidates and results
for (key in rows[rows.length-1]) {
if (key !== '市区町村' && key !== '有権者数' && key !== '投票率') {
candidates.push(key);
}
}
results = rows;
candidateColors.domain(d3.keys(results[0]).filter(function(key) { return (key !== "市区町村" && key !== '有権者数' && key !== '投票率'); }));
results.forEach(function(d) {
var y0 = 0;
d.entries = candidateColors.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name], votes: +d[name]}; });
d.entries.forEach(function(d) { d.y0 /= y0; d.y1 /= y0; });
});
bardata = results[results.length - 1].entries;
var x = d3.scale.linear().rangeRound([0, width]);
var g2 = svg.append('g')
.attr('class', 'legend');
g2.append('rect')
.attr('class', 'total')
.attr('x', 0 )
.attr('y', 0)
.attr('height', 50)
.attr('width', width)
.style('fill', 'hsla(0, 0%, 0%, 0.2)');
g2.selectAll('rect.result')
.data(bardata)
.enter()
.append('rect')
.attr('class', 'result')
.attr('x', function(d) { return x(d.y0);} )
.attr('y', 25)
.attr('height', 50 - 25)
.attr('width', function(d) { return x(d.y1 - d.y0);})
.style('fill', function(d) { return candidateColors(d.name); });
g2.append('line')
.attr('class','split')
.attr('x1', width / 2)
.attr('y1', 0)
.attr('x2', width / 2)
.attr('y2', 50)
.style('stroke', 'white')
.style('stroke-width', 1);
g2.append('line')
.attr('class','split-ex')
.attr('x1', width / 2)
.attr('y1', 50)
.attr('x2', width / 2)
.attr('y2', 55)
.style('stroke', 'red')
.style('stroke-width', 1);
g2.append('text')
.attr('class', 'bar-label')
.attr('x', width / 2)
.attr('y', 65)
.style('text-anchor', 'middle')
.text('50%');
g2.selectAll('text.legend')
.data(candidates)
.enter()
.append('text')
.attr('class', 'legend')
.attr('x', function(d, i) { return (i === 0) ? 20 : width - 20;})
.attr('y', 25)
.style('text-anchor', function(d, i){ return (i === 0) ? 'start' : 'end';})
.text(function(d){ return d;});
g2.append('text')
.attr('class', 'legend-choson')
.attr('x', width / 2)
.attr('y', 15)
.style('text-anchor', 'middle')
.text('合計');
g2.selectAll('text.result')
.data(bardata)
.enter()
.append('text')
.attr('class', 'result')
.attr('x', function(d, i) { return (i === 0) ? 20 : width - 20;})
.attr('y', 40)
.style('text-anchor', function(d, i){ return (i === 0) ? 'start' : 'end';})
.text(function(d){ return d.votes.toLocaleString() + '票';});
updateBarChart(rows.length-1);
}
function updateBarChart(index) {
var x = d3.scale.linear().rangeRound([0, width]);
bardata = results[index].entries;
var g2 = d3.select('g.legend');
d3.select('text.legend-choson')
.text(function(d) { return results[index]['市区町村'].replace(/(.+)区$/, '札幌市$1区')
+ '(投票率:' + (results[index]['投票率'] * 100).toFixed(2) + '%)'; });
g2.selectAll('rect.result')
.data(bardata)
.transition()
.duration(300)
.attr('y', function(d) {
return 50 - results[index]['投票率'] * 50;
})
.attr('height', function(d) {
return results[index]['投票率'] * 50;
})
.attr('x', function(d) { return x(d.y0);} )
.attr('width', function(d) { return x(d.y1 - d.y0);});
g2.selectAll('text.result')
.data(bardata)
.text(function(d){ return d.votes.toLocaleString() + '票';});
g2.selectAll('line.split')
.transition()
.duration(300)
.attr('y1', 50 - results[index]['投票率'] * 50);
g2.selectAll('line.split-ex')
.transition()
.duration(300)
.attr('x1', x(bardata[0].y1))
.attr('x2', x(bardata[0].y1));
g2.selectAll('text.bar-label')
.transition()
.duration(300)
.attr('x', x(bardata[0].y1))
.text((bardata[0].y1 * 100).toFixed(2) + '%');
}
function renderMap(map) {
// setup map
hokkaido = topojson.feature(map, map.objects.hokkaido).features;
updateMap(hokkaido);
}
function updateMap(candidate) {
var projection = d3.geo.mercator()
.center([142.5,43.6])
.scale(6000)
//.center(d3.geo.centroid(hokkaido))
.translate([width / 2, height / 2]);
var path = d3.geo.path().projection(projection);
var update = g.selectAll('path.map-path').data(hokkaido);
var enter = update.enter();
for (var i = 0; i < candidates.length; i++) {
update.attr('candidate-' + (i+1), function(d){
return d.properties[candidates[i]];
});
}
enter
.append('path')
.filter(function(d){
return (d.properties.SIKUCHOSON === null);
})
.attr('class', 'map-path-disabled')
.attr('d', path)
.style('fill', '#eee');
enter
.append('path')
.filter(function(d){
return (d.properties.SIKUCHOSON !== null);
})
.attr('class', 'map-path')
.attr('d', path)
.attr('vector-effect', 'non-scaling-stroke')
.attr('JCODE', function(d) {return d.properties.JCODE;})
.attr('KENCODE', function(d) {
if (d.properties.JCODE) {
return d.properties.JCODE.substr(0, 2);
} else {
return 'null';
}
})
.attr('shikuchoson', function(d) {
return d.properties.SIKUCHOSON;
})
.style('fill', '#eee')
.style('cursor', 'pointer')
/*.on('mouseup', function(){
var self = d3.select(this);
//alert(self.attr('shikuchoson'));
var index = searchIndex(results, '市区町村', self.attr('shikuchoson'));
updateBarChart(index);
})*/
.on('mouseover', function(){
var self = d3.select(this);
self.moveToFront()
.style('fill', '#fff')
.style('stroke', '#f00');
//d3.select('text.label-' + self.attr('JCODE')).attr('visibility', 'visible');
var index = searchIndex(results, '市区町村', self.attr('shikuchoson'));
updateBarChart(index);
})
.on('mouseout', function(){
var self = d3.select(this);
self.transition()
//.duration(300)
.style('fill', function(d) {
return areaColor(d);
})
.style('stroke', '#fff');
updateBarChart(results.length - 1);
})
;
update
.transition()
.duration(300)
.style('fill', function(d) {
return areaColor(d);
});
var centroids = [];
for (var i = 0; i < hokkaido.length; i++) {
centroids.push(path.centroid(hokkaido[i]));
}
//console.log(centroids);
g.selectAll('text.label')
.data(hokkaido)
.enter()
.append('text')
.attr('class', function(d) { return 'label label-' + d.properties.JCODE; })
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr('dy', function(d) {
return '.35em';
})
.attr('pointer-events', 'none')
.attr('visibility', 'hidden')
.text(function(d) { return d.properties.SIKUCHOSON; });
/*
for (var i = 0; i < votes.length; i++) {
var entries = d3.entries(votes[i]);
entries.shift(); // remove first town-name
//console.log(entries);
var totalVotes = 0;
for (var j = 0; j < entries.length; j++) {
totalVotes += +entries[j].value;
}
var radius = Math.sqrt(totalVotes) * 0.125;
var arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius * 0.5);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return +d.value; });
var garc = g.selectAll('g.arc-' + i)
.data(pie(entries))
.enter()
.append('g')
.attr('class', function(d) { return "arc arc-" + i; })
.attr("transform", 'translate(' + centroids[i] + ')');
garc.append('path')
.attr('d', arc)
.style('fill', function(d) { return candidateColors(+d.value); });
}
*/
}
function searchIndex (rows, key, value) {
var index = -1;
for (var i = 0; i < rows.length; i++) {
if (rows[i][key] === value) {
index = i;
break;
}
}
return index;
}
function renderRows(rows) {
initCandidates(rows);
// add properties
for (var i = 0; i < hokkaido.length; i++) {
var choson = hokkaido[i].properties.SIKUCHOSON;
var index = searchIndex(rows, '市区町村', choson);
if (index >= 0) {
for (var j = 0; j < candidates.length; j++) {
hokkaido[i].properties[candidates[j]] = rows[index][candidates[j]];
}
votes.push(rows[index]);
}
}
for (var i = 0; i < results.length; i++) {
var vote = results[i];
var totalVote = 0;
for (var j = 0; j < candidates.length; j++) {
totalVote += +vote[candidates[j]];
}
//vote['投票率'] = totalVote / vote['有権者数'];
vote['棄権者数'] = vote['有権者数'] - totalVote;
}
updateBarChart(results.length -1);
}
function zoomed() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
d3.select(self.frameElement).style("height", height + "px");
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment