Example #1
0
 def __init__(self, 
              datestr, 
              pollster, 
              sponsor, 
              sample_size, 
              con, lab, lib, ukip):
     """Constructor.  Store off data."""
     
     # Store off the easy stuff.
     self.pollster = pollster
     self.sponsor = sponsor
     self.sample_size = sample_size
     
     # Parse the date string into a date object for easy sorting.
     self.date = datetime.datetime.strptime(datestr, '%d %b %Y')
     
     # Store all the vote percentages as if they were votes from a total
     # turnout of 100.
     votes = {CON: con,
              LAB: lab,
              LD: lib,
              UKP: ukip}
     votes[OTH] = 100 - sum(votes.values())
     
     # Now convert those into a support dictionary.
     self.support = utils.calculate_support(votes)
     
     # Initialize somewhere to store the MonteCarlo results of this poll.
     self.mc_results = None
     
     return
Example #2
0
 def calculate_overall_support(self, year=None):
     """Create a support dictionary based on the number of votes in the
     given year.  If no year is provided, use the predicted votes.
     """
     
     total_votes = {}
     for const_name in self.constituencies.keys():
         const = self.constituencies[const_name]
         if year is None:
             votes = const.sim_votes
         elif year == 2005:
             votes = const.votes_2005
         else:
             assert year == 2010, "Year must be None, 2005 or 2010"
             votes = const.votes_2010
         for party in votes.keys():
             if party not in total_votes.keys():
                 total_votes[party] = votes[party]
             else:
                 total_votes[party] += votes[party]
     
     support = utils.calculate_support(total_votes)
                 
     return support
Example #3
0
    def __init__(self, datestr, pollster, sponsor, sample_size, con, lab, lib,
                 ukip):
        """Constructor.  Store off data."""

        # Store off the easy stuff.
        self.pollster = pollster
        self.sponsor = sponsor
        self.sample_size = sample_size

        # Parse the date string into a date object for easy sorting.
        self.date = datetime.datetime.strptime(datestr, '%d %b %Y')

        # Store all the vote percentages as if they were votes from a total
        # turnout of 100.
        votes = {CON: con, LAB: lab, LD: lib, UKP: ukip}
        votes[OTH] = 100 - sum(votes.values())

        # Now convert those into a support dictionary.
        self.support = utils.calculate_support(votes)

        # Initialize somewhere to store the MonteCarlo results of this poll.
        self.mc_results = None

        return
Example #4
0
    def calculate_overall_support(self, year=None):
        """Create a support dictionary based on the number of votes in the
        given year.  If no year is provided, use the predicted votes.
        """

        total_votes = {}
        for const_name in self.constituencies.keys():
            const = self.constituencies[const_name]
            if year is None:
                votes = const.sim_votes
            elif year == 2005:
                votes = const.votes_2005
            else:
                assert year == 2010, "Year must be None, 2005 or 2010"
                votes = const.votes_2010
            for party in votes.keys():
                if party not in total_votes.keys():
                    total_votes[party] = votes[party]
                else:
                    total_votes[party] += votes[party]

        support = utils.calculate_support(total_votes)

        return support
Example #5
0
    def analyze(self):
        """Analyze the results of the election."""
        
        # Create a new Result structure to hold these results.
        self.result = Result()
        
        # First determine the largest party.
        party_list = sorted(self.parties.values(),
                            key=attrgetter('seats'),
                            reverse=True)
        self.result.largest_party = party_list[0].name
        self.result.most_seats_won = party_list[0].seats

        # Save off the numbers of seats gained by all parties.
        for party in self.parties:
            self.result.seats[party] = self.parties[party].seats
            
        # Record zero seats for any party that didn't get any.
        for party in (set(PARTY_NAMES) - set(self.parties)):
            self.result.seats[party] = 0
                
        # Now determine whether the largest party is past or behind the winning
        # line (and by how much).
        self.result.margin_of_victory = (self.result.most_seats_won - 
                                         NEEDED_FOR_MAJORITY)
        if self.result.margin_of_victory >= 0:
            self.result.summary = "{0} victory (majority {1})".format(
                                                  self.result.largest_party,
                                                  self.result.margin_of_victory)
            self.result.winner = self.result.largest_party
        else:
            self.result.summary = "Hung Parliament ({0} needs {1})".format(
                                            self.result.largest_party,
                                            (0 - self.result.margin_of_victory))
            
            # Work out the coalitions that could conceivably take power.  The
            # expected rules for this are as follows:
            # - A coalition always has CON or LAB as the senior partner
            # - Both CON and LAB will take LD as their preferred junior partner
            # - Only CON will take UKP as a junior partner
            # - Only LAB will take GRN as a junior partner
            # - LD and GRN will not join a coalition that includes UKP
            # - SNP will join neither a LAB nor a CON coalition
            # - PC will join only a LAB coalition
            # - OTH will join anyone
            # - Both LAB and CON prefer named parties to OTH
            if (self.result.seats[CON] + self.result.seats[LD] >=
                NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-LD")
            elif (self.result.seats[CON] + self.result.seats[UKP] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-UKP")    
            elif (self.result.seats[CON] + self.result.seats[LD] + 
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-LD-OTH")
            elif (self.result.seats[CON] + self.result.seats[OTH] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-OTH")    
            elif (self.result.seats[CON] + self.result.seats[UKP] + 
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-UKP-OTH")
                
            if (self.result.seats[LAB] + self.result.seats[LD] >=
                NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD")
            elif (self.result.seats[LAB] + self.result.seats[LD] + 
                  self.result.seats[PC] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC")    
            elif (self.result.seats[LAB] + self.result.seats[LD] + 
                  self.result.seats[GRN] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-GRN")
            elif (self.result.seats[LAB] + self.result.seats[LD] + 
                  self.result.seats[GRN] + self.result.seats[PC] >= 
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC-GRN")
            elif (self.result.seats[LAB] + self.result.seats[PC] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-PC")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-OTH")
            elif (self.result.seats[LAB] + self.result.seats[LD] + 
                  self.result.seats[PC] + self.result.seats[OTH] >= 
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC-OTH")    
            elif (self.result.seats[LAB] + self.result.seats[LD] + 
                  self.result.seats[GRN] + self.result.seats[OTH] >= 
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-GRN-OTH")
            elif (self.result.seats[LAB] + self.result.seats[LD] + 
                  self.result.seats[GRN] + self.result.seats[PC] + 
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC-GRN-OTH")
                
            if len(self.result.possible_coalitions) == 0:
                self.result.possible_coalitions = ["NONE"]
            
        # Did UKIP win any seats in this election?
        if UKP in self.parties:
            self.result.ukip_seats = self.parties[UKP].seats
        else:
            self.result.ukip_seats = 0
        
        # Did the Lib-Dems?
        if LD in self.parties:
            self.result.libdem_seats = self.parties[LD].seats
        else:
            self.result.libdem_seats = 0
        
        # Did the Greens hold Brighton Pavilion?
        if self.constituencies["Brighton Pavilion"].winning_party == GRN:
            self.result.greens_hold_brighton = True
        else:
            self.result.greens_hold_brighton = False
            
        # Was the party with the most seats the popular vote winner?
        votes = {}
        for const_name in self.constituencies:
            const = self.constituencies[const_name]
            for party in const.sim_votes.keys():
                if party not in votes.keys():
                    votes[party] = const.sim_votes[party]
                else:
                    votes[party] += const.sim_votes[party]
        
        most_votes = 0
        self.result.most_votes_party = None
        for party in votes.keys():
            if votes[party] > most_votes:
                most_votes = votes[party]
                self.result.most_votes_party = party
                
        self.result.seat_winner_is_pop_winner = (self.result.largest_party ==
                                                 self.result.most_votes_party)
        
        # Find all the constituencies where the Conservatives are predicted
        # to win heavily, but UKIP did not field a candidate in 2010 - these
        # are the UKIP stealth targets, where they could win much more
        # easily than expected.
        no_ukips = [self.constituencies[cons] for cons in self.constituencies if 
                    self.constituencies[cons].votes_2010[UKP] == 0]
        con_win_no_ukip = [cons for cons in no_ukips if 
                            cons.winning_party == CON]
        for cons in con_win_no_ukip:
            vote_counts = sorted(cons.sim_votes.values(),
                                     reverse=True)
            margin = vote_counts[0] - vote_counts[1]
            if margin > 1000:
                self.result.ukip_stealth_targets[cons.name] = margin
        
        # Was the vote distribution sufficiently close to the initial support
        # figures?
        overall_support = utils.calculate_support(votes)
        support_2010 = self.calculate_overall_support(2010)
        self.result.support = overall_support
        for party in self.predicted_support:
            divergence = abs(self.predicted_support[party] - 
                             overall_support[party])
            logger.debug("{0} support was {1}, predicted {2}, actual {3}, "
                         "divergence {4}".format(party,
                                                 support_2010[party],
                                                 self.predicted_support[party],
                                                 overall_support[party],
                                                 divergence))
            if divergence > RESULT_TOLERANCE:
                # This party's result is too far away from its predicted
                # support.  This result can't stand.
                logger.debug("Result too far from prediction!")
                self.result.result_too_divergent = True
        
        return
Example #6
0
    def analyze(self):
        """Analyze the results of the election."""

        # Create a new Result structure to hold these results.
        self.result = Result()

        # First determine the largest party.
        party_list = sorted(self.parties.values(),
                            key=attrgetter('seats'),
                            reverse=True)
        self.result.largest_party = party_list[0].name
        self.result.most_seats_won = party_list[0].seats

        # Save off the numbers of seats gained by all parties.
        for party in self.parties:
            self.result.seats[party] = self.parties[party].seats

        # Record zero seats for any party that didn't get any.
        for party in (set(PARTY_NAMES) - set(self.parties)):
            self.result.seats[party] = 0

        # Now determine whether the largest party is past or behind the winning
        # line (and by how much).
        self.result.margin_of_victory = (self.result.most_seats_won -
                                         NEEDED_FOR_MAJORITY)
        if self.result.margin_of_victory >= 0:
            self.result.summary = "{0} victory (majority {1})".format(
                self.result.largest_party, self.result.margin_of_victory)
            self.result.winner = self.result.largest_party
        else:
            self.result.summary = "Hung Parliament ({0} needs {1})".format(
                self.result.largest_party, (0 - self.result.margin_of_victory))

            # Work out the coalitions that could conceivably take power.  The
            # expected rules for this are as follows:
            # - A coalition always has CON or LAB as the senior partner
            # - Both CON and LAB will take LD as their preferred junior partner
            # - Only CON will take UKP as a junior partner
            # - Only LAB will take GRN as a junior partner
            # - LD and GRN will not join a coalition that includes UKP
            # - SNP will join neither a LAB nor a CON coalition
            # - PC will join only a LAB coalition
            # - OTH will join anyone
            # - Both LAB and CON prefer named parties to OTH
            if (self.result.seats[CON] + self.result.seats[LD] >=
                    NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-LD")
            elif (self.result.seats[CON] + self.result.seats[UKP] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-UKP")
            elif (self.result.seats[CON] + self.result.seats[LD] +
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-LD-OTH")
            elif (self.result.seats[CON] + self.result.seats[OTH] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-OTH")
            elif (self.result.seats[CON] + self.result.seats[UKP] +
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("CON-UKP-OTH")

            if (self.result.seats[LAB] + self.result.seats[LD] >=
                    NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[PC] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[GRN] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-GRN")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[GRN] + self.result.seats[PC] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC-GRN")
            elif (self.result.seats[LAB] + self.result.seats[PC] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-PC")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-OTH")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[PC] + self.result.seats[OTH] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC-OTH")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[GRN] + self.result.seats[OTH] >=
                  NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-GRN-OTH")
            elif (self.result.seats[LAB] + self.result.seats[LD] +
                  self.result.seats[GRN] + self.result.seats[PC] +
                  self.result.seats[OTH] >= NEEDED_FOR_MAJORITY):
                self.result.possible_coalitions.append("LAB-LD-PC-GRN-OTH")

            if len(self.result.possible_coalitions) == 0:
                self.result.possible_coalitions = ["NONE"]

        # Did UKIP win any seats in this election?
        if UKP in self.parties:
            self.result.ukip_seats = self.parties[UKP].seats
        else:
            self.result.ukip_seats = 0

        # Did the Lib-Dems?
        if LD in self.parties:
            self.result.libdem_seats = self.parties[LD].seats
        else:
            self.result.libdem_seats = 0

        # Did the Greens hold Brighton Pavilion?
        if self.constituencies["Brighton Pavilion"].winning_party == GRN:
            self.result.greens_hold_brighton = True
        else:
            self.result.greens_hold_brighton = False

        # Was the party with the most seats the popular vote winner?
        votes = {}
        for const_name in self.constituencies:
            const = self.constituencies[const_name]
            for party in const.sim_votes.keys():
                if party not in votes.keys():
                    votes[party] = const.sim_votes[party]
                else:
                    votes[party] += const.sim_votes[party]

        most_votes = 0
        self.result.most_votes_party = None
        for party in votes.keys():
            if votes[party] > most_votes:
                most_votes = votes[party]
                self.result.most_votes_party = party

        self.result.seat_winner_is_pop_winner = (
            self.result.largest_party == self.result.most_votes_party)

        # Find all the constituencies where the Conservatives are predicted
        # to win heavily, but UKIP did not field a candidate in 2010 - these
        # are the UKIP stealth targets, where they could win much more
        # easily than expected.
        no_ukips = [
            self.constituencies[cons] for cons in self.constituencies
            if self.constituencies[cons].votes_2010[UKP] == 0
        ]
        con_win_no_ukip = [
            cons for cons in no_ukips if cons.winning_party == CON
        ]
        for cons in con_win_no_ukip:
            vote_counts = sorted(cons.sim_votes.values(), reverse=True)
            margin = vote_counts[0] - vote_counts[1]
            if margin > 1000:
                self.result.ukip_stealth_targets[cons.name] = margin

        # Was the vote distribution sufficiently close to the initial support
        # figures?
        overall_support = utils.calculate_support(votes)
        support_2010 = self.calculate_overall_support(2010)
        self.result.support = overall_support
        for party in self.predicted_support:
            divergence = abs(self.predicted_support[party] -
                             overall_support[party])
            logger.debug("{0} support was {1}, predicted {2}, actual {3}, "
                         "divergence {4}".format(party, support_2010[party],
                                                 self.predicted_support[party],
                                                 overall_support[party],
                                                 divergence))
            if divergence > RESULT_TOLERANCE:
                # This party's result is too far away from its predicted
                # support.  This result can't stand.
                logger.debug("Result too far from prediction!")
                self.result.result_too_divergent = True

        return