index.html
<!DOCTYPE html>
<html>
<head>
<title>circles</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.2.0/journal/bootstrap.min.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<style type="text/css">
text {
font-family: sans-serif;
}
.tick {
fill-opacity: 0;
stroke: #000000;
stroke-width: 1;
}
.domain {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
}
.axis line {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 15px;
}
.axis {
}
rect, circle {
fill-opacity: .5;
stroke-opacity: 0.99;
stroke-width: 1;
fill: blue;
}
.ourpoint {
fill-opacity: .99;
stroke-opacity: 0.99;
stroke-width: 1;
fill: red;
}
.zeroline {
stroke: #000;
stroke-width: 1;
stroke-opacity: 1;
}
.centerline {
stroke: #080;
stroke-width: 10;
stroke-opacity: 1;
}
.estateline {
stroke: #080;
stroke-width: 3;
stroke-opacity: 1;
}
.restline {
stroke: #444;
stroke-width: 3;
stroke-opacity: 1;
}
.totalline {
stroke: #888;
stroke-width: 3;
stroke-opacity: 1;
}
.label {
font-family: sans-serif;
font-size: 15px;
}
.center, .madari {
fill: #b00;
stroke: #b00;
}
.estate, .banska-bystrica, .brezno {
fill: #080;
stroke: #080;
}
</style>
</head>
<body>
<nav class="navbar navbar-default" role=navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand">Average distances and deviations of parties using 35 random questions out of 80 in Czech VAA 2013.</a>
</div>
</div>
</nav>
<div class="alert alert-info">Every point represents one random set of 35 question out of 80 asked. Actual VAA is in red.</div>
<div id="chart"></div>
<script>
var margin = {top: 20, right: 20, bottom: 50, left: 50},
width = 770 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
.domain([0.2,0.5]);
var y = d3.scale.linear()
.range([height, 0])
.domain([0,0.2]);
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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", x(0.5))
.attr("dx", "0em")
.attr("dy", "-1em")
.style("text-anchor", "end")
.text("weighted average distance");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("weighted average deviation");
var line = d3.svg.line()
.x(
function(d) {
return d[0]; })
.y(function(d) { return d[1]; });
ourpoint = {"average":0.37, "deviation": 0.132}
arcpoints = [
{"x":0.34, "y": 0.055},
{"x":0.38, "y": 0.055},
{"x":0.43, "y": 0.08},
{"x":0.44, "y": 0.12},
{"x":0.44, "y": 0.127}
];
var valueline = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
coef = .5;
d3.csv('statistics.csv', function(data) {
var nodes = svg.selectAll(".circle")
.data(data)
.enter().append("svg:circle")
.attr("cx", function (d) {return x(d.average)})
.attr("cy", function (d) {return y(d.deviation);})
.attr("r", function (d) {return 3;})
.attr("class", function(d) {return "circle"})
.attr("title", function(d) {return d.average + ":" + d.deviation});
svg.append("circle")
.datum(ourpoint)
.attr("class", "ourpoint")
.attr("cx", function (d) {return x(d.average)})
.attr("cy", function (d) {return y(d.deviation);})
.attr("r", 20);
svg.append("path")
.attr("class","centerline")
.attr("d", valueline(arcpoints))
.attr("fill", "none");
});
</script>
</body>
</html>
calc_matches_our.py
'''calculate distances'''
import csv
from random import shuffle
import copy
def option2numeric_party(v):
if v == 'yes':
return 1
if v == 'no':
return -1
if v == 'abstain':
return 0
return 0
party_votes = {}
with open("../../parties/data/votes.csv") as fin:
i = 0
csvr = csv.reader(fin)
for row in csvr:
if i == 0:
j = 0
header = {}
for item in row:
header[item] = j
j = j + 1
else:
for item in row:
if option2numeric_party(row[header['option']]) != 'none':
try:
party_votes[row[header['voter_id']]]
except:
party_votes[row[header['voter_id']]] = {}
party_votes[row[header['voter_id']]][row[header['vote_event_id']]] = option2numeric_party(row[header['option']])
i = i + 1
parties = {}
with open("voters.csv") as fin:
i = 0
csvr = csv.reader(fin)
for row in csvr:
if i == 0:
nothing = 0
else:
parties[row[0]] = float(row[2])/100
i += 1
vote_events = []
vedic = {}
for pkey in party_votes:
for vekey in party_votes[pkey]:
vedic[vekey] = vekey
for key in vedic:
vote_events.append(key)
def option2numeric_user(v):
if v == 'yes':
return 1
if v == 'no':
return -1
if v == 'abstain':
return 'none'
return 'none'
print("votes read")
def match(u,p):
w = 0
m = 0
for ku in u:
try:
m = m + u[ku]['option']*p[ku]*u[ku]['weight']
w = w + abs(u[ku]['option'])*u[ku]['weight']
except:
nothing = 0
if w == 0:
return 0
else:
return (m/w+1)/2
def pmatch(u,p):
w = 0
m = 0
for ku in u:
try:
m = m + u[ku]*p[ku]
w = w + abs(u[ku])*abs(p[ku])
except:
nothing = 0
if w == 0:
return 0
else:
return m/w
party_votes_35 = {}
vote_events = ['26', '2', '5', '10', '12', '7', '9', '20', '29', '27', '34', '102', '106', '112', '44', '47', '55', '30', '56', '120', '63', '40', '60', '119', '118', '62', '23', '13', '17', '31', '39', '37', '24', '25', '35']
for pkey in party_votes:
party_votes_35[pkey] = {}
for j in range(0,35):
party_votes_35[pkey][vote_events[j]] = party_votes[pkey][vote_events[j]]
pdistances_li = []
pdistances_ind = []
pdistances_w = []
ws = []
wss = []
pmatches = {}
for key in party_votes_35:
for pkey in party_votes_35:
try:
pmatches[key]
except:
pmatches[key] = {}
pmatches[key][pkey] = pmatch(party_votes_35[key],party_votes_35[pkey])
pdistances_ind = copy.deepcopy(pmatches)
for key in party_votes_35:
for pkey in party_votes_35:
if key == pkey:
pdistances_ind[key][pkey] = False
else:
if pdistances_ind[key][pkey] != False:
pdistances_li.append(1-(pmatches[key][pkey]+1)/2)
ws.append(parties[key]*parties[pkey])
wss.append([parties[key],parties[pkey]])
pdistances_w.append((1-(pmatches[key][pkey]+1)/2) * parties[key]*parties[pkey])
pdistances_ind[key][pkey] = False
pdistances_ind[pkey][key] = False
dists = []
average = sum(pdistances_w) / sum(ws)
i = 0
for item in pdistances_li:
dists.append(abs(item-average) * ws[i])
i += 1
deviation = sum(dists)/sum(ws)
print(average, deviation)
with open("party_distances.csv","w") as fout:
csvw = csv.writer(fout)
row = ['']
for pkey in sorted(party_votes):
row.append(pkey)
csvw.writerow(row)
for ukey in sorted(party_votes):
row = [ukey]
for pkey in sorted(party_votes):
try:
row.append(pdistances[ukey][pkey])
except:
row.append(0)
csvw.writerow(row)