Based on answers from http://VolebnaKalkulacka.sk using Weighted PCA method as described here: https://gist.github.com/michalskop/8514867
Cutting lines with loss function 0 (no errors, perfect cut) are shown.
Based on answers from http://VolebnaKalkulacka.sk using Weighted PCA method as described here: https://gist.github.com/michalskop/8514867
Cutting lines with loss function 0 (no errors, perfect cut) are shown.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| body { | |
| font: 12px sans-serif; | |
| } | |
| .point { | |
| fill: #1F77B4; | |
| stroke: #1F77B4; | |
| fill-opacity: .3; | |
| stroke-width: 1.5px; | |
| stroke-opacity: 1; | |
| } | |
| g.active .point { | |
| fill-opacity: .9; | |
| } | |
| g.active .name { | |
| font-weight: bold; | |
| } | |
| .line-text { | |
| font: 10px sans-serif; | |
| } | |
| g.active .line-text { | |
| font-weight: bold; | |
| cursor: default; | |
| } | |
| g.active line { | |
| stroke-width: 4 | |
| } | |
| .name { | |
| fill: blue; | |
| font-family: sans-serif; | |
| cursor: default; | |
| } | |
| line { | |
| stroke:gray; | |
| stroke-width:2; | |
| opacity: .15; | |
| } | |
| .quality-1 line { | |
| stroke-dasharray:10,10 | |
| } | |
| .area { | |
| visibility: hidden; | |
| } | |
| g.active .area { | |
| opacity: .15; | |
| visibility: visible; | |
| } | |
| g.active .yes { | |
| fill: green; | |
| } | |
| g.active .no { | |
| fill: red; | |
| } | |
| g.yes circle { | |
| stroke: green; | |
| } | |
| g.no circle { | |
| stroke: red; | |
| } | |
| </style> | |
| <div id="chart"></div> | |
| <script src="http://d3js.org/d3.v3.js"></script> | |
| <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> | |
| <script> | |
| var margin = {top: 20, right: 30, bottom: 30, left: 30}, | |
| width = 500 - margin.left - margin.right, | |
| height = 500 - margin.top - margin.bottom; | |
| var x = d3.scale.linear() | |
| .range([0, width]) | |
| .domain([-2.5,2.5]); | |
| var y = d3.scale.linear() | |
| .range([height, 0]) | |
| .domain([-2.5,2.5]); | |
| var xAxis = d3.svg.axis() | |
| .scale(x) | |
| .orient("bottom"); | |
| var yAxis = d3.svg.axis() | |
| .scale(y) | |
| .orient("left"); | |
| var svg = d3.select("#chart").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 + ")"); | |
| d3.csv("wpca_candidates.csv", function(error, data) { | |
| limits = {"x": [-2.5,2.5],"y": [-2.5,2.5]}; | |
| lines = [{ | |
| 'a':0, | |
| 'b':-1.06, | |
| 'd1':-2.053, | |
| 'd2':-1.93, | |
| 'id': 1, | |
| 'description':'Možnosť vyhlásiť amnestiu'}, | |
| { | |
| 'a': 0.145, | |
| 'b': -0.177, | |
| 'd1':0.37, | |
| 'd2':2.07, | |
| 'description':'Imunita prezidenta'}, | |
| { | |
| 'a': 0.335, | |
| 'b': 2.7665358349, | |
| 'd1': 1.54, | |
| 'd2': -0.56, | |
| 'description':'Zákaz interupcií'}, | |
| { | |
| 'a': -1.019, | |
| 'b': 2.142, | |
| 'd1':-2.1, | |
| 'd2':0.98, | |
| 'description':'Registrované partnerstvo'}, | |
| { | |
| 'a': 3.99, | |
| 'b': -2.87, | |
| 'd1':-0.85, | |
| 'd2':-0.3, | |
| 'description':'Kotleba pozývaný ako iní župani'}, | |
| { | |
| 'a': -0.27, | |
| 'b': -0.21, | |
| 'd1':0.33, | |
| 'd2':1.6, | |
| 'description':'Obch. vzťahy x ľudská práva'}, | |
| { | |
| 'a': 2.6613760408, | |
| 'b': -2.5781557199, | |
| 'd1':-0.16, | |
| 'd2':-0.06, | |
| 'description':'Rómčina', | |
| 'quality':1 }, | |
| { | |
| 'a': 6.38, | |
| 'b': -3.16, | |
| 'd1':-0.33, | |
| 'd2':-0.1, | |
| 'description':'Voľby cez internet'}, | |
| { | |
| 'a': -2.5817095387, | |
| 'b': 21.1590242094, | |
| 'd1':-0.49199217, | |
| 'd2':0.02325212, | |
| 'description':'Maďarčina - stejné postavenie', | |
| 'quality': 1 | |
| }, | |
| ]; | |
| for (k in lines) { | |
| ps = linecross(lines[k],limits); | |
| if (ps.length == 2) { | |
| lines[k].x1 = ps[0][0]; | |
| lines[k].y1 = ps[0][1]; | |
| lines[k].x2 = ps[1][0]; | |
| lines[k].y2 = ps[1][1]; | |
| } | |
| way = get_sign(lines[k].b,lines[k].d1,lines[k].d2); | |
| lines[k].path =[corners(lines[k],limits,way),corners(lines[k],limits,-1*way)]; | |
| } | |
| var line = svg.selectAll ('g') | |
| .data(lines) | |
| .enter().append('g') | |
| .attr("class",function(d) {if (d.quality == 1) return "line quality-1"; else return "line";}) | |
| .attr("id", function (d, i) {return "q-" + i;}) | |
| .on("mouseover", function (d, i) { | |
| d3.select(this).classed({"active":true}); | |
| highlight_persons(data,i); | |
| }) | |
| .on("mouseout",function (d,i) { | |
| d3.select(this).classed({"active":false}); | |
| dehighlight_persons(i); | |
| }) | |
| line.append("line") | |
| .attr("x1",function(d) {return x(d.x1)}) | |
| .attr("y1",function(d) {return y(d.y1)}) | |
| .attr("x2",function(d) {return x(d.x2)}) | |
| .attr("y2",function(d) {return y(d.y2)}); | |
| line.append("text") | |
| .attr("text-anchor", "middle") | |
| .attr("class","line-text") | |
| .text(function (d, i) { | |
| return d.description; | |
| }) | |
| .attr("x", function(d, i) { | |
| if (d.x1 > d.x2) | |
| return x(d.x2); | |
| else | |
| return x(d.x1); | |
| }) | |
| .attr("y", function(d, i) { | |
| if (d.x1 > d.x2) | |
| return y(d.y1); | |
| else | |
| return y(d.y2); | |
| }) | |
| .style("text-anchor", "start") | |
| .attr("transform", function(d, i) { | |
| rot=-Math.atan(d.b)/2/Math.PI*360; //d.slope; | |
| if (d.x1 > d.x2){ | |
| xx = x(d.x1); | |
| yy = y(d.y1); | |
| } else { | |
| xx = x(d.x2); | |
| yy = y(d.y2); | |
| } | |
| return "rotate(" + rot +"," +xx + "," + yy +")"}); | |
| //explanation: http://code.hazzens.com/d3tut/lesson_3.html | |
| var area = d3.svg.line() | |
| .x(function(d) {return x(d.x);}) | |
| .y(function(d) {return y(d.y);}); | |
| var areas = line.selectAll("path.area") | |
| .data(function(d) { | |
| return d.path; | |
| }).enter() | |
| .append("path") | |
| .attr("class",function(d, i) {if (i == 0) return "area yes"; else return "area no";}) | |
| .attr("d",area); | |
| var point = svg.selectAll ('.candidate') | |
| .data(data) | |
| .enter().append("g") | |
| .attr("class","candidate") | |
| .attr("id", function (d, i) {return "p-" + i;}) | |
| .on("mouseover", function (d, i) { | |
| d3.select(this).attr("class","candidate active"); | |
| }) | |
| .on("mouseout",function (d,i) { | |
| d3.select(this).attr("class","candidate"); | |
| }) | |
| point.append('circle') | |
| .attr("cx", function(d) { | |
| return x(d.d1) | |
| }) | |
| .attr("cy", function(d) {return y(d.d2) }) | |
| .attr("r", 10) | |
| .attr("class", "point") | |
| point.append('text') | |
| .text(function (d, i) {return d.name; }) | |
| .attr("x", function(d) {return x(d.d1) }) | |
| .attr("y", function(d) {return y(d.d2) }) | |
| .attr("r", 10) | |
| .attr("class", "name") | |
| .style("text-anchor","middle") | |
| }) | |
| function highlight_persons(values,index) { | |
| //cannot use jQuery addClass with svg ! | |
| //http://stackoverflow.com/questions/8638621/jquery-svg-why-cant-i-addclass | |
| $(".candidate").each(function(i,e) { | |
| $(this).attr('class',function() { | |
| if (parseInt(values[i]['q'+index]) == 1) return 'candidate yes'; | |
| if (parseInt(values[i]['q'+index]) == -1) return 'candidate no'; | |
| return; | |
| }); | |
| }); | |
| } | |
| function dehighlight_persons(index) { | |
| $(".candidate").attr('class','candidate'); | |
| } | |
| function corners(l,e,o) { | |
| //l = {"a":0,"b":1} //line, a and slope, i.e., y=a+bx | |
| //e = {"x": [-10,10], "y": [-10,10]} //limits | |
| //o = 1 //orientation -1 or 1 | |
| //crossing x0, x1 | |
| //crossing y0, y1 | |
| outp = linecross (l,e); | |
| out = []; | |
| //vertices | |
| for (i=0;i<=1;i++){ | |
| for (j=0;j<=1;j++){ | |
| if (o*(l.a+l.b*e.x[i]-e.y[j]) > 0) | |
| outp.push([e.x[i],e.y[j]]); | |
| } | |
| } | |
| //sort the outps, anticlockwise | |
| if (outp.length > 0) { | |
| mid = [0,0]; | |
| for (i in outp) { | |
| mid[0] += outp[i][0]; | |
| mid[1] += outp[i][1]; | |
| } | |
| mid[0] = mid[0] / outp.length; | |
| mid[1] = mid[1] / outp.length; | |
| for (i in outp) { | |
| p = outp[i][1] - mid[1]; | |
| q = outp[i][0] - mid[0]; | |
| if (q != 0) | |
| outp[i][2] = Math.atan(p/q) + (q<0 ? Math.PI : 0); | |
| else | |
| outp[i][2] = Math.PI/2 + Math.PI*sign(p); | |
| } | |
| outp = outp.sort(function(w,z) { | |
| return w[2] > z[2]; | |
| }); | |
| for (i in outp) { | |
| outp[i].splice(2,1); | |
| out.push({"x":outp[i][0],"y":outp[i][1]}); | |
| } | |
| } | |
| return out; | |
| } | |
| function linecross (l,e) { | |
| out = []; | |
| //crossing x0, x1 | |
| for (i=0;i<=1;i++){ | |
| Y = l.a + l.b*e.x[i]; | |
| if ((Y > e.y[0]) && (Y < e.y[1])) | |
| out.push([e.x[i],Y]); | |
| } | |
| //crossing y0, y1 | |
| for (j=0;j<=1;j++){ | |
| if (l.b != 0) { | |
| X = (e.y[j] - l.a)/l.b; | |
| if ((X > e.x[0]) && (X < e.x[1])) | |
| out.push([X,e.y[j]]); | |
| } | |
| } | |
| return out; | |
| } | |
| function get_sign(b,d1,d2) { | |
| t = b*d1-d2; | |
| if (t > 0) return 1; | |
| if (t < 0) return -1; | |
| return 0; | |
| } | |
| function sign(x) { | |
| return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN; | |
| } | |
| </script> | |
| <script> | |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ | |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), | |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) | |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); | |
| ga('create', 'UA-8592359-13', 'ocks.org'); | |
| ga('send', 'pageview'); | |
| </script> |
| name | d1 | d2 | q0 | q1 | q2 | q3 | q4 | q5 | q6 | q7 | q8 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Melník | 1.07849065 | -0.1191408 | -1 | -1 | 1 | -1 | 1 | 1 | 0 | 1 | -1 | |
| Martinčko | -1.99039949 | 0.745852 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | |
| Šimko | -1.57697495 | -1.2902898 | 1 | -1 | -1 | 1 | 1 | -1 | 1 | 1 | 1 | |
| Čarnogurský | 0.03047429 | -1.9369032 | 1 | -1 | 1 | -1 | 1 | -1 | 1 | 1 | -1 | |
| Kiska | -1.01942107 | 2.3123596 | -1 | 1 | -1 | 1 | 1 | 1 | 1 | 1 | -1 | |
| Procházka | 0.81328076 | 0.7885653 | -1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | -1 | |
| Hrušovský | 2.39481329 | 0.6917826 | -1 | 1 | 1 | -1 | -1 | 1 | 1 | -1 | -1 | |
| Bárdos | 1.73643192 | 0.6233822 | -1 | 1 | 1 | -1 | -1 | 1 | 1 | 1 | 1 | |
| Mezenská | 0.32224881 | -2.1949306 | 1 | -1 | 1 | -1 | 1 | -1 | 1 | 1 | -1 | |
| Kňažko | -1.78894421 | 0.3793228 | 1 | 0 | -1 | 1 | 1 | 1 | 1 | 1 | -1 |