Guest User

senate2014_est.py

a guest
Jul 5th, 2014
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.94 KB | None | 0 0
  1. # Senate estimate 30 June 2014
  2. # Copyright Sam Wang, Princeton University, [email protected]
  3. # GNU license - free use but retain this header.
  4. #
  5. # Python translation 5 July 2014 by Ryan Buckley
  6. #
  7. # Dem/Ind safe: 45
  8. # GOP safe: 46
  9. # 9 races remain: AK, AR, CO, GA, IA, KY, LA, MI, NC
  10. import numpy as np
  11. import matplotlib.pyplot as plt
  12. import scipy.stats
  13.  
  14. def senate2014_est(margins, dem_safe, GOP_safe, un, bias = 0):
  15.     """ Take polling margins, number of safe dem seats, number of safe GOP seats, un, and bias. Return all_dists, whose i-th element (indexed at 0) is the probability of democrats winning i contested seats """
  16.     num_states = len(margins)
  17.     assert( num_states == 100 - dem_safe - GOP_safe )
  18.  
  19.     # get the medians of the margins for each state
  20.     margin_lens = np.zeros( len(margins) )
  21.     medians = np.zeros( len(margins) )
  22.     margin_mads = np.zeros( len(margins) )
  23.     for i, state_margin in enumerate(margins):
  24.         margin_lens[i] = len(state_margin)
  25.         medians[i] = np.median(state_margin)
  26.         margin_mads[i] = mad(state_margin)
  27.     # calculate the standard error of the mean for each state
  28.     sem = margin_mads / 0.6745 * 1.2 / np.sqrt(margin_lens)
  29.  
  30.     all_dists = np.zeros( num_states + 1 )
  31.     all_probs = np.zeros( num_states )
  32.     bias_values = np.arange(bias-2, bias+2.1, 0.2)
  33.  
  34.     for diff in bias_values:
  35.         # SUBTLE CHANGE: max() in MATLAB becomes maximum() in NumPy
  36.         z = ( medians + diff ) / np.maximum(np.sqrt( sem * sem + un*un),
  37.                                             np.sqrt(1.0/500/margin_lens) )
  38.         senate_probs = scipy.stats.t.cdf(z, margin_lens)
  39.  
  40.         # get dist of sums of independent random variables by convolution
  41.         senate_dist = np.array([1-senate_probs[0], senate_probs[0]])
  42.         for prob in senate_probs[1:num_states+1]:
  43.             senate_dist = np.convolve(senate_dist, np.array([1-prob, prob]))
  44.  
  45.         all_probs = all_probs + senate_probs
  46.         all_dists = all_dists + senate_dist
  47.  
  48.     all_probs =   all_probs / len(bias_values)
  49.     all_dists = ( all_dists / len(bias_values) ) *100
  50.  
  51.     mode_dem = dem_safe + np.argmax(all_dists)
  52.     mode_gop = 100 - mode_dem
  53.     prob_dem = 0.88*all_dists[50-dem_safe] + np.sum(all_dists[51-dem_safe:])
  54.     mean_seats = np.sum(all_dists*np.arange(num_states+1) ) / 100 + dem_safe
  55.     print all_probs
  56.     print all_dists
  57.     print mean_seats
  58.     print prob_dem
  59.  
  60.     arr_to_write = np.array([mode_dem, mode_gop, prob_dem])
  61.     np.savetxt('Sen_estimates_2014.csv', arr_to_write, delimiter="," )
  62.     return all_dists
  63.  
  64.  
  65. def mad(arr):
  66.     """ Calculate the mean absolute deviation of the input array. """
  67.     mean = np.mean(arr)
  68.     n = len(arr)
  69.     return np.sum( np.abs(arr - mean) )*1.0/n
  70.  
  71. def draw_barplot(dem_safe, num_states, all_dists):
  72.     plt.bar( range(dem_safe, dem_safe+num_states+1), all_dists,
  73.                     color='red', align='center')
  74.     plt.bar( range(50, dem_safe + num_states + 1 ),
  75.                 all_dists[ 50-dem_safe:num_states+1],
  76.                 color='blue', align='center')
  77.     plt.xticks(  range(dem_safe, dem_safe+num_states+1 ) )
  78.     plt.grid()
  79.     plt.xlabel('Democratic/Independent Senate Seats')
  80.     plt.ylabel('Probability (%)')
  81.     plt.show()
  82.  
  83. def get_margins():
  84.     """ Return a list of poll margins for contested states """
  85.     # polls newest to oldest from HuffPost. last three polls, going
  86.     # back no more than 6 weeks
  87.     # If over 3 polls are available and the oldest polls are near one another in time, take them all
  88.     margins_ak=np.array([5, -5]) # http://elections.huffingtonpost.com/pollster/2014-alaska-senate-sullivan-vs-begich
  89.     margins_ar=np.array([-7, -8, -4]) # http://elections.huffingtonpost.com/pollster/2014-arkansas-senate-cotton-vs-pryor
  90.     margins_co=np.array([1, 4, -2]) # http://elections.huffingtonpost.com/pollster/2014-colorado-senate-gardner-vs-udall
  91.     margins_ga=np.array([2, 3, -5]) # http://elections.huffingtonpost.com/pollster/2014-georgia-senate-perdue-vs-nunn
  92.     margins_ia=np.array([4, -6, -1, -5]) # http://elections.huffingtonpost.com/pollster/2014-iowa-senate-ernst-vs-braley
  93.     margins_ky=np.array([2, 3, -7]) # http://elections.huffingtonpost.com/pollster/2014-kentucky-senate-mcconnell-vs-grimes
  94.     margins_la=np.array([0, -6]) # http://elections.huffingtonpost.com/pollster/2014-louisiana-senate-cassidy-vs-landrieu
  95.     margins_mi=np.array([3, 5, 9]) # http://elections.huffingtonpost.com/pollster/2014-michigan-senate-land-vs-peters
  96.     margins_nc=np.array([1, 5, 7]) # http://elections.huffingtonpost.com/pollster/2014-north-carolina-senate-tillis-vs-hagan
  97.  
  98.     # Pass the state margins as a *list* of 1D NumPy arrays
  99.     # using a 2D NumPy array might be nicer, but we have to deal with
  100.     # different states having different numbers of polls
  101.     return [margins_ak, margins_ar, margins_co, margins_ga, margins_ia,
  102.                margins_ky, margins_la, margins_mi, margins_nc]
  103.  
  104. def main():
  105.     margins = get_margins()
  106.     num_states = len(margins)
  107.     dem_safe = 45
  108.     GOP_safe = 46
  109.  
  110.     all_dists = senate2014_est(margins, dem_safe, GOP_safe, un=1.5, bias =0)
  111.     draw_barplot( dem_safe, num_states, all_dists )
  112.  
  113.     bias_range = np.arange(-5, 5.1, 0.2)
  114.     bias_calc(bias_range, margins, dem_safe, GOP_safe, un=1.5)
  115.  
  116. def bias_calc(bias_range, margins, dem_safe, GOP_safe, un):
  117.     num_states = len(margins)
  118.     assert( num_states == 100 - dem_safe - GOP_safe )
  119.  
  120.     senate_means = np.zeros( len(bias_range) )
  121.     for i, bias in enumerate(bias_range):
  122.         all_dists = senate2014_est(margins, dem_safe,GOP_safe,un, bias=bias)
  123.         senate_means[i] = ( np.sum( all_dists * np.arange(num_states+1) )
  124.                                     / 100 + dem_safe )
  125.     plt.plot(bias_range, senate_means,'.-k')
  126.     plt.grid()
  127.     plt.xlabel('Shift in national D-R vote margin (%)')
  128.     plt.ylabel('Average Dem+Ind Senate seats')
  129.     plt.axis( [-3, 3, 47.9, 53] )
  130.     plt.show()
  131.  
  132. if __name__ == "__main__":
  133.     main()
Advertisement
Add Comment
Please, Sign In to add comment