Skip to content

Commit

Permalink
Integrated the riding poll model with the main proportional swing mod…
Browse files Browse the repository at this point in the history
…el. Also added independent candidates.
  • Loading branch information
j3camero committed Oct 1, 2015
1 parent 1bd8c7e commit 5f0d6d0
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 16 deletions.
20 changes: 16 additions & 4 deletions riding_forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
from scipy.stats import norm

from regional_poll_interpolator import RegionalPollInterpolator
import riding_poll_model

party_long_names = {
'cpc': 'Conservative/Conservateur',
'lpc': 'Liberal/Lib',
'ndp': 'NDP-New Democratic Party/NPD-Nouveau Parti d',
'gpc': 'Green Party/Parti Vert',
'bq': 'Bloc Qu',
'oth': 'Independent',
}

province_to_region = {
Expand Down Expand Up @@ -129,7 +131,10 @@ def KeyWithHighestValue(d, forbidden_keys=[]):
assert region
before = interpolator.Interpolate(region, party, baseline_date)
after = interpolator.GetMostRecent(region, party)
projected_gain = after / before
if before > 0:
projected_gain = after / before
else:
projected_gain = 1
projection = popular_vote * projected_gain
if not riding_number in old_ridings:
old_ridings[riding_number] = {
Expand Down Expand Up @@ -179,26 +184,34 @@ def KeyWithHighestValue(d, forbidden_keys=[]):
r['total_electors_2011'] += int(electors)

# Output final stats for each riding.
party_order = ['cpc', 'ndp', 'lpc', 'gpc', 'bq']
party_order = ['cpc', 'ndp', 'lpc', 'gpc', 'bq', 'oth']
readable_party_names = {
'cpc': 'CON',
'lpc': 'LIB',
'ndp': 'NDP',
'gpc': 'GRN',
'bq': 'BQ',
'oth': 'OTH',
}
print ('province,name,number,' +
','.join(readable_party_names[p].lower() for p in party_order) +
',projected_winner,strategic_vote,confidence,turnout_2011')
for r in new_ridings.values():
projections = {}
riding_name = r['name']
riding_number = str(r['number'])
province = r['province']
# Calculate projections for this riding by mixing old-riding projections.
for feeder_number, weight in r['feeders'].items():
feeder = old_ridings[feeder_number]
normalized = NormalizeDictVector(feeder['projections'])
for party, support in normalized.items():
if party not in projections:
projections[party] = 0
projections[party] += support * weight
# Upgrade the projections for ridings with local polling data available.
projections = riding_poll_model.projections_by_riding_number.get(
riding_number, projections)
ordered_projections = [projections.get(p, 0) for p in party_order]
projected_winner = KeyWithHighestValue(projections)
runner_up = KeyWithHighestValue(projections, [projected_winner])
Expand All @@ -208,7 +221,6 @@ def KeyWithHighestValue(d, forbidden_keys=[]):
strategic_vote = readable_party_names[strategic_vote]
confidence = norm.cdf(gap / 0.25)
turnout = float(r['total_votes_2011']) / r['total_electors_2011']
riding_name = r['name']
row = ([r['province'], riding_name, r['number']] + ordered_projections +
row = ([province, riding_name, riding_number] + ordered_projections +
[projected_winner, strategic_vote, confidence, turnout])
print ','.join([str(x) for x in row])
17 changes: 5 additions & 12 deletions riding_poll_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,10 @@ def DictVectorToString(vector):
strings.append('%s %.2f' % (k, v))
return ' '.join(strings)

# The projections based on riding polls are stored in here, keyed by riding
# number as a string.
projections_by_riding_number = {}

# Load the poll data interpolator.
interpolator = RegionalPollInterpolator()
interpolator.LoadFromCsv('regional_poll_averages.csv')
Expand Down Expand Up @@ -450,24 +454,13 @@ def DictVectorToString(vector):
region, parsed_date, party_numbers)
age_seconds = (datetime.datetime.now() - parsed_date).total_seconds()
age_days = float(age_seconds) / (24 * 3600)
#age_months = age_days / 30.5
age_years = age_days / 365.25
weight = sample_size * (0.25 ** age_years)
total_weight += weight
for party, support in poll_projection.items():
if party not in weighted_projection:
weighted_projection[party] = 0
weighted_projection[party] += weight * support
if riding_name == 'Calgary Centre':
print 'riding:', riding_name, riding_number, region
print 'poll:', DictVectorToString(party_numbers)
print 'projection:', DictVectorToString(poll_projection)
print 'date:', parsed_date, 'weight:', weight, 'sample:', sample_size
print ''
for party in weighted_projection:
weighted_projection[party] /= total_weight
if riding_name == 'Calgary Centre':
print 'riding:', riding_name, riding_number, region
print 'projection:', DictVectorToString(weighted_projection)
print 'total_weight:', total_weight
print ''
projections_by_riding_number[str(riding_number)] = weighted_projection

0 comments on commit 5f0d6d0

Please sign in to comment.