diff --git a/_assets/scripts/aaa.jl b/_assets/scripts/aaa.jl deleted file mode 100644 index 9fb1949..0000000 --- a/_assets/scripts/aaa.jl +++ /dev/null @@ -1,7 +0,0 @@ -pa = [ 73.0, 53.0, 48.0, 70.0, 71.75 ] -ga = [ 36.0, 42.0, 18.0, 3.0, 2.97 ] -nc = [ 30.0, 24.0, 29.0, 16.0, 15.39 ] -mi = [ 73.0, 82.0, 81.0, 92.0, 92.25 ] -az = [ 66.0, 29.0, 26.0, 8.0, 8.14 ] -wi = [ 68.0, 60.0, 81.0, 86.0, 85.11 ] -nv = [ 25.0, 27.0, 31.0, 55.0, 54.84] diff --git a/_assets/scripts/avg_of_avg.jl b/_assets/scripts/avg_of_avg.jl index e9e5c5b..4f1bfde 100644 --- a/_assets/scripts/avg_of_avg.jl +++ b/_assets/scripts/avg_of_avg.jl @@ -1,20 +1,20 @@ using Plots -pa = [ 73.0, 53.0, 48.0, 70.0, 71.75 ] -ga = [ 36.0, 42.0, 18.0, 3.0, 2.97 ] -nc = [ 30.0, 24.0, 29.0, 16.0, 15.39 ] -mi = [ 73.0, 82.0, 81.0, 92.0, 92.25 ] -az = [ 66.0, 29.0, 26.0, 8.0, 8.14 ] -wi = [ 68.0, 60.0, 81.0, 86.0, 85.11 ] -nv = [ 25.0, 27.0, 31.0, 55.0, 54.84] - +pa = [ 73.0, 53.0, 48.0, 70.0, 71.75, 70.78 ] +ga = [ 36.0, 42.0, 18.0, 3.0, 2.97, 2.81 ] +nc = [ 30.0, 24.0, 29.0, 16.0, 15.39, 10.00 ] +mi = [ 73.0, 82.0, 81.0, 92.0, 92.25, 94.87 ] +az = [ 66.0, 29.0, 26.0, 8.0, 8.14, 6.23 ] +wi = [ 68.0, 60.0, 81.0, 86.0, 85.11, 81.35 ] +nv = [ 25.0, 27.0, 31.0, 55.0, 54.84, 55.51 ] +x = 1:6 p = plot(x, [pa ga nc mi az wi nv], title="Modeled Likelihood of Harris Win", xlabel="Time Period", ylabel="Likelihood (%)", label=["PA" "GA" "NC" "MI" "AZ" "WI" "NV"], - xticks=(1:5, ["early August", "late August", "early September", "late September", "mid October"]), + xticks=(x, ["early August", "late August", "early September", "late September", "mid October", "late October"]), xrotation=45, - legend=:topleft, + legend=:false, linewidth=2, marker=:circle) @@ -26,3 +26,4 @@ annotate!([(2.5, 52, ("Win", 10, :black, :center)), (2.5, 48, ("Loss", 10, :black, :center))]) savefig("../img/avg_of_avg.png") + diff --git a/_assets/scripts/blue_paths_graph.png b/_assets/scripts/blue_paths_graph.png deleted file mode 100644 index 8804330..0000000 Binary files a/_assets/scripts/blue_paths_graph.png and /dev/null differ diff --git a/_assets/scripts/blue_winning_paths.png b/_assets/scripts/blue_winning_paths.png deleted file mode 100644 index 1c73a18..0000000 Binary files a/_assets/scripts/blue_winning_paths.png and /dev/null differ diff --git a/_assets/scripts/clust.jl b/_assets/scripts/clust.jl new file mode 100644 index 0000000..92c5e4a --- /dev/null +++ b/_assets/scripts/clust.jl @@ -0,0 +1,79 @@ +using Clustering +using CSV +using DataFrames +using Plots +using Statistics + +df = CSV.read("objs/margins.csv",DataFrame) + +function cluster_data(df::DataFrame, n_clusters::Int=3) + # Input validation + if nrow(df) < n_clusters + error("Number of rows ($(nrow(df))) must be greater than number of clusters ($n_clusters)") + end + + # Create position array based on order in dataframe + positions = collect(1:nrow(df)) + + # Extract features into a matrix - using position and margin + features = hcat(positions, df.margin)' + + # Normalize features to give equal weight + features_normalized = (features .- mean(features, dims=2)) ./ std(features, dims=2) + + # Perform k-means clustering + result = kmeans(features_normalized, n_clusters) + + # Add cluster assignments to the original dataframe + df_clustered = copy(df) + df_clustered.cluster = result.assignments + + # Calculate cluster statistics + cluster_stats = DataFrame() + for i in 1:n_clusters + cluster_indices = findall(x -> x == i, df_clustered.cluster) + cluster_data = df_clustered[cluster_indices, :] + stats = ( + cluster = i, + size = nrow(cluster_data), + mean_position = mean(positions[cluster_indices]), + mean_margin = mean(cluster_data.margin), + std_position = std(positions[cluster_indices]), + std_margin = std(cluster_data.margin) + ) + push!(cluster_stats, stats) + end + + # Define custom colors for clusters + cluster_colors = [:green, :orange, :yellow] + + # Create visualization with all specified formatting + plt = Plots.scatter( + positions, + 100 .* df_clustered.margin, # Multiply by 100 to convert to percentage + group=df_clustered.cluster, + xlabel="Order of AP Call", + ylabel="Democratic Margin (%)", + title="2020 Election", + legend=:topright, + yformatter=y->string(round(Int, y)) * "%", # Format as percentage with no decimals + markersize=8, + framestyle=:box, + grid=true, + gridlinewidth=0.5, + gridstyle=:dash, + gridcolor=:gray, + palette=cluster_colors, + legend_title="Clusters" + ) + + # Add emphasized zero line + hline!(plt, [0], color=:black, linewidth=1.5, label=nothing) + + return df_clustered, cluster_stats, plt +end + +# Example usage: +df_with_clusters, stats, cluster_plot = cluster_data(df) +display(cluster_plot) +println(stats) \ No newline at end of file diff --git a/_assets/scripts/cons.jl b/_assets/scripts/cons.jl index e6110ef..20df4c6 100644 --- a/_assets/scripts/cons.jl +++ b/_assets/scripts/cons.jl @@ -1,5 +1,3 @@ -# const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -# const states = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] const FLAGRED = "rgb(178, 34, 52)" const FLAGBLUE = "rgb( 60, 59, 110)" const PURPLE = "rgb(119, 47, 81)" diff --git a/_assets/scripts/data/2020age.csv b/_assets/scripts/data/2020age.csv new file mode 100644 index 0000000..ed7bca5 --- /dev/null +++ b/_assets/scripts/data/2020age.csv @@ -0,0 +1,39 @@ +st,cohort,totpop,cpop,reg,vot +AZ,18 to 24,653,629,371,327 +AZ,25 to 34,941,850,619,579 +AZ,35 to 44,929,756,565,509 +AZ,45 to 64,1833,1627,1301,1242 +AZ,65+,1282,1213,1023,992 +GA,18 to 24,990,925,556,489 +GA,25 to 34,1496,1354,913,794 +GA,35 to 44,1287,1083,723,690 +GA,45 to 64,2634,2454,1854,1783 +GA,65+,1625,1584,1187,1132 +MI,18 to 24,932,887,546,469 +MI,25 to 34,1344,1257,910,777 +MI,35 to 44,1130,1063,764,666 +MI,45 to 64,2663,2547,1969,1798 +MI,65+,1721,1713,1324,1284 +NV,18 to 24,284,262,110,96 +NV,25 to 34,463,415,275,236 +NV,35 to 44,352,310,193,176 +NV,45 to 64,804,734,505,481 +NV,65+,500,477,373,363 +NC,18 to 24,872,820,465,404 +NC,25 to 34,1412,1259,809,706 +NC,35 to 44,1315,1068,705,637 +NC,45 to 64,2524,2303,1699,1638 +NC,65+,1992,1941,1483,1396 +PA,18 to 24,1049,1017,601,519 +PA,25 to 34,1789,1747,1354,1207 +PA,35 to 44,1360,1281,948,866 +PA,45 to 64,3212,3122,2491,2315 +PA,65+,2492,2453,1943,1850 +PA,18 to 24,581,577,333,323 +PA,25 to 34,762,714,582,557 +PA,35 to 44,650,617,437,426 +PA,45 to 64,1604,1572,1241,1171 +PA,65+,941,941,797,776 +"Source: U.S. Census Bureau, Current Population Survey, November 2022",,,,, +"url: ""https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-585.html""",,,,, +"Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022",,,,, \ No newline at end of file diff --git a/_assets/scripts/data/2020states.csv b/_assets/scripts/data/2020states.csv new file mode 100644 index 0000000..00613f1 --- /dev/null +++ b/_assets/scripts/data/2020states.csv @@ -0,0 +1,8 @@ +st,totpop,eligible,registered,pctreg`,voted,pctvot +AZ,5638,5075,3878,76.4,3649,71.9 +GA,8032,7400,5233,70.7,4888,66.1 +MI,7790,7467,5513,73.8,4994,66.9 +NV,2402,2198,1455,66.2,1351,61.5 +NC,8113,7391,5161,69.8,4780,64.7 +PA,9902,9621,7337,76.3,6756,70.2 +WI,4538,4421,3391,76.7,3253,73.6 diff --git a/_assets/scripts/data/2020voter.csv b/_assets/scripts/data/2020voter.csv new file mode 100644 index 0000000..38bbb04 --- /dev/null +++ b/_assets/scripts/data/2020voter.csv @@ -0,0 +1,145 @@ +demograph,gender,cohort,registered,voted +Male over 18,m,121870,65.1,59.5 +18 to 24 years,m,14382,54.7,45.8 +25 to 34 years,m,22406,58.1,51.0 +35 to 44 years,m,20466,59.6,53.3 +45 to 54 years,m,19442,65.8,60.7 +55 to 64 years,m,20318,71.2,67.1 +65 to 74 years,m,15401,75.8,73.2 +75 years and over,m,9456,77.1,72.5 +18 years,m,1998,42.9,37.2 +19 years,m,1936,52.7,43.2 +20 years,m,2361,56.8,47.2 +21 years,m,2134,56.0,44.1 +22 years,m,1909,58.5,47.2 +23 years,m,2025,58.7,51.6 +24 years,m,2018,57.0,50.0 +25 years,m,2045,53.3,45.6 +26 years,m,2060,50.6,43.3 +27 years,m,2347,61.0,53.5 +28 years,m,2331,58.5,49.6 +29 years,m,2456,58.3,51.2 +30 years,m,2233,57.3,50.8 +31 years,m,2396,59.5,52.3 +32 years,m,2113,62.4,56.3 +33 years,m,2080,58.9,53.1 +34 years,m,2344,60.6,53.0 +35 years,m,2210,58.7,51.7 +36 years,m,2325,58.0,51.6 +37 years,m,2002,60.1,55.5 +38 years,m,2083,60.5,52.6 +39 years,m,1954,62.4,54.4 +40 years,m,2049,56.6,51.2 +41 years,m,1924,56.6,51.3 +42 years,m,1972,62.0,55.6 +43 years,m,1960,61.9,56.0 +44 years,m,1986,59.8,53.8 +45 years,m,1921,62.4,57.6 +46 years,m,1918,64.5,59.1 +47 years,m,1834,66.4,59.1 +48 years,m,1937,64.2,58.7 +49 years,m,1925,64.0,60.5 +50 years,m,2005,63.4,59.7 +51 years,m,2082,68.4,61.7 +52 years,m,1958,68.5,65.1 +53 years,m,1999,68.0,61.8 +54 years,m,1863,68.1,63.3 +55 years,m,2186,66.6,61.5 +56 years,m,1951,72.0,67.6 +57 years,m,1989,69.8,65.4 +58 years,m,2091,70.2,65.3 +59 years,m,1961,72.3,67.7 +60 years,m,2196,69.0,66.0 +61 years,m,2119,68.0,64.3 +62 years,m,1902,73.1,68.3 +63 years,m,1962,77.8,74.4 +64 years,m,1960,74.8,71.2 +65 years,m,1909,73.7,70.4 +66 years,m,1765,74.5,72.0 +67 years,m,1705,75.9,73.1 +68 years,m,1610,75.4,72.6 +69 years,m,1519,75.9,73.3 +70 years,m,1441,73.3,71.5 +71 years,m,1347,74.7,73.0 +72 years,m,1536,76.9,75.2 +73 years,m,1318,82.7,78.8 +74 years,m,1251,76.9,73.3 +75 years,m,1073,76.6,75.2 +76 years,m,901,82.0,77.7 +77 years,m,806,79.9,76.3 +78 years,m,859,81.5,77.4 +79 years,m,749,79.7,76.1 +80-84 years,m,2838,77.7,73.0 +85 years and over,m,2229,71.0,64.1 +Female 18 years and over,f,130404,68.2,63.0 +18 to 24 years,f,14277,56.8,50.2 +25 to 34 years,f,22466,63.8,56.4 +35 to 44 years,f,21092,64.7,59.3 +45 to 54 years,f,20316,68.5,64.0 +55 to 64 years,f,21837,73.4,69.7 +65 to 74 years,f,17553,76.0,72.8 +75 years and over,f,12864,74.4,68.5 +18 years,f,1928,48.4,43.1 +19 years,f,1872,55.4,50.5 +20 years,f,2213,58.0,50.8 +21 years,f,2045,53.7,48.0 +22 years,f,2108,62.7,53.8 +23 years,f,1935,62.4,53.8 +24 years,f,2176,56.7,50.7 +25 years,f,2010,62.1,54.2 +26 years,f,2201,61.6,54.4 +27 years,f,2389,63.9,55.2 +28 years,f,2187,62.7,54.4 +29 years,f,2413,64.5,58.6 +30 years,f,2504,64.2,55.4 +31 years,f,2225,64.0,56.4 +32 years,f,2212,67.4,61.5 +33 years,f,2304,62.9,56.5 +34 years,f,2022,64.0,57.3 +35 years,f,2295,64.4,57.5 +36 years,f,2264,65.4,59.1 +37 years,f,1992,61.2,55.8 +38 years,f,2325,70.5,64.5 +39 years,f,1970,66.1,61.3 +40 years,f,2250,64.3,59.2 +41 years,f,2028,65.6,60.1 +42 years,f,2052,61.9,58.4 +43 years,f,1944,63.2,59.4 +44 years,f,1974,63.6,57.2 +45 years,f,2101,62.9,59.0 +46 years,f,1896,67.4,61.9 +47 years,f,1956,65.2,60.8 +48 years,f,1984,68.5,63.0 +49 years,f,2038,68.6,64.1 +50 years,f,2192,71.9,68.4 +51 years,f,2180,67.7,62.6 +52 years,f,2042,70.4,65.4 +53 years,f,1975,72.8,68.9 +54 years,f,1951,69.9,65.3 +55 years,f,2299,70.4,67.5 +56 years,f,2126,68.1,63.9 +57 years,f,2006,77.7,71.9 +58 years,f,2117,70.5,66.9 +59 years,f,2293,74.0,69.6 +60 years,f,2326,74.6,71.4 +61 years,f,2241,71.5,68.3 +62 years,f,2125,76.5,73.0 +63 years,f,2116,77.2,74.3 +64 years,f,2187,74.1,70.8 +65 years,f,2084,73.8,71.7 +66 years,f,1979,77.5,73.8 +67 years,f,1895,74.9,71.6 +68 years,f,1826,74.3,71.8 +69 years,f,1766,78.0,74.6 +70 years,f,1740,72.6,69.7 +71 years,f,1642,76.5,73.0 +72 years,f,1640,79.5,75.5 +73 years,f,1633,78.4,74.3 +74 years,f,1348,75.4,72.5 +75 years,f,1176,81.6,76.2 +76 years,f,1228,77.1,73.6 +77 years,f,1138,77.1,74.3 +78 years,f,1077,81.1,78.1 +79 years,f,873,75.0,70.0 +80-84 years,f,3715,74.0,67.9 +85 years and over,f,3656,68.7,59.8 \ No newline at end of file diff --git a/_assets/scripts/data/2022age.csv b/_assets/scripts/data/2022age.csv new file mode 100644 index 0000000..be7d014 --- /dev/null +++ b/_assets/scripts/data/2022age.csv @@ -0,0 +1,39 @@ +st,cohort,totpop,cpop,reg,vot +AZ,18 to 24 ,751,694,322,170 +AZ,25 to 34 ,911,782,509,300 +AZ,35 to 44 ,937,800,532,428 +AZ,45 to 64 ,1800,1530,1148,975 +AZ,65 and over,1332,1287,1047,971 +GA,18 to 24 ,924,859,466,322 +GA,25 to 34 ,1620,1395,918,640 +GA,35 to 44 ,1400,1176,812,628 +GA,45 to 64 ,2610,2451,1695,1457 +GA,65 and over,1760,1720,1384,1276 +NC,18 to 24 ,921,866,372,40.3 +NC,25 to 34 ,1395,1236,652,46.7 +NC,35 to 44 ,1290,1069,675,52.3 +NC,45 to 64 ,2687,2523,1581,58.9 +NC,65 and over,1881,1838,1303,69.3 +MI,18 to 24 ,826,799,532,371 +MI,25 to 34 ,1304,1223,852,622 +MI,35 to 44 ,1228,1183,894,689 +MI,45 to 64 ,2639,2545,2025,1710 +MI,65 and over,1779,1767,1494,1365 +NV,18 to 24 ,297,287,122,63 +NV,25 to 34 ,414,355,222,153 +NV,35 to 44 ,406,358,229,170 +NV,45 to 64 ,789,694,458,378 +NV,65 and over,544,511,405,358 +PA,18 to 24 ,1145,1093,610,437 +PA,25 to 34 ,1680,1611,1041,776 +PA,35 to 44 ,1531,1397,1007,784 +PA,45 to 64 ,3139,3043,2328,1995 +PA,65 and over,2630,2597,2024,1851 +WI,18 to 24 ,588,579,341,286 +WI,25 to 34 ,724,679,474,371 +WI,35 to 44 ,693,669,447,373 +WI,45 to 64 ,1473,1440,1107,908 +WI,65 and over,1113,1095,856,777 +"Source: U.S. Census Bureau, Current Population Survey, November 2022",,,,, +https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-586.html,,,,, +"Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022",,,,, \ No newline at end of file diff --git a/_assets/scripts/data/ACS.csv b/_assets/scripts/data/ACS.csv new file mode 100644 index 0000000..091cbd5 --- /dev/null +++ b/_assets/scripts/data/ACS.csv @@ -0,0 +1,346 @@ +Label (Grouping),AZ,GA,MI,NV,NC,PA,WI +TOTAL NUMBER OF RACES REPORTED,,,,,,, +    Total population,"7,359,197","10,912,876","10,034,118","3,177,772","10,698,973","12,972,008","5,892,539" +        One race,80.6%,91.7%,92.9%,82.3%,92.1%,92.8%,92.1% +        Two races,18.5%,7.7%,6.7%,16.3%,7.4%,6.6%,7.5% +        Three races,0.8%,0.5%,0.4%,1.3%,0.5%,0.5%,0.4% +        Four or more races,0.1%,0.1%,0.0%,0.1%,0.1%,0.1%,0.0% +SEX AND AGE,,,,,,, +    Total population,"7,359,197","10,912,876","10,034,118","3,177,772","10,698,973","12,972,008","5,892,539" +        Male,50.0%,48.8%,49.6%,50.3%,48.9%,49.3%,50.2% +        Female,50.0%,51.2%,50.4%,49.7%,51.1%,50.7%,49.8% +Under 5 years,5.3%,5.7%,5.3%,5.4%,5.5%,5.2%,5.2% +5 to 17 years,16.2%,17.3%,15.6%,16.3%,16.0%,15.1%,15.8% +18 to 24 years,9.8%,9.8%,9.5%,8.3%,9.7%,9.2%,9.5% +25 to 34 years,13.8%,13.6%,13.1%,14.4%,13.3%,12.9%,12.5% +35 to 44 years,12.6%,13.5%,12.2%,13.9%,12.9%,12.5%,12.6% +45 to 54 years,11.6%,12.8%,12.0%,12.5%,12.6%,11.9%,11.8% +55 to 64 years,11.8%,12.2%,13.6%,12.3%,12.7%,13.6%,13.9% +65 to 74 years,10.6%,9.2%,11.2%,10.2%,10.4%,11.3%,11.2% +75 years and over,8.2%,5.9%,7.5%,6.7%,7.0%,8.3%,7.5% +        Median age (years),38.8,37.6,40.3,39.0,39.2,40.9,40.4 +18 years and over,78.4%,77.0%,79.0%,78.3%,78.6%,79.8%,78.9% +21 years and over,74.5%,72.8%,75.0%,74.8%,74.4%,75.6%,74.8% +62 years and over,22.5%,18.6%,23.0%,20.5%,21.4%,23.9%,23.0% +65 years and over,18.8%,15.1%,18.7%,16.9%,17.4%,19.6%,18.7% +Under 18 years,"1,587,603","2,505,668","2,106,228","689,653","2,292,928","2,622,158","1,241,780" +            Male,51.1%,51.2%,51.3%,50.8%,51.2%,51.1%,51.7% +            Female,48.9%,48.8%,48.7%,49.2%,48.8%,48.9%,48.3% +18 years and over,"5,771,594","8,407,208","7,927,890","2,488,119","8,406,045","10,349,850","4,650,759" +            Male,49.7%,48.1%,49.2%,50.2%,48.3%,48.9%,49.8% +            Female,50.3%,51.9%,50.8%,49.8%,51.7%,51.1%,50.2% +18 to 34 years,"1,736,629","2,558,225","2,264,311","720,689","2,454,354","2,875,427","1,295,988" +            Male,51.9%,50.0%,51.2%,51.5%,50.3%,50.8%,51.4% +            Female,48.1%,50.0%,48.8%,48.5%,49.7%,49.2%,48.6% +35 to 64 years,"2,653,011","4,204,708","3,786,017","1,228,939","4,085,077","4,935,369","2,252,385" +            Male,50.2%,48.6%,49.9%,50.9%,49.0%,50.0%,50.7% +            Female,49.8%,51.4%,50.1%,49.1%,51.0%,50.0%,49.3% +65 years and over,"1,381,954","1,644,275","1,877,562","538,491","1,866,614","2,539,054","1,102,386" +            Male,46.0%,43.8%,45.2%,46.8%,44.0%,44.5%,46.3% +            Female,54.0%,56.2%,54.8%,53.2%,56.0%,55.5%,53.7% +RELATIONSHIP,,,,,,, +    Population in households,"7,204,265","10,662,548","9,821,154","3,142,947","10,417,729","12,540,001","5,755,117" +        Householder or spouse,58.0%,56.4%,60.6%,54.9%,61.0%,61.8%,63.6% +        Unmarried partner,3.3%,2.3%,3.1%,3.3%,2.6%,3.1%,3.7% +        Child,27.8%,30.0%,28.3%,28.3%,27.6%,27.4%,26.6% +        Other relatives,7.4%,8.3%,5.1%,9.5%,6.1%,5.3%,3.4% +        Other nonrelatives,3.5%,3.0%,2.8%,4.0%,2.7%,2.4%,2.7% +HOUSEHOLDS BY TYPE,,,,,,, +    Households,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        Family households,64.7%,66.8%,62.3%,64.6%,64.8%,62.2%,60.7% +With own children of the householder under 18 years,25.2%,27.8%,24.0%,25.6%,25.9%,23.9%,24.1% +        Married-couple family,46.7%,46.9%,45.7%,44.2%,47.9%,46.5%,47.0% +With own children of the householder under 18 years,16.6%,18.1%,16.0%,16.0%,17.3%,16.3%,16.5% +"        Female householder, no spouse present, family",11.8%,15.0%,11.7%,13.3%,12.5%,11.2%,9.1% +With own children of the householder under 18 years,5.8%,7.6%,5.8%,6.7%,6.6%,5.6%,5.2% +        Nonfamily households,35.3%,33.2%,37.7%,35.4%,35.2%,37.8%,39.3% +            Male householder,16.9%,15.1%,18.1%,18.2%,15.7%,17.3%,19.3% +                Living alone,12.6%,11.6%,14.3%,14.0%,12.4%,13.7%,14.7% +                Not living alone,4.4%,3.5%,3.8%,4.1%,3.3%,3.6%,4.6% +            Female householder,18.4%,18.1%,19.6%,17.3%,19.5%,20.4%,20.1% +                Living alone,14.6%,15.4%,16.3%,13.5%,16.4%,16.9%,16.3% +                Not living alone,3.8%,2.6%,3.3%,3.8%,3.0%,3.5%,3.8% +        Average household size,2.53,2.61,2.40,2.62,2.42,2.37,2.31 +        Average family size,3.10,3.19,3.02,3.21,3.00,2.99,2.92 +MARITAL STATUS,,,,,,, +Population 15 years and over,"6,063,874","8,867,492","8,310,382","2,612,414","8,814,897","10,822,275","4,880,508" +"        Now married, except separated",47.4%,46.9%,47.4%,45.2%,49.5%,48.1%,49.8% +        Widowed,5.3%,5.4%,5.9%,5.3%,5.7%,6.3%,5.3% +        Divorced,11.4%,11.1%,11.2%,13.1%,10.3%,9.6%,10.7% +        Separated,1.4%,1.8%,1.1%,1.7%,2.1%,1.7%,0.9% +        Never married,34.5%,34.8%,34.4%,34.6%,32.4%,34.4%,33.4% +Male 15 years and over,"3,017,075","4,277,823","4,095,300","1,311,824","4,267,986","5,300,790","2,435,440" +"        Now married, except separated",48.3%,49.5%,48.6%,46.1%,51.9%,50.0%,50.5% +        Widowed,2.7%,2.5%,2.9%,2.7%,2.8%,2.9%,2.7% +        Divorced,9.9%,9.3%,10.0%,11.6%,8.5%,8.5%,9.8% +        Separated,1.2%,1.5%,1.0%,1.3%,1.9%,1.6%,0.7% +        Never married,37.9%,37.3%,37.5%,38.3%,34.9%,37.1%,36.4% +Female 15 years and over,"3,046,799","4,589,669","4,215,082","1,300,590","4,546,911","5,521,485","2,445,068" +"        Now married, except separated",46.5%,44.6%,46.2%,44.4%,47.3%,46.2%,49.1% +        Widowed,7.9%,8.0%,8.8%,8.0%,8.5%,9.6%,7.8% +        Divorced,12.9%,12.7%,12.4%,14.6%,11.9%,10.6%,11.5% +        Separated,1.6%,2.2%,1.2%,2.1%,2.3%,1.8%,1.1% +        Never married,31.1%,32.4%,31.4%,30.9%,30.1%,31.8%,30.4% +SCHOOL ENROLLMENT,,,,,,, +Population 3 years and over enrolled in school,"1,720,168","2,772,163","2,291,873","697,833","2,483,789","2,909,535","1,350,029" +"        Nursery school, preschool",4.2%,5.8%,5.8%,4.3%,5.3%,5.5%,5.4% +        Kindergarten,4.8%,4.9%,5.1%,5.7%,5.0%,4.7%,5.3% +Elementary school (grades 1-8),41.4%,41.0%,40.4%,44.1%,41.1%,40.3%,41.1% +High school (grades 9-12),23.0%,22.7%,22.2%,23.7%,22.0%,21.4%,22.4% +        College or graduate school,26.6%,25.7%,26.5%,22.1%,26.6%,28.0%,25.8% +Male 3 years and over enrolled in school,"858,679","1,358,342","1,135,923","344,041","1,222,590","1,431,980","672,243" +Percent enrolled in kindergarten to grade 12,70.8%,71.9%,70.1%,76.4%,71.3%,69.1%,71.7% +            Percent enrolled in college or graduate school,24.7%,22.1%,23.6%,19.5%,23.1%,24.9%,22.7% +Female 3 years and over enrolled in school,"861,489","1,413,821","1,155,950","353,792","1,261,199","1,477,555","677,786" +Percent enrolled in kindergarten to grade 12,67.8%,65.2%,65.3%,70.8%,64.9%,63.9%,66.0% +            Percent enrolled in college or graduate school,28.4%,29.2%,29.3%,24.7%,30.1%,31.1%,28.8% +EDUCATIONAL ATTAINMENT,,,,,,, +Population 25 years and over,"5,053,656","7,332,980","6,978,952","2,223,852","7,372,120","9,151,744","4,088,500" +        Less than high school diploma,10.8%,10.5%,8.2%,12.6%,9.8%,7.8%,6.5% +        High school graduate (includes equivalency),23.8%,27.0%,28.1%,27.9%,24.9%,33.0%,29.6% +        Some college or associate's degree,32.4%,27.8%,31.6%,32.5%,29.4%,24.1%,30.7% +        Bachelor's degree,20.4%,20.7%,19.5%,17.6%,22.8%,20.8%,21.7% +        Graduate or professional degree,12.5%,14.0%,12.6%,9.5%,13.2%,14.3%,11.6% +        High school graduate or higher,89.2%,89.5%,91.8%,87.4%,90.2%,92.2%,93.5% +"            Male, high school graduate or higher",88.9%,88.6%,91.2%,86.9%,88.8%,91.8%,92.5% +"            Female, high school graduate or higher",89.4%,90.4%,92.5%,87.9%,91.4%,92.5%,94.4% +        Bachelor's degree or higher,33.0%,34.7%,32.1%,27.0%,35.9%,35.1%,33.2% +"            Male, bachelor's degree or higher",32.7%,33.3%,31.2%,25.9%,34.2%,34.0%,31.0% +"            Female, bachelor's degree or higher",33.2%,35.9%,33.0%,28.2%,37.5%,36.1%,35.4% +FERTILITY,,,,,,, +Women 15 to 50 years,"1,680,785","2,675,339","2,235,671","741,887","2,518,824","2,881,967","1,301,817" +Women 15 to 50 years who had a birth in the past 12 months,"86,548","151,128","111,639","41,310","129,267","149,542","66,580" +Unmarried women 15 to 50 years who had a birth in the past 12 months,"30,022","54,424","36,943","12,221","42,336","41,688","18,432" +As a percent of all women with a birth in the past 12 months,34.7%,36.0%,33.1%,29.6%,32.8%,27.9%,27.7% +RESPONSIBILITY FOR GRANDCHILDREN UNDER 18 YEARS,,,,,,, +Population 30 years and over,"4,546,407","6,602,024","6,330,291","2,005,818","6,677,445","8,347,825","3,722,339" +        Grandparents living with grandchild(ren),3.4%,3.8%,2.4%,4.1%,2.9%,2.5%,1.5% +            Grandparents responsible for grandchildren as a percentage of living with grandchildren,31.3%,37.0%,30.7%,27.6%,41.6%,31.1%,33.6% +VETERAN STATUS,,,,,,, +Civilian population 18 years and over,"5,747,509","8,347,433","7,923,161","2,473,493","8,294,906","10,341,435","4,646,486" +        Civilian veteran,7.9%,7.3%,5.8%,8.3%,7.5%,6.2%,6.1% +DISABILITY STATUS,,,,,,, +    Total civilian noninstitutionalized population,"7,251,924","10,718,050","9,929,781","3,139,304","10,480,843","12,789,843","5,831,451" +        With a disability,13.6%,13.3%,14.3%,14.3%,13.7%,14.6%,12.5% +Civilian noninstitutionalized population under 18 years,"1,585,268","2,503,322","2,103,940","688,935","2,290,759","2,618,106","1,240,934" +        With a disability,5.1%,5.3%,5.1%,5.3%,4.6%,5.7%,4.2% +Civilian noninstitutionalized population 18 to 64 years,"4,304,458","6,607,703","5,987,728","1,916,374","6,365,446","7,714,886","3,513,627" +        With a disability,10.9%,11.2%,12.2%,11.9%,11.4%,12.0%,10.4% +Civilian noninstitutionalized population 65 years and older,"1,362,198","1,607,025","1,838,113","533,995","1,824,638","2,456,851","1,076,890" +        With a disability,31.9%,34.7%,31.9%,34.4%,33.3%,31.9%,28.7% +RESIDENCE 1 YEAR AGO,,,,,,, +Population 1 year and over,"7,285,247","10,791,161","9,936,710","3,145,500","10,588,557","12,845,436","5,835,492" +        Same house,86.0%,86.6%,88.4%,86.4%,87.3%,89.3%,87.7% +        Different house in the U.S.,13.4%,12.8%,11.1%,13.1%,12.2%,10.3%,11.9% +            Same county,7.9%,5.2%,6.1%,8.3%,5.2%,5.7%,6.3% +            Different county,5.5%,7.6%,5.1%,4.8%,6.9%,4.6%,5.5% +                Same state,1.6%,4.6%,3.5%,0.8%,3.7%,2.5%,3.5% +                Different state,3.9%,3.0%,1.6%,4.1%,3.2%,2.0%,2.1% +        Abroad,0.6%,0.6%,0.4%,0.5%,0.6%,0.4%,0.4% +"PLACE OF BIRTH, CITIZENSHIP STATUS AND YEAR OF ENTRY",,,,,,, +    Native,"6,396,509","9,744,854","9,338,915","2,576,815","9,782,186","11,993,835","5,597,798" +        Male,50.2%,48.6%,49.6%,50.9%,48.8%,49.3%,50.3% +        Female,49.8%,51.4%,50.4%,49.1%,51.2%,50.7%,49.7% +    Foreign born,"962,688","1,168,022","695,203","600,957","916,787","978,173","294,741" +        Male,48.6%,49.9%,49.3%,48.0%,49.5%,49.2%,49.3% +        Female,51.4%,50.1%,50.7%,52.0%,50.5%,50.8%,50.7% +        Foreign born; naturalized U.S. citizen,"477,730","589,710","396,976","324,092","404,205","552,582","141,128" +            Male,46.8%,47.7%,48.0%,44.8%,47.3%,47.4%,45.4% +            Female,53.2%,52.3%,52.0%,55.2%,52.7%,52.6%,54.6% +        Foreign born; not a U.S. citizen,"484,958","578,312","298,227","276,865","512,582","425,591","153,613" +            Male,50.4%,52.2%,51.0%,51.6%,51.2%,51.6%,52.8% +            Female,49.6%,47.8%,49.0%,48.4%,48.8%,48.4%,47.2% +    Population born outside the United States,"962,688","1,168,022","695,203","600,957","916,787","978,173","294,741" +Entered 2010 or later,27.7%,34.3%,38.4%,23.5%,35.9%,38.4%,35.8% +Entered 2000 to 2009,22.7%,26.7%,21.6%,24.5%,26.6%,23.7%,23.4% +Entered before 2000,49.6%,39.0%,39.9%,52.0%,37.6%,37.9%,40.8% +WORLD REGION OF BIRTH OF FOREIGN BORN,,,,,,, +    Foreign-born population excluding population born at sea,"962,688","1,168,022","695,203","600,957","916,787","978,173","294,741" +        Europe,8.0%,7.6%,16.7%,6.8%,12.0%,16.6%,15.2% +        Asia,21.9%,30.5%,53.7%,32.7%,28.0%,37.7%,34.8% +        Africa,4.1%,11.7%,5.7%,2.9%,8.3%,9.1%,7.1% +        Oceania,0.5%,0.4%,0.4%,0.6%,0.4%,0.3%,0.3% +        Latin America,61.7%,48.4%,18.7%,55.0%,49.1%,34.4%,40.5% +        Northern America,3.7%,1.5%,4.8%,2.0%,2.2%,1.9%,2.2% +LANGUAGE SPOKEN AT HOME AND ABILITY TO SPEAK ENGLISH,,,,,,, +Population 5 years and over,"6,965,784","10,291,750","9,497,313","3,005,197","10,114,481","12,303,274","5,583,295" +        English only,73.8%,85.1%,89.8%,70.1%,87.3%,87.7%,91.3% +        Language other than English,26.2%,14.9%,10.2%,29.9%,12.7%,12.3%,8.7% +"            Speak English less than ""very well""",8.2%,5.5%,3.7%,11.0%,4.8%,5.0%,3.2% +EMPLOYMENT STATUS,,,,,,, +Population 16 years and over,"5,961,733","8,708,310","8,179,427","2,572,023","8,671,939","10,660,341","4,802,830" +        In labor force,60.7%,63.9%,61.6%,63.3%,62.8%,62.8%,65.1% +            Civilian labor force,60.3%,63.2%,61.5%,62.7%,61.5%,62.8%,65.0% +                Employed,57.7%,60.6%,58.7%,59.3%,59.2%,60.1%,63.2% +                Unemployed,2.6%,2.6%,2.9%,3.4%,2.3%,2.7%,1.8% +                    Unemployment Rate,4.3%,4.2%,4.6%,5.5%,3.8%,4.3%,2.8% +            Armed Forces,0.4%,0.7%,0.1%,0.6%,1.3%,0.1%,0.1% +        Not in labor force,39.3%,36.1%,38.4%,36.7%,37.2%,37.2%,34.9% +Females 16 years and over,"2,995,623","4,509,831","4,152,360","1,279,958","4,477,069","5,443,468","2,407,021" +        In labor force,55.5%,59.4%,57.3%,58.6%,58.1%,58.7%,61.4% +            Civilian labor force,55.4%,59.2%,57.2%,58.5%,57.8%,58.6%,61.4% +                Employed,52.9%,56.5%,54.7%,55.1%,55.6%,56.2%,59.7% +                Unemployed,2.5%,2.7%,2.6%,3.4%,2.2%,2.4%,1.6% +                    Unemployment Rate,4.5%,4.5%,4.5%,5.8%,3.8%,4.1%,2.6% +COMMUTING TO WORK,,,,,,, +Workers 16 years and over,"3,402,927","5,214,843","4,706,068","1,506,293","5,130,773","6,283,929","2,991,638" +"        Car, truck, or van - drove alone",66.1%,70.5%,74.0%,70.0%,71.2%,68.8%,73.9% +"        Car, truck, or van - carpooled",9.8%,9.0%,7.9%,11.2%,8.5%,7.5%,7.8% +        Public transportation (excluding taxicab),0.8%,1.1%,0.8%,2.2%,0.5%,3.4%,1.1% +        Walked,1.7%,1.3%,2.0%,1.4%,1.6%,3.2%,2.7% +        Other means,2.4%,1.8%,1.6%,3.0%,1.4%,2.0%,1.6% +        Worked from home,19.2%,16.3%,13.7%,12.2%,16.8%,15.2%,13.0% +        Mean travel time to work (minutes),24.9,28.2,24.2,24.5,25.1,26.4,22.2 +OCCUPATION,,,,,,, +Civilian employed population 16 years and over,"3,441,676","5,273,176","4,800,228","1,524,894","5,135,307","6,402,242","3,036,963" +"        Management, business, science, and arts occupations",40.9%,41.4%,40.6%,33.5%,42.0%,43.0%,39.9% +        Service occupations,17.1%,14.6%,15.9%,22.6%,15.3%,16.0%,14.9% +        Sales and office occupations,22.3%,20.9%,19.3%,21.9%,19.9%,19.2%,18.9% +"        Natural resources, construction, and maintenance occupations",8.8%,8.1%,7.9%,8.9%,8.7%,7.6%,8.6% +"        Production, transportation, and material moving occupations",10.9%,15.1%,16.3%,13.0%,14.1%,14.2%,17.6% +Male civilian employed population 16 years and over,"1,855,786","2,723,387","2,530,898","820,038","2,646,717","3,340,647","1,598,848" +"        Management, business, science, and arts occupations",37.3%,36.9%,37.0%,29.8%,37.1%,38.5%,34.4% +        Service occupations,15.3%,12.4%,12.1%,20.6%,12.8%,12.6%,11.4% +        Sales and office occupations,17.0%,14.5%,13.5%,16.1%,14.2%,14.2%,13.3% +"        Natural resources, construction, and maintenance occupations",15.5%,14.8%,14.3%,15.7%,15.9%,13.9%,15.5% +"        Production, transportation, and material moving occupations",15.0%,21.4%,23.0%,17.8%,20.0%,20.8%,25.3% +Female civilian employed population 16 years and over,"1,585,890","2,549,789","2,269,330","704,856","2,488,590","3,061,595","1,438,115" +"        Management, business, science, and arts occupations",45.1%,46.2%,44.7%,37.8%,47.3%,47.9%,46.1% +        Service occupations,19.2%,16.9%,20.0%,25.0%,18.0%,19.6%,18.7% +        Sales and office occupations,28.6%,27.7%,25.8%,28.7%,26.0%,24.7%,25.2% +"        Natural resources, construction, and maintenance occupations",0.9%,0.8%,0.8%,1.0%,1.0%,0.7%,0.9% +"        Production, transportation, and material moving occupations",6.1%,8.4%,8.7%,7.5%,7.7%,7.0%,9.1% +INDUSTRY,,,,,,, +Civilian employed population 16 years and over,"3,441,676","5,273,176","4,800,228","1,524,894","5,135,307","6,402,242","3,036,963" +"        Agriculture, forestry, fishing and hunting, and mining",1.4%,0.9%,1.1%,1.4%,1.1%,1.2%,2.2% +        Construction,7.7%,6.8%,5.9%,7.5%,7.2%,5.8%,6.2% +        Manufacturing,7.5%,10.4%,18.2%,5.5%,11.7%,11.0%,18.4% +        Wholesale trade,1.9%,2.4%,1.9%,2.0%,2.0%,2.3%,2.4% +        Retail trade,12.2%,11.4%,10.7%,11.3%,11.3%,11.5%,10.9% +"        Transportation and warehousing, and utilities",6.1%,7.6%,5.1%,7.3%,5.5%,6.2%,4.9% +        Information,1.4%,2.3%,1.3%,1.7%,1.6%,1.4%,1.5% +"        Finance and insurance, and real estate and rental and leasing",8.9%,6.4%,5.8%,5.9%,7.2%,6.7%,6.1% +"        Professional, scientific, and management, and administrative and waste management services",12.5%,13.3%,10.2%,12.8%,12.9%,11.2%,9.2% +"        Educational services, and health care and social assistance",21.4%,20.5%,23.0%,16.2%,22.2%,26.6%,23.2% +"        Arts, entertainment, and recreation, and accommodation and food services",9.6%,8.4%,8.7%,19.9%,8.3%,7.4%,7.3% +        Other services (except public administration),4.6%,4.8%,4.5%,4.9%,4.9%,4.6%,4.2% +        Public administration,4.8%,4.8%,3.5%,3.5%,4.1%,3.9%,3.6% +CLASS OF WORKER,,,,,,, +Civilian employed population 16 years and over,"3,441,676","5,273,176","4,800,228","1,524,894","5,135,307","6,402,242","3,036,963" +        Private wage and salary workers,80.3%,80.0%,83.1%,82.5%,80.6%,83.5%,81.9% +        Government workers,13.6%,14.2%,11.4%,11.8%,13.5%,11.3%,12.8% +        Self-employed workers in own not incorporated business,5.8%,5.7%,5.3%,5.4%,5.8%,5.0%,5.2% +        Unpaid family workers,0.2%,0.2%,0.1%,0.3%,0.2%,0.2%,0.2% +INCOME IN THE PAST 12 MONTHS (IN 2022 INFLATION-ADJUSTED DOLLARS),,,,,,, +    Households,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        Median household income (dollars),"74,568","72,837","66,986","72,333","67,481","71,798","70,996" +        With earnings,75.2%,79.5%,74.2%,77.3%,76.7%,75.0%,76.0% +            Mean earnings (dollars),"102,494","101,642","94,540","97,079","96,470","103,792","96,513" +        With Social Security income,33.4%,29.3%,34.6%,31.2%,31.8%,35.0%,32.2% +            Mean Social Security income (dollars),"23,704","21,670","23,068","21,342","22,539","22,575","23,279" +        With Supplemental Security Income,4.0%,5.1%,5.6%,4.7%,4.7%,5.6%,4.5% +            Mean Supplemental Security Income (dollars),"10,678","10,304","11,164","11,287","10,492","10,840","11,207" +        With cash public assistance income,1.9%,1.7%,2.5%,3.0%,1.6%,3.3%,2.0% +            Mean cash public assistance income (dollars),"3,724","3,549","3,460","3,758","3,315","3,092","3,344" +        With retirement income,26.7%,22.8%,27.9%,24.3%,24.5%,27.4%,26.4% +            Mean retirement income (dollars),"31,251","29,625","26,950","33,150","28,316","27,849","27,551" +        With Food Stamp/SNAP benefits,10.3%,13.2%,13.6%,13.4%,13.4%,14.4%,11.7% +    Families,"1,843,530","2,733,234","2,548,560","773,666","2,785,497","3,294,814","1,511,105" +        Median family income (dollars),"88,679","86,642","85,865","85,593","83,448","93,029","91,700" +            Married-couple family,72.3%,70.2%,73.3%,68.5%,73.9%,74.7%,77.6% +        Median income (dollars),"103,182","105,880","102,076","100,620","99,793","109,173","105,109" +"            Male householder, no spouse present, family",9.4%,7.3%,7.9%,10.8%,6.8%,7.2%,7.5% +        Median income (dollars),"64,779","63,120","60,615","69,898","56,963","65,099","64,141" +"            Female householder, no husband present, family",18.3%,22.5%,18.8%,20.7%,19.4%,18.0%,15.0% +        Median income (dollars),"51,649","47,661","44,192","51,080","43,242","46,054","45,236" +    Individuals,"7,359,197","10,912,876","10,034,118","3,177,772","10,698,973","12,972,008","5,892,539" +        Per capita income (dollars),"39,819","38,378","38,151","38,183","38,701","41,489","40,188" +"        With earnings for full-time, year-round workers:",,,,,,, +            Male,"1,478,889","2,196,252","1,938,740","636,702","2,175,288","2,635,037","1,241,897" +            Female,"1,080,442","1,800,677","1,436,983","480,066","1,711,122","2,015,147","936,639" +"        Mean earnings (dollars) for full-time, year-round workers:",,,,,,, +            Male,"81,123","83,251","81,467","74,052","80,257","86,494","80,588" +            Female,"64,020","62,404","61,245","62,377","61,140","65,618","60,832" +"        Median earnings (dollars) full-time, year-round workers:",,,,,,, +            Male,"57,628","58,853","61,623","53,821","55,156","63,487","61,280" +            Female,"50,126","48,397","49,665","46,691","47,092","52,070","49,582" +HEALTH INSURANCE COVERAGE,,,,,,, +    Civilian noninstitutionalized population,"7,251,924","10,718,050","9,929,781","3,139,304","10,480,843","12,789,843","5,831,451" +        With private health insurance,63.9%,66.6%,70.4%,63.4%,67.8%,71.2%,73.3% +        With public coverage,38.3%,33.0%,41.0%,36.9%,35.9%,38.8%,35.7% +        No health insurance coverage,10.3%,11.7%,4.5%,11.1%,9.3%,5.3%,5.2% +POVERTY RATES FOR FAMILIES AND PEOPLE FOR WHOM POVERTY STATUS IS DETERMINED,,,,,,, +    All families,8.9%,9.4%,9.1%,9.1%,9.3%,7.9%,6.8% +With related children of the householder under 18 years,13.3%,13.9%,15.1%,14.0%,14.6%,12.4%,10.9% +With related children of the householder under 5 years only,11.8%,12.0%,13.7%,12.6%,12.7%,11.4%,11.1% +        Married-couple family,5.6%,4.6%,4.5%,5.4%,4.5%,3.9%,3.4% +With related children of the householder under 18 years,7.3%,5.6%,6.5%,7.2%,5.6%,4.8%,4.1% +With related children of the householder under 5 years only,5.5%,3.2%,4.0%,4.5%,4.2%,4.6%,3.8% +"        Female householder, no spouse present, family",20.9%,23.2%,25.3%,21.1%,26.3%,23.2%,23.1% +With related children of the householder under 18 years,29.3%,30.6%,35.9%,28.9%,35.1%,31.5%,30.2% +With related children of the householder under 5 years only,31.1%,31.1%,41.4%,32.3%,36.5%,31.6%,33.0% +    All people,12.5%,12.7%,13.4%,12.5%,12.8%,11.8%,10.7% +Under 18 years,15.8%,16.6%,18.2%,16.1%,17.2%,15.2%,12.7% +Related children of the householder under 18 years,15.5%,16.3%,17.8%,15.8%,16.9%,15.0%,12.4% +Related children of the householder under 5 years,17.7%,18.0%,19.8%,17.2%,18.3%,16.2%,13.8% +Related children of the householder 5 to 17 years,14.7%,15.8%,17.1%,15.3%,16.4%,14.5%,11.9% +18 years and over,11.5%,11.5%,12.1%,11.4%,11.5%,10.9%,10.2% +18 to 64 years,11.9%,11.6%,12.8%,11.6%,11.7%,11.2%,10.3% +65 years and over,10.4%,11.1%,9.8%,10.8%,10.9%,10.1%,9.6% +        People in families,9.8%,10.1%,10.2%,9.6%,10.1%,8.6%,7.3% +Unrelated individuals 15 years and over,22.7%,24.4%,25.0%,23.3%,23.7%,23.5%,21.8% +HOUSING TENURE,,,,,,, +    Occupied housing units,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        Owner-occupied housing units,67.4%,65.9%,73.2%,60.3%,66.7%,69.1%,68.1% +        Renter-occupied housing units,32.6%,34.1%,26.8%,39.7%,33.3%,30.9%,31.9% +        Average household size of owner-occupied unit,2.59,2.71,2.52,2.69,2.53,2.52,2.47 +        Average household size of renter-occupied unit,2.39,2.41,2.08,2.53,2.20,2.03,1.97 +UNITS IN STRUCTURE,,,,,,, +    Occupied housing units,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +"1-unit, detached or attached",71.4%,72.4%,77.4%,68.0%,71.4%,76.0%,70.8% +2 to 4 units,4.4%,5.2%,4.6%,7.0%,4.6%,8.0%,9.1% +5 or more units,16.0%,14.9%,13.2%,19.6%,13.5%,12.8%,17.5% +"        Mobile home, boat, RV, van, etc.",8.2%,7.5%,4.9%,5.3%,10.5%,3.3%,2.6% +YEAR STRUCTURE BUILT,,,,,,, +    Occupied housing units,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +Built 2020 or later,2.7%,2.6%,0.9%,2.8%,2.9%,0.9%,1.4% +Built 2010 to 2019,12.6%,13.0%,5.6%,13.9%,15.3%,5.6%,7.8% +Built 2000 to 2009,23.2%,21.5%,10.5%,26.2%,19.4%,8.6%,12.8% +Built 1980 to 1999,32.2%,33.1%,21.9%,36.2%,30.0%,18.4%,21.4% +Built 1960 to 1979,21.4%,18.9%,26.5%,16.4%,19.4%,22.6%,23.2% +Built 1940 to 1959,6.6%,7.4%,20.9%,3.7%,8.7%,20.2%,15.5% +Built 1939 or earlier,1.3%,3.5%,13.7%,0.8%,4.4%,23.7%,18.0% +VEHICLES AVAILABLE,,,,,,, +    Occupied housing units,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        None,5.1%,5.7%,6.9%,7.0%,5.0%,10.5%,6.5% +1 or more,94.9%,94.3%,93.1%,93.0%,95.0%,89.5%,93.5% +HOUSE HEATING FUEL,,,,,,, +    Occupied housing units,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        Gas,35.8%,41.7%,83.4%,62.0%,30.3%,56.5%,76.7% +        Electricity,60.2%,56.7%,12.3%,34.4%,65.7%,25.3%,17.7% +        All other fuels,3.0%,0.8%,3.8%,3.0%,3.4%,17.7%,5.0% +        No fuel used,1.0%,0.8%,0.5%,0.7%,0.6%,0.5%,0.6% +SELECTED CHARACTERISTICS,,,,,,, +    Occupied housing units,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        No telephone service available,1.3%,0.7%,0.8%,1.2%,0.9%,1.0%,0.8% +1.01 or more occupants per room,4.5%,2.4%,1.6%,4.6%,2.3%,1.7%,1.5% +SELECTED MONTHLY OWNER COSTS AS A PERCENTAGE OF HOUSEHOLD INCOME IN THE PAST 12 MONTHS,,,,,,, +    Housing units with a mortgage (excluding units where SMOC cannot be computed),"1,180,749","1,705,941","1,724,683","473,798","1,770,630","2,114,599","1,031,942" +Less than 30 percent,73.7%,75.0%,76.0%,69.0%,76.3%,75.8%,76.5% +30 percent or more,26.3%,25.0%,24.0%,31.0%,23.7%,24.2%,23.5% +OWNER CHARACTERISTICS,,,,,,, +    Owner-occupied housing units,"1,921,746","2,695,885","2,991,685","722,684","2,868,467","3,658,207","1,696,493" +        Median value (dollars),"402,800","297,400","224,400","434,700","280,600","245,500","252,800" +        Median selected monthly owner costs with a mortgage (dollars),"1,616","1,599","1,435","1,730","1,444","1,601","1,545" +        Median selected monthly owner costs without a mortgage (dollars),468,488,565,486,444,597,616 +GROSS RENT AS A PERCENTAGE OF HOUSEHOLD INCOME IN THE PAST 12 MONTHS,,,,,,, +    Occupied units paying rent (excluding units where GRAPI cannot be computed),"867,455","1,284,614","1,008,054","450,409","1,300,902","1,504,487","748,787" +Less than 30 percent,47.2%,48.2%,49.2%,42.7%,51.6%,51.4%,54.6% +30 percent or more,52.8%,51.8%,50.8%,57.3%,48.4%,48.6%,45.4% +GROSS RENT,,,,,,, +    Occupied units paying rent,"887,809","1,320,725","1,034,449","462,009","1,331,663","1,540,239","763,110" +        Median gross rent (dollars),"1,450","1,269","1,052","1,461","1,131","1,116",992 +COMPUTERS AND INTERNET USE,,,,,,, +    Total households,"2,850,377","4,092,467","4,089,794","1,198,356","4,299,266","5,294,065","2,491,121" +        With a computer,96.4%,96.2%,95.5%,97.0%,95.4%,94.2%,94.9% +        With a broadband Internet subscription,91.1%,91.2%,90.5%,91.5%,90.2%,89.9%,90.6% \ No newline at end of file diff --git a/_assets/scripts/data/az.csv b/_assets/scripts/data/az.csv new file mode 100644 index 0000000..1191fb6 --- /dev/null +++ b/_assets/scripts/data/az.csv @@ -0,0 +1,37 @@ +Atlas Intel 10/12 - 10/17 1440 LV 3.0 49 49 Tie +Atlas Intel 10/30 - 10/31 1005 LV 3.0 51 47 Trump +4 +Atlas Intel 9/20 - 9/25 946 LV 3.0 50 49 Trump +1 +Bloomberg 10/16 - 10/20 915 LV 3.0 49 49 Tie +Bloomberg 9/19 - 9/25 926 LV 3.0 47 50 Harris +3 +CBS News 10/11 - 10/16 1435 LV 3.3 51 48 Trump +3 +CNN* 10/21 - 10/26 781 LV 4.4 47 48 Harris +1 +CNN* 8/23 - 8/29 682 LV 4.7 49 44 Trump +5 +Cook Political Report 7/26 - 8/2 435 LV — 46 48 Harris +2 +Cook Political Report 9/19 - 9/25 409 LV — 48 50 Harris +2 +Data Orbital 10/26 - 10/28 550 LV 4.3 50 42 Trump +8 +Emerson 9/27 - 9/28 920 LV 3.2 50 47 Trump +3 +FOX News 9/20 - 9/24 764 LV 3.5 51 48 Trump +3 +Fabrizio/Anzalone 9/24 - 10/1 600 LV 4.0 50 48 Trump +2 +GSG/NSOR 9/23 - 9/29 400 LV 4.9 47 48 Harris +1 +InsiderAdvantage 10/20 - 10/21 800 LV 3.0 50 47 Trump +3 +InsiderAdvantage 8/29 - 8/30 800 LV 3.0 49 48 Trump +1 +InsiderAdvantage 9/29 - 9/30 800 LV 3.0 49 48 Trump +1 +KPHO-TV/HighGround 9/26 - 9/29 500 LV 4.4 46 48 Harris +2 +Marist 10/17 - 10/22 1193 LV 3.7 50 49 Trump +1 +Marist 9/19 - 9/24 1264 LV 3.8 50 49 Trump +1 +NY Times/Siena 10/7 - 10/10 808 LV — 51 46 Trump +5 +NY Times/Siena 8/8 - 8/15 677 LV — 45 50 Harris +5 +NY Times/Siena 9/17 - 9/21 713 LV — 50 45 Trump +5 +Noble Predictive Insights 10/28 - 10/30 775 LV 3.5 48 47 Trump +1 +PPP (D) 7/29 - 7/30 618 LV 3.9 49 47 Trump +2 +Rasmussen Reports 10/25 - 10/29 803 LV 3.0 48 46 Trump +2 +Rasmussen Reports 8/13 - 8/17 1187 LV — 47 45 Trump +2 +Rasmussen Reports 9/19 - 9/22 1071 LV 3.0 49 47 Trump +2 +The Hill/Emerson 10/5 - 10/8 1000 LV 3.0 49 47 Trump +2 +The Hill/Emerson 8/25 - 8/28 720 LV 3.6 50 47 Trump +3 +The Hill/Emerson 9/15 - 9/18 868 LV 3.3 49 48 Trump +1 +Trafalgar Group (R 8/6 - 8/8 1000 LV 2.9 48 47 Trump +1 +Trafalgar Group (R) 10/10 - 10/13 1090 LV 2.9 48 46 Trump +2 +Trafalgar Group (R) 10/24 - 10/26 1094 LV 2.9 48 46 Trump +2 +Trafalgar Group (R) 9/11 - 9/12 1088 LV 2.9 47 46 Trump +1 +USA Today/Suffolk 9/21 - 9/24 500 LV 4.4 48 42 Trump +6 diff --git a/_assets/scripts/data/call_order.csv b/_assets/scripts/data/call_order.csv new file mode 100644 index 0000000..5ad81d9 --- /dev/null +++ b/_assets/scripts/data/call_order.csv @@ -0,0 +1,57 @@ +time,state +2024-11-05 19:00,Kentucky +2024-11-05 19:00,Vermont +2024-11-05 19:30,West Virginia +2024-11-05 19:36,Virginia +2024-11-05 19:56,South Carolina +2024-11-05 20:00,Alabama +2024-11-05 20:00,Mississippi +2024-11-05 20:00,Tennessee +2024-11-05 20:00,Oklahoma +2024-11-05 20:00,Connecticut +2024-11-05 20:00,Delaware +2024-11-05 20:00,Illinois +2024-11-05 20:00,Maryland +2024-11-05 20:00,Massachusetts +2024-11-05 20:00,New Jersey +2024-11-05 20:00,Rhode Island +2024-11-05 20:30,Arkansas +2024-11-05 20:52,Indiana +2024-11-05 21:00,North Dakota +2024-11-05 21:00,South Dakota +2024-11-05 21:00,Wyoming +2024-11-05 21:00,Louisiana +2024-11-05 21:00,New York +2024-11-05 21:00,New Mexico +2024-11-05 21:00,Nebraska +2024-11-05 21:00,NE1 +2024-11-05 21:00,NE2 +2024-11-05 21:00,NE3 +2024-11-05 21:27,DC +2024-11-05 21:37,Colorado +2024-11-05 21:59,Kansas +2024-11-05 22:31,Missouri +2024-11-05 22:54,New Hampshire +2024-11-05 23:00,Idaho +2024-11-05 23:00,California +2024-11-05 23:00,Oregon +2024-11-05 23:00,Washington +2024-11-05 23:08,Utah +2024-11-06 00:06,Hawaii +2024-11-06 00:13,Minnesota +2024-11-06 00:19,Ohio +2024-11-06 00:20,Montana +2024-11-06 00:21,Iowa +2024-11-06 00:35,Florida +2024-11-06 01:06,Texas +2024-11-06 02:51,Arizona +2024-11-06 03:06,Maine +2024-11-06 03:06,ME1 +2024-11-06 13:24,ME2 +2024-11-06 14:16,Wisconsin +2024-11-06 17:58,Michigan +2024-11-06 11:25,Pennsylvania +2024-11-06 12:13,Nevada +2024-11-09 00:00,Alaska +2024-11-11 00:00,Georgia +2024-11-11 00:00,North Carolina diff --git a/_assets/scripts/data/college.csv b/_assets/scripts/data/college.csv new file mode 100644 index 0000000..24c1433 --- /dev/null +++ b/_assets/scripts/data/college.csv @@ -0,0 +1,17 @@ +Alabama - 9 votes,Kentucky - 8 votes,North Dakota - 3 votes +Alaska - 3 votes,Louisiana - 8 votes,Ohio - 17 votes +Arizona - 11 votes,Maine - 4 votes,Oklahoma - 7 votes +Arkansas - 6 votes,Maryland - 10 votes,Oregon - 8 votes +California - 54 votes,Massachusetts - 11 votes,Pennsylvania - 19 votes +Colorado - 10 votes,Michigan - 15 votes,Rhode Island - 4 votes +Connecticut - 7 votes,Minnesota - 10 votes,South Carolina - 9 votes +Delaware - 3 votes,Mississippi - 6 votes,South Dakota - 3 votes +District of Columbia - 3 votes,Missouri - 10 votes,Tennessee - 11 votes +Florida - 30 votes,Montana - 4 votes,Texas - 40 votes +Georgia - 16 votes,Nebraska - 5 votes,Utah - 6 votes +Hawaii - 4 votes,Nevada - 6 votes,Vermont - 3 votes +Idaho - 4 votes,New Hampshire - 4 votes,Virginia - 13 votes +Illinois - 19 votes,New Jersey - 14 votes,Washington - 12 votes +Indiana - 11 votes,New Mexico - 5 votes,West Virginia - 4 votes +Iowa - 6 votes,New York - 28 votes,Wisconsin - 10 votes +Kansas - 6 votes,North Carolina - 16 votes,Wyoming - 3 votes diff --git a/_assets/scripts/data/ga.csv b/_assets/scripts/data/ga.csv new file mode 100644 index 0000000..a06eb46 --- /dev/null +++ b/_assets/scripts/data/ga.csv @@ -0,0 +1,33 @@ +AmGreatness/TIPP 9/16 - 9/18 835 LV 3.5 48 48 Tie +Atlanta Journal-Constitution 9/9 - 9/15 1000 LV 3.1 47 44 Trump +3 +Atlas Intel 10/27 - 10/30 1212 LV 3.0 50 48 Trump +2 +Atlas Intel 9/20 - 9/25 1200 LV 3.0 50 49 Trump +1 +Bloomberg 10/16 - 10/20 914 LV 3.0 50 48 Trump +2 +Bloomberg 9/19 - 9/25 913 LV 3.0 49 49 Tie +CBS News 9/20 - 9/24 1441 LV 3.3 51 49 Trump +2 +CNN* 10/23 - 10/28 732 LV 4.7 48 47 Trump +1 +Cook Political Report 7/26 - 8/2 405 LV — 48 48 Tie +Cook Political Report 9/19 - 9/25 411 LV — 49 47 Trump +2 +FOX 5 Atlanta/InsiderAdvantage 7/15 - 7/16 800 LV 4.1 47 37 Trump +10 +FOX News 9/20 - 9/24 707 LV 3.5 48 51 Harris +3 +Fabrizio/Anzalone 7/24 - 7/31 600 LV 4.0 48 48 Tie +InsiderAdvantage 10/14 - 10/15 800 LV 3.7 49 47 Trump +2 +InsiderAdvantage 8/29 - 8/31 800 LV 3.7 48 48 Tie +InsiderAdvantage 9/29 - 9/30 800 LV 3.0 48 48 Tie +Landmark Communications 7/22 - 7/22 400 LV 5.0 48 47 Trump +1 +Marist 10/17 - 10/22 1193 LV 3.9 49 49 Tie +Marist 9/19 - 9/24 1220 LV 3.9 50 49 Trump +1 +NY Times/Siena 8/9 - 8/14 661 LV — 50 46 Trump +4 +NY Times/Siena 9/17 - 9/21 682 LV — 49 45 Trump +4 +PPP (D) 7/29 - 7/30 662 LV 3.8 47 48 Harris +1 +Quinnipiac 10/10 - 10/14 1328 LV 2.7 52 46 Trump +6 +Quinnipiac 9/25 - 9/29 942 LV 3.2 50 45 Trump +5 +Quinnipiac 9/4 - 9/8 969 LV 3.2 49 46 Trump +3 +Rasmussen Reports 10/25 - 10/28 910 LV 3.0 51 46 Trump +5 +Rasmussen Reports 9/19 - 9/22 1152 LV 3.0 50 47 Trump +3 +The Hill/Emerson 10/5 - 10/8 1000 LV 3.0 49 48 Trump +1 +The Hill/Emerson 8/25 - 8/28 800 LV 3.4 48 49 Harris +1 +The Hill/Emerson 9/15 - 9/18 975 LV 3.1 50 47 Trump +3 +Trafalgar Group (R) 10/24 - 10/26 1087 LV 2.9 48 46 Trump +Trafalgar Group (R) 10/7 - 10/8 1089 LV 2.9 46 45 Trump +1 +Trafalgar Group (R) 9/11 - 9/13 1098 LV 2.9 46 45 Trump +1 diff --git a/_assets/scripts/data/j4.sh b/_assets/scripts/data/j4.sh new file mode 100755 index 0000000..c6d594e --- /dev/null +++ b/_assets/scripts/data/j4.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Check if a file is provided as an argument +if [ "$#" -gt 0 ]; then + # Use 'paste' to join every 4 lines from the file(s) + paste -d ' ' - - - - "$@" +else + # Use 'paste' to join every 4 lines from standard input + paste -d ' ' - - - - +fi + diff --git a/_assets/scripts/data/make_csv.sh b/_assets/scripts/data/make_csv.sh new file mode 100755 index 0000000..c9b6dae --- /dev/null +++ b/_assets/scripts/data/make_csv.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Check if an input file is provided +if [ "$#" -gt 0 ]; then + input_file="$1" +else + echo "Usage: $0 input_file" + exit 1 +fi + +awk 'BEGIN { + FS = "\t" # Set the field separator to tab +} +{ + # Split the first field into words to extract the agency name and date range + split($1, arr, " ") + agency = "" + date_found = 0 + for (i = 1; i <= length(arr); i++) { + if (match(arr[i], /^[0-9]+\/[0-9]+$/)) { + # Date range starts here + date_range = arr[i] + if (arr[i+1] == "-" && match(arr[i+2], /^[0-9]+\/[0-9]+$/)) { + date_range = date_range " " arr[i+1] " " arr[i+2] + i += 2 + } + date_found = 1 + break + } else { + # Build the agency name + agency = (agency == "") ? arr[i] : agency " " arr[i] + } + } + + # Extract the start day from the date range + if (date_found) { + match(date_range, /[0-9]+\/([0-9]+)/, m) + start_day = m[1] + } else { + start_day = 0 # Default if no date found + } + + # Determine 'sep1' or 'sep2' based on the start day + if (start_day < 15) { + date_str = "sep2" + } else { + date_str = "sep1" + } + + # Extract the number of respondents from the second field + split($2, resp_arr, " ") + num_respondents = resp_arr[1] + + # Extract the two numbers after the third field + num1 = $4 + num2 = $5 + + # Print the CSV line + print agency "," date_str "," num_respondents "," num1 "," num2 +}' "$input_file" diff --git a/_assets/scripts/data/mi.csv b/_assets/scripts/data/mi.csv new file mode 100644 index 0000000..8c91410 --- /dev/null +++ b/_assets/scripts/data/mi.csv @@ -0,0 +1,37 @@ +AmGreatness/TIPP 8/20 - 8/22 741 LV 3.7 48 46 Harris +2 +Atlas Intel 10/27 - 10/30 1136 LV 3.0 49 49 Tie +Atlas Intel 9/20 - 9/25 918 LV 3.0 47 51 Trump +4 +Bloomberg 10/16 - 10/20 756 LV 4.0 47 50 Harris +3 +Bloomberg 9/19 - 9/25 800 LV 3.0 50 47 Harris +3 +CBS News 9/3 - 9/6 1086 LV 3.6 50 49 Harris +1 +Cook Political Report 7/26 - 8/2 406 LV — 49 46 Harris +3 +Cook Political Report 9/19 - 9/25 416 LV — 51 48 Harris +3 +EPIC-MRA 8/23 - 8/26 600 LV 4.0 46 47 Trump +1 +Emerson 10/25 - 10/27 1000 LV 3.0 48 49 Trump +1 +FOX News 10/24 - 10/28 988 LV 3.0 49 49 Tie +Fabrizio/Anzalone 10/2 - 10/8 600 LV 4.0 49 48 Trump +1 +Fabrizio/Anzalone 8/7 - 8/11 600 LV 4.0 48 48 Tie +InsiderAdvantage 10/26 - 10/27 800 LV 3.7 47 48 Trump +1 +InsiderAdvantage 10/8 - 10/9 800 LV 3.7 48 46 Trump +2 +InsiderAdvantage 8/6 - 8/8 800 LV 3.4 49 47 Harris +2 +InsiderAdvantage 9/11 - 9/12 800 LV 3.7 48 49 Trump +1 +MIRS/MI News Source 9/11 - 9/11 580 LV 4.1 48 48 Tie +MIRS/MI News Source 9/30 - 9/30 709 LV 3.7 48 49 Trump +1 +Marist 10/27 - 10/30 1214 LV 3.5 51 48 Harris +3 +Marist 9/12 - 9/17 1138 LV 3.4 52 47 Harris +5 +NY Times/Siena 9/21 - 9/26 688 LV — 48 47 Harris +1 +Quinnipiac 10/17 - 10/21 1136 LV 2.9 46 50 Harris +4 +Quinnipiac 9/12 - 9/16 905 LV 3.3 51 46 Harris +5 +Rasmussen Reports 8/13 - 8/17 1093 LV — 48 47 Harris +1 +Rasmussen Reports 9/19 - 9/22 1086 LV 3.0 48 48 Tie +Susquehanna 10/23 - 10/27 400 LV 4.9 52 47 Harris +5 +The Hill/Emerson 10/5 - 10/8 950 LV 3.1 49 49 Tie +The Hill/Emerson 8/25 - 8/28 800 LV 3.4 50 47 Harris +3 +The Hill/Emerson 9/15 - 9/18 875 LV 3.2 49 47 Harris +2 +Trafalgar Group (R) 10/18 - 10/20 1090 LV 2.9 46 44 Trump +2 +Trafalgar Group (R) 8/28 - 8/30 1089 LV 2.9 47 47 Tie +Trafalgar Group (R) 9/28 - 9/30 1086 LV 2.9 45 47 Trump +2 +USA Today/Suffolk 10/24 - 10/27 500 LV 4.0 47 47 Tie +USA Today/Suffolk 9/16 - 9/19 500 LV 4.4 48 45 Harris +3 +Washington Post 10/24 - 10/28 1003 LV 3.7 47 46 Harris +1 +quinnipiac 10/3 - 10/7 1007 LV 3.1 51 47 Trump +4 diff --git a/_assets/scripts/data/naturalizatons.csv b/_assets/scripts/data/naturalizatons.csv new file mode 100644 index 0000000..2e69cbf --- /dev/null +++ b/_assets/scripts/data/naturalizatons.csv @@ -0,0 +1,8 @@ +ST,FY21,FY22 +AZ,17512,16396 +GA,16476,28440 +MI,11716,16077 +NV,8061,10573 +NC,13173,13626 +PA,19693,26747 +WI,5029,6125 \ No newline at end of file diff --git a/_assets/scripts/data/nc.csv b/_assets/scripts/data/nc.csv new file mode 100644 index 0000000..b9ee325 --- /dev/null +++ b/_assets/scripts/data/nc.csv @@ -0,0 +1,44 @@ +AmGreatness/TIPP 9/11 - 9/13 973 LV 3.2 49 46 Trump +3 +Atlas Intel 10/27 - 10/30 1373 LV 3.0 51 47 Trump +4 +Bloomberg 10/16 - 10/20 755 LV 4.0 50 49 Trump +1 +Bloomberg 9/19 - 9/25 828 LV 3.0 48 50 Harris +2 +CNN 9/20 - 9/25 931 LV 3.9 49 49 +CNN* 10/23 - 10/28 750 LV 4.5 47 48 Harris +1 +Carolina Journal/Cygnal 8/4 - 8/5 600 LV 4.0 47 44 Trump +3 +Carolina Journal/Cygnal* 9/15 - 9/16 600 LV 4.0 46 45 Trump +1 +Cook Political Report 7/26 - 8/2 403 LV — 47 48 Harris +1 +Cook Political Report 9/19 - 9/25 411 LV — 49 49 Tie +East Carolina U. 9/23 - 9/26 1005 LV 3.0 49 47 Trump +2 +East Carolina U.* 8/26 - 8/28 920 LV 3.0 48 47 Trump +1 +Emerson 10/21 - 10/22 950 LV 3.1 50 48 Trump +2 +Emerson 9/27 - 9/28 850 LV 3.3 49 48 Trump +1 +FOX News 10/24 - 10/28 872 LV 3.0 50 49 Trump +1 +FOX News 9/20 - 9/24 787 LV 3.5 50 49 Trump +1 +Fabrizio/Anzalone 9/11 - 9/17 600 LV 4.0 50 47 Trump +3 +High Point University 9/20 - 9/29 589 LV 4.9 48 48 Tie +High Point/SurveyUSA 10/17 - 10/20 1164 RV 3.7 46 47 Harris +1 +InsiderAdvantage 10/19 - 10/20 800 LV 3.5 49 47 Trump +2 +InsiderAdvantage 8/29 - 8/31 800 LV 3.5 49 48 Trump +1 +InsiderAdvantage 9/29 - 9/30 800 LV 3.0 50 49 Trump +1 +Marist 10/17 - 10/22 1226 LV 3.6 50 48 Trump +2 +Marist 9/19 - 9/24 1348 LV 3.7 49 49 Tie +NY Times/Siena 8/9 - 8/14 655 LV — 47 49 Harris +2 +NY Times/Siena 9/17 - 9/21 682 LV — 49 47 Trump +2 +Quinnipiac 10/10 - 10/14 1031 LV 3.1 47 50 Harris +3 +Quinnipiac 9/25 - 9/29 953 LV 3.2 49 48 Trump +1 +Quinnipiac 9/4 - 9/8 940 LV 3.2 47 50 Harris +3 +Rasmussen Reports 10/25 - 10/28 849 LV 3.0 50 47 Trump +3 +Rasmussen Reports 10/9 - 10/14 1042 LV 3.0 51 46 Trump +5 +Rasmussen Reports 9/19 - 9/22 1078 LV 3.0 49 46 Trump +3 +The Hill/Emerson 10/5 - 10/8 1000 LV 3.0 49 48 Trump +1 +The Hill/Emerson 8/25 - 8/28 775 LV 3.5 49 48 Trump +1 +The Hill/Emerson 9/15 - 9/18 1000 LV 3.0 48 49 Harris +1 +Tie Atlas Intel 9/20 - 9/25 1173 LV 3.0 48 51 Harris +3 +Trafalgar Group (R) 10/10 - 10/13 1085 LV 2.9 47 45 Trump +2 +Trafalgar Group (R) 10/25 - 10/28 1091 LV 2.9 49 46 Trump +3 +Trafalgar Group (R) 8/6 - 8/8 1000 LV 2.9 49 45 Trump +4 +Trafalgar Group (R) 9/11 - 9/12 1094 LV 2.9 48 46 Trump +2 +Victory Insights 9/16 - 9/18 600 LV 4.0 49 45 Trump +4 +WRAL-TV/SurveyUSA 10/23 - 10/26 853 LV 4.1 47 47 Tie +WRAL-TV/SurveyUSA 9/4 - 9/7 900 LV 4.9 46 49 Harris +3 +Washington Post 9/25 - 9/29 1001 LV 3.5 50 48 Trump +2 diff --git a/_assets/scripts/data/newvoters.csv b/_assets/scripts/data/newvoters.csv new file mode 100644 index 0000000..5d27bb9 --- /dev/null +++ b/_assets/scripts/data/newvoters.csv @@ -0,0 +1,10 @@ +Gender,Arizona,Georgia,Michigan,Nevada,North Carolina,Pennsylvania,Wisconsin +M14,49314,76728,64878,20648,69120,80041,38868 +M15,49487,76928,66271,20690,69202,80113,38736 +M16,49613,76829,67403,20669,69441,81130,39287 +M17,48604,75491,66978,20348,68463,80446,38025 +F14,46967,73160,62026,19669,66133,75657,36904 +F15,47416,73275,62115,19677,66411,76125,36639 +F16,46989,74000,64352,19232,66083,77305,37258 +F17,45872,71978,63572,19027,65174,75934,35825 +New voters,384262,598389,517595,159960,540027,626751,301542 \ No newline at end of file diff --git a/_assets/scripts/data/nv.csv b/_assets/scripts/data/nv.csv new file mode 100644 index 0000000..08867f6 --- /dev/null +++ b/_assets/scripts/data/nv.csv @@ -0,0 +1,26 @@ +AmGreatness/TIPP 9/23 - 9/25 736 LV 3.7 50 49 Harris +1 +Atlas Intel 10/27 - 10/30 845 LV 3.0 51 47 Trump +4 +Atlas Intel 9/20 - 9/25 858 LV 3.0 51 48 Harris +3 +Bloomberg 10/16 - 10/20 449 LV 5.0 48 49 Harris 0 +Bloomberg 9/19 - 9/25 516 LV 4.0 52 45 Harris +7 +CNN* 10/21 - 10/26 683 LV 4.6 48 47 Trump +1 +CNN* 8/23 - 8/29 626 LV 4.9 48 47 Harris +1 +Cook Political Report 7/26 - 8/2 403 LV — 45 48 Trump +3 +Cook Political Report 9/19 - 9/25 409 LV — 48 47 Harris +1 +Emerson 10/29 - 10/31 700 LV 3.6 47 48 Harris +1 +GSG/NSOR 9/23 - 9/29 407 LV 4.9 47 48 Harris +1 +InsiderAdvantage 8/29 - 8/31 800 LV 3.5 47 48 Trump +1 +InsiderAdvantage 9/29 - 9/30 800 LV 3.0 49 48 Trump +1 +NY Times/Siena 8/12 - 8/15 677 LV — 47 48 Trump +1 +Noble Predictive Insights 9/9 - 9/16 692 LV 3.7 48 47 Harris +1 +Rasmussen Reports 10/25 - 10/28 767 LV 3.0 49 47 Trump +2 +Rasmussen Reports 8/13 - 8/19 980 LV — 46 48 Trump +2 +Rasmussen Reports 9/19 - 9/22 738 LV 3.0 48 49 Trump +1 +Susquehanna 10/28 - 10/31 400 LV 4.9 50 44 Trump +6 +TTrafalgar Group (R) 10/10 - 10/13 1088 LV 2.9 45 46 Harris +1 +The Hill/Emerson 10/5 - 10/8 900 LV 3.2 47 48 Harris +1 +The Hill/Emerson 8/25 - 8/28 1168 LV 2.8 49 48 Harris +1 +The Hill/Emerson 9/15 - 9/18 895 LV 3.2 48 48 +Tie Trafalgar Group (R) 9/11 - 9/13 1079 LV 2.9 45 44 Harris +1 +Trafalgar Group (R) 10/10 - 10/13 1088 LV 2.9 45 46 Harris +1 +Trafalgar Group (R) 10/25 - 10/28 1082 LV 2.9 48 48 Tie diff --git a/_assets/scripts/data/pa.csv b/_assets/scripts/data/pa.csv new file mode 100644 index 0000000..27b2b6d --- /dev/null +++ b/_assets/scripts/data/pa.csv @@ -0,0 +1,52 @@ +AmGreatness/NSOR 10/22 - 10/26 600 LV 4.0 47 47 tie dye +AmGreatness/NSOR 7/20 - 7/23 600 LV 4.0 47 45 Trump +2 +AmGreatness/TIPP 10/7 - 10/9 803 LV 3.5 49 48 Trump +1 +Atlas Intel 10/27 - 10/30 1738 LV 2.0 49 48 Trump +1 +Atlas Intel 9/20 - 9/25 1775 LV 2.0 51 48 Trump +3 +Bloomberg 10/16 - 10/20 866 LV 3.0 48 50 Harris +2 +Bloomberg 9/19 - 9/25 924 LV 3.0 46 51 Harris +5 +CBS News 10/22 - 10/28 1273 LV 3.9 49 49 tie dye +CBS News 9/3 - 9/6 1085 LV 3.4 50 50 Tie 0 +CNN* 10/23 - 10/28 819 LV 4.7 48 48 tie dye +CNN* 8/23 - 8/29 789 LV 4.7 47 47 Tie 0 +Cook Political Report 7/26 - 8/2 411 LV — 48 49 Harris +1 +Cook Political Report 9/19 - 9/25 474 LV — 49 50 Harris +1 +Emerson 10/21 - 10/22 860 LV 3.3 49 48 Trump +1 +Emerson 8/13 - 8/14 1000 LV 3.0 49 48 Trump +1 +Emerson 9/27 - 9/28 1000 LV 3.0 48 48 Tie 0 +FOX News 10/24 - 10/28 1057 LV 3.0 50 49 Trump +1 +FOX News 9/20 - 9/24 775 LV 3.5 49 49 Tie 0 +Fabrizio/Anzalone 9/17 - 9/24 600 LV 4.0 47 50 Harris +3 +Franklin & Marshall 10/9 - 10/20 583 LV 5.0 50 49 Trump +1 +InsiderAdvantage 10/26 - 10/27 800 LV 3.5 48 47 Trump +1 +InsiderAdvantage 10/7 - 10/8 800 LV 3.5 49 47 Trump +2 +InsiderAdvantage 8/18 - 8/19 800 LV 3.5 47 46 Trump +1 +InsiderAdvantage 9/14 - 9/15 800 LV 3.5 50 48 Trump +2 +Marist 10/27 - 10/30 1400 LV 3.1 48 50 Harris +2 +Marist 9/12 - 9/17 1476 LV 3.2 49 49 Tie 0 +Muhlenberg College 9/16 - 9/19 450 LV 6.0 48 48 Tie 0 +NY Times/Siena 10/7 - 10/10 857 LV — 47 50 Harris +3 +NY Times/Siena 8/6 - 8/9 693 LV 4.2 46 50 Harris +4 +NY Times/Siena 9/11 - 9/16 1082 LV 3.8 46 50 Harris +4 +PPP (D) 7/29 - 7/30 627 LV 3.9 48 47 Trump +1 +Quinnipiac 10/24 - 10/28 2186 LV 2.1 49 47 Trump +2 +Quinnipiac 10/3 - 10/7 1412 LV 3.1 47 49 Harris +2 +Quinnipiac 8/8 - 8/12 1738 LV 2.4 47 50 Harris +3 +Quinnipiac 9/12 - 9/16 1331 LV 2.7 46 51 Harris +5 +Rasmussen Reports 10/25 - 10/28 849 LV 3.0 49 47 Trump +2 +Rasmussen Reports 10/9 - 10/13 1072 LV 3.0 50 47 Trump +3 +Rasmussen Reports 8/13 - 8/17 1312 LV — 47 46 Trump +1 +Rasmussen Reports 9/19 - 9/22 1202 LV 3.0 48 48 Tie 0 +Susquehanna 9/16 - 9/22 700 LV 3.7 46 46 Tie 0 +The Hill/Emerson 10/5 - 10/8 1000 LV 3.0 49 48 Trump +1 +The Hill/Emerson 8/25 - 8/28 950 LV 3.1 48 48 Tie 0 +The Hill/Emerson 9/15 - 9/18 880 LV 3.2 48 47 Trump +1 +Trafalgar Group (R) 8/28 - 8/30 1082 LV 2.9 47 45 Trump +2 +Trafalgar Group (R) 8/6 - 8/8 1000 LV 2.9 46 44 Trump +2 +Trafalgar Group (R) 9/26 - 9/29 1090 LV 2.9 48 45 Trump +3 +UMass Lowell 9/11 - 9/19 800 LV 4.0 46 48 Harris +2 +USA Today/Suffolk 10/27 - 10/30 500 LV 4.4 49 49 tie dye +USA Today/Suffolk 9/11 - 9/14 500 LV 4.4 46 49 Harris +3 +Washington Post 10/26 - 10/30 1204 LV 3.1 47 48 Harris +1 +Washington Post 9/12 - 9/16 1003 LV 3.6 48 48 Tie 0 +co/efficient 9/4 - 9/6 889 LV 3.3 48 46 Trump +2 diff --git a/_assets/scripts/data/pres_turnout.csv b/_assets/scripts/data/pres_turnout.csv new file mode 100644 index 0000000..6a01bb0 --- /dev/null +++ b/_assets/scripts/data/pres_turnout.csv @@ -0,0 +1,22 @@ +Year,Turnout +1940,62.4 +1944,55.9 +1948,52.2 +1952,62.3 +1956,60.2 +1960,63.8 +1964,62.8 +1968,62.5 +1972,56.2 +1976,54.8 +1980,54.2 +1984,55.2 +1988,52.8 +1992,58.1 +1996,51.7 +2000,54.2 +2004,60.1 +2008,61.6 +2012,58.6 +2016,60.1 +2020,66,6 diff --git a/_assets/scripts/data/scratch b/_assets/scripts/data/scratch new file mode 100644 index 0000000..befabb5 --- /dev/null +++ b/_assets/scripts/data/scratch @@ -0,0 +1,4 @@ +Atlas Intel 10/27 - 10/30 1212 LV 3.0 50 48 Trump +2 +Rasmussen Reports 10/25 - 10/28 910 LV 3.0 51 46 Trump +5 +CNN* 10/23 - 10/28 732 LV 4.7 48 47 Trump +1 +Trafalgar Group (R) 10/24 - 10/26 1087 LV 2.9 48 46 Trump diff --git a/_assets/scripts/data/si_may.csv b/_assets/scripts/data/si_may.csv new file mode 100644 index 0000000..6a68681 --- /dev/null +++ b/_assets/scripts/data/si_may.csv @@ -0,0 +1,7 @@ +State,Biden,Trump,N +AZ,43,49,626 +GA,41,50,604 +MI,47,46,616 +NV,38,51,614 +PA,45,48,1023 +WI,46,47,614 \ No newline at end of file diff --git a/_assets/scripts/data/vote2022.csv b/_assets/scripts/data/vote2022.csv new file mode 100644 index 0000000..c98ccec --- /dev/null +++ b/_assets/scripts/data/vote2022.csv @@ -0,0 +1,46 @@ +st,cohort,totpop,cpop,reg,vot +AZ,Total,5731,5093,3560,2844 +,18 to 24 years,751,694,322,170 +,25 to 34 years,911,782,509,300 +,35 to 44 years,937,800,532,428 +,45 to 64 years,1800,1530,1148,975 +,65 years and over,1332,1287,1047,971 +GA,Total,8314,7601,5275,4323 +,18 to 24 years,924,859,466,322 +,25 to 34 years,1620,1395,918,640 +,35 to 44 years,1400,1176,812,628 +,45 to 64 years,2610,2451,1695,1457 +,65 years and over,1760,1720,1384,1276 +,Total,8175,7533,4583,56.1 +,18 to 24 years,921,866,372,40.3 +NC,25 to 34 years,1395,1236,652,46.7 +,35 to 44 years,1290,1069,675,52.3 +,45 to 64 years,2687,2523,1581,58.9 +,65 years and over,1881,1838,1303,69.3 +MI,Total,7777,7517,5797,4757 +,18 to 24 years,826,799,532,371 +,25 to 34 years,1304,1223,852,622 +,35 to 44 years,1228,1183,894,689 +,45 to 64 years,2639,2545,2025,1710 +,65 years and over,1779,1767,1494,1365 +NV,Total,2451,2206,1436,1123 +,18 to 24 years,297,287,122,63 +,25 to 34 years,414,355,222,153 +,35 to 44 years,406,358,229,170 +,45 to 64 years,789,694,458,378 +,65 years and over,544,511,405,358 +PA,Total,10124,9741,7009,5843 +,18 to 24 years,1145,1093,610,437 +,25 to 34 years,1680,1611,1041,776 +,35 to 44 years,1531,1397,1007,784 +,45 to 64 years,3139,3043,2328,1995 +,65 years and over,2630,2597,2024,1851 +WI,Total,4591,4461,3225,2715 +,18 to 24 years,588,579,341,286 +,25 to 34 years,724,679,474,371 +,35 to 44 years,693,669,447,373 +,45 to 64 years,1473,1440,1107,908 +,65 years and over,1113,1095,856,777 +"Source: U.S. Census Bureau, Current Population Survey, November 2022",,,,, +https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-586.html,,,,, +"Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022",,,,, \ No newline at end of file diff --git a/_assets/scripts/data/votebyage.csv b/_assets/scripts/data/votebyage.csv new file mode 100644 index 0000000..5333362 --- /dev/null +++ b/_assets/scripts/data/votebyage.csv @@ -0,0 +1,145 @@ +demograph,gender,cohort,registered,voted +Male over 18,cm,121870,65.1,59.5 +18 to 24 years,cm,14382,54.7,45.8 +25 to 34 years,cm,22406,58.1,51.0 +35 to 44 years,cm,20466,59.6,53.3 +45 to 54 years,cm,19442,65.8,60.7 +55 to 64 years,cm,20318,71.2,67.1 +65 to 74 years,cm,15401,75.8,73.2 +75 years and over,cm,9456,77.1,72.5 +18 years,m,1998,42.9,37.2 +19 years,m,1936,52.7,43.2 +20 years,m,2361,56.8,47.2 +21 years,m,2134,56.0,44.1 +22 years,m,1909,58.5,47.2 +23 years,m,2025,58.7,51.6 +24 years,m,2018,57.0,50.0 +25 years,m,2045,53.3,45.6 +26 years,m,2060,50.6,43.3 +27 years,m,2347,61.0,53.5 +28 years,m,2331,58.5,49.6 +29 years,m,2456,58.3,51.2 +30 years,m,2233,57.3,50.8 +31 years,m,2396,59.5,52.3 +32 years,m,2113,62.4,56.3 +33 years,m,2080,58.9,53.1 +34 years,m,2344,60.6,53.0 +35 years,m,2210,58.7,51.7 +36 years,m,2325,58.0,51.6 +37 years,m,2002,60.1,55.5 +38 years,m,2083,60.5,52.6 +39 years,m,1954,62.4,54.4 +40 years,m,2049,56.6,51.2 +41 years,m,1924,56.6,51.3 +42 years,m,1972,62.0,55.6 +43 years,m,1960,61.9,56.0 +44 years,m,1986,59.8,53.8 +45 years,m,1921,62.4,57.6 +46 years,m,1918,64.5,59.1 +47 years,m,1834,66.4,59.1 +48 years,m,1937,64.2,58.7 +49 years,m,1925,64.0,60.5 +50 years,m,2005,63.4,59.7 +51 years,m,2082,68.4,61.7 +52 years,m,1958,68.5,65.1 +53 years,m,1999,68.0,61.8 +54 years,m,1863,68.1,63.3 +55 years,m,2186,66.6,61.5 +56 years,m,1951,72.0,67.6 +57 years,m,1989,69.8,65.4 +58 years,m,2091,70.2,65.3 +59 years,m,1961,72.3,67.7 +60 years,m,2196,69.0,66.0 +61 years,m,2119,68.0,64.3 +62 years,m,1902,73.1,68.3 +63 years,m,1962,77.8,74.4 +64 years,m,1960,74.8,71.2 +65 years,m,1909,73.7,70.4 +66 years,m,1765,74.5,72.0 +67 years,m,1705,75.9,73.1 +68 years,m,1610,75.4,72.6 +69 years,m,1519,75.9,73.3 +70 years,m,1441,73.3,71.5 +71 years,m,1347,74.7,73.0 +72 years,m,1536,76.9,75.2 +73 years,m,1318,82.7,78.8 +74 years,m,1251,76.9,73.3 +75 years,m,1073,76.6,75.2 +76 years,m,901,82.0,77.7 +77 years,m,806,79.9,76.3 +78 years,m,859,81.5,77.4 +79 years,m,749,79.7,76.1 +80-84 years,m,2838,77.7,73.0 +85 years and over,m,2229,71.0,64.1 +Female 18 years and over,fm,130404,68.2,63.0 +18 to 24 years,fm,14277,56.8,50.2 +25 to 34 years,fm,22466,63.8,56.4 +35 to 44 years,fm,21092,64.7,59.3 +45 to 54 years,fm,20316,68.5,64.0 +55 to 64 years,fm,21837,73.4,69.7 +65 to 74 years,fm,17553,76.0,72.8 +75 years and over,fm,12864,74.4,68.5 +18 years,f,1928,48.4,43.1 +19 years,f,1872,55.4,50.5 +20 years,f,2213,58.0,50.8 +21 years,f,2045,53.7,48.0 +22 years,f,2108,62.7,53.8 +23 years,f,1935,62.4,53.8 +24 years,f,2176,56.7,50.7 +25 years,f,2010,62.1,54.2 +26 years,f,2201,61.6,54.4 +27 years,f,2389,63.9,55.2 +28 years,f,2187,62.7,54.4 +29 years,f,2413,64.5,58.6 +30 years,f,2504,64.2,55.4 +31 years,f,2225,64.0,56.4 +32 years,f,2212,67.4,61.5 +33 years,f,2304,62.9,56.5 +34 years,f,2022,64.0,57.3 +35 years,f,2295,64.4,57.5 +36 years,f,2264,65.4,59.1 +37 years,f,1992,61.2,55.8 +38 years,f,2325,70.5,64.5 +39 years,f,1970,66.1,61.3 +40 years,f,2250,64.3,59.2 +41 years,f,2028,65.6,60.1 +42 years,f,2052,61.9,58.4 +43 years,f,1944,63.2,59.4 +44 years,f,1974,63.6,57.2 +45 years,f,2101,62.9,59.0 +46 years,f,1896,67.4,61.9 +47 years,f,1956,65.2,60.8 +48 years,f,1984,68.5,63.0 +49 years,f,2038,68.6,64.1 +50 years,f,2192,71.9,68.4 +51 years,f,2180,67.7,62.6 +52 years,f,2042,70.4,65.4 +53 years,f,1975,72.8,68.9 +54 years,f,1951,69.9,65.3 +55 years,f,2299,70.4,67.5 +56 years,f,2126,68.1,63.9 +57 years,f,2006,77.7,71.9 +58 years,f,2117,70.5,66.9 +59 years,f,2293,74.0,69.6 +60 years,f,2326,74.6,71.4 +61 years,f,2241,71.5,68.3 +62 years,f,2125,76.5,73.0 +63 years,f,2116,77.2,74.3 +64 years,f,2187,74.1,70.8 +65 years,f,2084,73.8,71.7 +66 years,f,1979,77.5,73.8 +67 years,f,1895,74.9,71.6 +68 years,f,1826,74.3,71.8 +69 years,f,1766,78.0,74.6 +70 years,f,1740,72.6,69.7 +71 years,f,1642,76.5,73.0 +72 years,f,1640,79.5,75.5 +73 years,f,1633,78.4,74.3 +74 years,f,1348,75.4,72.5 +75 years,f,1176,81.6,76.2 +76 years,f,1228,77.1,73.6 +77 years,f,1138,77.1,74.3 +78 years,f,1077,81.1,78.1 +79 years,f,873,75.0,70.0 +80-84 years,fm,3715,74.0,67.9 +85 years and over,fm,3656,68.7,59.8 \ No newline at end of file diff --git a/_assets/scripts/data/votes.csv b/_assets/scripts/data/votes.csv new file mode 100644 index 0000000..533e29f --- /dev/null +++ b/_assets/scripts/data/votes.csv @@ -0,0 +1,70 @@ +"State or +district","Biden/Harris +Democratic",,,"Trump/Pence +Republican",,,"Jorgensen/Cohen +Libertarian",,,"Hawkins/Walker +Green",,,Others,,,Margin,,"Margin +swing","Total +votes" +,Votes,%,EV,Votes,%,EV,Votes,%,EV,Votes,%,EV,Votes,%,EV,Votes,%,%, +Alab.,"849,624",36.57%,–,"1,441,170",62.03%,9,"25,176",1.08%,–,,,–,"7,312",0.31%,–,"-591,546",-25.46%,2.27%,"2,323,282" +Alaska,"153,778",42.77%,–,"189,951",52.83%,3,"8,897",2.47%,–,,,–,"6,904",1.92%,–,"-36,173",-10.06%,4.67%,"359,530" +Arizona,"1,672,143",49.36%,11,"1,661,686",49.06%,–,"51,465",1.52%,–,"1,557",0.05%,–,475,0.01%,–,"10,457",0.31%,3.81%,"3,387,326" +Ark.,"423,932",34.78%,–,"760,647",62.40%,6,"13,133",1.08%,–,"2,980",0.24%,–,"18,377",1.51%,–,"-336,715",-27.62%,-0.70%,"1,219,069" +Calif.,"11,110,639",63.48%,55,"6,006,518",34.32%,–,"187,910",1.07%,–,"81,032",0.46%,–,"115,281",0.66%,–,"5,104,121",29.16%,-0.95%,"17,501,380" +Colo.,"1,804,352",55.40%,9,"1,364,607",41.90%,–,"52,460",1.61%,–,"8,986",0.28%,–,"26,575",0.82%,–,"439,745",13.50%,8.59%,"3,256,980" +Conn.,"1,080,831",59.26%,7,"714,717",39.19%,–,"20,230",1.11%,–,"7,538",0.41%,–,541,0.03%,–,"366,114",20.07%,6.43%,"1,823,857" +Del.,"296,268",58.74%,3,"200,603",39.77%,–,"5,000",0.99%,–,"2,139",0.42%,–,336,0.07%,–,"95,665",18.97%,7.60%,"504,346" +D.C.,"317,323",92.15%,3,"18,586",5.40%,–,"2,036",0.59%,–,"1,726",0.50%,–,"4,685",1.36%,–,"298,737",86.75%,-0.02%,"344,356" +Florida,"5,297,045",47.86%,–,"5,668,731",51.22%,29,"70,324",0.64%,–,"14,721",0.13%,–,"16,635",0.15%,–,"-371,686",-3.36%,-2.16%,"11,067,456" +Georgia,"2,473,633",49.47%,16,"2,461,854",49.24%,–,"62,229",1.24%,–,"1,013",0.02%,–,"1,231",0.02%,–,"11,779",0.24%,5.37%,"4,999,960" +Hawaii,"366,130",63.73%,4,"196,864",34.27%,–,"5,539",0.96%,–,"3,822",0.67%,–,"2,114",0.37%,–,"169,266",29.46%,-2.72%,"574,469" +Idaho,"287,021",33.07%,–,"554,119",63.84%,4,"16,404",1.89%,–,407,0.05%,–,"9,983",1.15%,–,"-267,098",-30.77%,1.00%,"867,934" +Illinois,"3,471,915",57.54%,20,"2,446,891",40.55%,–,"66,544",1.10%,–,"30,494",0.51%,–,"17,900",0.30%,–,"1,025,024",16.99%,-0.08%,"6,033,744" +Indiana,"1,242,498",40.96%,–,"1,729,857",57.03%,11,"58,901",1.94%,–,989,0.03%,–,965,0.03%,–,"-487,359",-16.07%,3.10%,"3,033,210" +Iowa,"759,061",44.89%,–,"897,672",53.09%,6,"19,637",1.16%,–,"3,075",0.18%,–,"11,426",0.68%,–,"-138,611",-8.20%,1.21%,"1,690,871" +Kansas,"570,323",41.51%,–,"771,406",56.14%,6,"30,574",2.23%,–,669,0.05%,–,"1,014",0.07%,–,"-201,083",-14.64%,5.96%,"1,373,986" +Ky.,"772,474",36.15%,–,"1,326,646",62.09%,8,"26,234",1.23%,–,716,0.03%,–,"10,698",0.50%,–,"-554,172",-25.94%,3.90%,"2,136,768" +La.,"856,034",39.85%,–,"1,255,776",58.46%,8,"21,645",1.01%,–,–,–,–,"14,607",0.68%,–,"-399,742",-18.61%,1.03%,"2,148,062" +Maine †,"435,072",53.09%,2,"360,737",44.02%,–,"14,152",1.73%,–,"8,230",1.00%,–,"1,270",0.15%,–,"74,335",9.07%,6.11%,"819,461" +"ME-1 +Tooltip Maine's 1st congressional district","266,376",60.11%,1,"164,045",37.02%,–,"7,343",1.66%,–,"4,654",1.05%,–,694,0.16%,–,"102,331",23.09%,8.28%,"443,112" +"ME-2 +Tooltip Maine's 2nd congressional district","168,696",44.82%,–,"196,692",52.26%,1,"6,809",1.81%,–,"3,576",0.95%,–,576,0.15%,–,"-27,996",-7.44%,2.85%,"376,349" +Md.,"1,985,023",65.36%,10,"976,414",32.15%,–,"33,488",1.10%,–,"15,799",0.52%,–,"26,306",0.87%,–,"1,008,609",33.21%,6.79%,"3,037,030" +Mass.,"2,382,202",65.60%,11,"1,167,202",32.14%,–,"47,013",1.29%,–,"18,658",0.51%,–,"16,327",0.45%,–,"1,215,000",33.46%,6.26%,"3,631,402" +Mich.,"2,804,040",50.62%,16,"2,649,852",47.84%,–,"60,381",1.09%,–,"13,718",0.25%,–,"11,311",0.20%,–,"154,188",2.78%,3.01%,"5,539,302" +Minn.,"1,717,077",52.40%,10,"1,484,065",45.28%,–,"34,976",1.07%,–,"10,033",0.31%,–,"31,020",0.95%,–,"233,012",7.11%,5.59%,"3,277,171" +Miss.,"539,398",41.06%,–,"756,764",57.60%,6,"8,026",0.61%,–,"1,498",0.11%,–,"8,073",0.61%,–,"-217,366",-16.55%,1.28%,"1,313,759" +Mo.,"1,253,014",41.41%,–,"1,718,736",56.80%,10,"41,205",1.36%,–,"8,283",0.27%,–,"4,724",0.16%,–,"-465,722",-15.39%,3.25%,"3,025,962" +Mont.,"244,786",40.55%,–,"343,602",56.92%,3,"15,252",2.53%,–,–,–,–,34,0.01%,–,"-98,816",-16.37%,4.05%,"603,674" +Neb. †,"374,583",39.17%,–,"556,846",58.22%,2,"20,283",2.12%,–,,,–,"4,671",0.49%,–,"-182,263",-19.06%,5.99%,"956,383" +"NE-1 +Tooltip Nebraska's 1st congressional district","132,261",41.09%,–,"180,290",56.01%,1,"7,495",2.33%,–,,,–,"1,840",0.57%,–,"-48,029",-14.92%,5.80%,"321,886" +"NE-2 +Tooltip Nebraska's 2nd congressional district","176,468",51.95%,1,"154,377",45.45%,–,"6,909",2.03%,–,,,–,"1,912",0.56%,–,"22,091",6.50%,8.74%,"339,666" +"NE-3 +Tooltip Nebraska's 3rd congressional district","65,854",22.34%,–,"222,179",75.36%,1,"5,879",1.99%,–,,,–,919,0.31%,–,"-156,325",-53.02%,1.17%,"294,831" +Nev.,"703,486",50.06%,6,"669,890",47.67%,–,"14,783",1.05%,–,–,–,–,"17,217",1.23%,–,"33,596",2.39%,-0.03%,"1,405,376" +N.H.,"424,937",52.71%,4,"365,660",45.36%,–,"13,236",1.64%,–,217,0.03%,–,"2,155",0.27%,–,"59,277",7.35%,6.98%,"806,205" +N.J.,"2,608,400",57.33%,14,"1,883,313",41.40%,–,"31,677",0.70%,–,"14,202",0.31%,–,"11,865",0.26%,–,"725,087",15.94%,1.84%,"4,549,457" +N.M.,"501,614",54.29%,5,"401,894",43.50%,–,"12,585",1.36%,–,"4,426",0.48%,–,"3,446",0.37%,–,"99,720",10.79%,2.58%,"923,965" +N.Y.,"5,244,886",60.87%,29,"3,251,997",37.74%,–,"60,383",0.70%,–,"32,832",0.38%,–,"26,763",0.31%,–,"1,992,889",23.13%,0.64%,"8,616,861" +N.C.,"2,684,292",48.59%,–,"2,758,775",49.93%,15,"48,678",0.88%,–,"12,195",0.22%,–,"20,864",0.38%,–,"-74,483",-1.35%,2.31%,"5,524,804" +N.D.,"115,042",31.78%,–,"235,751",65.12%,3,"9,371",2.59%,–,,,–,"1,860",0.51%,–,"-120,709",-33.34%,2.39%,"362,024" +Ohio,"2,679,165",45.24%,–,"3,154,834",53.27%,18,"67,569",1.14%,–,"18,812",0.32%,–,"1,822",0.03%,–,"-475,669",-8.03%,0.10%,"5,922,202" +Okla.,"503,890",32.29%,–,"1,020,280",65.37%,7,"24,731",1.58%,–,–,–,–,"11,798",0.76%,–,"-516,390",-33.09%,3.99%,"1,560,699" +Oregon,"1,340,383",56.45%,7,"958,448",40.37%,–,"41,582",1.75%,–,"11,831",0.50%,–,"22,077",0.93%,–,"381,935",16.08%,5.10%,"2,374,321" +Pa.,"3,458,229",50.02%,20,"3,377,674",48.69%,–,"79,380",1.14%,–,"1,282",0.02%,–,"20,411",0.29%,–,"80,555",1.16%,1.88%,"6,936,976" +R.I.,"307,486",59.39%,4,"199,922",38.61%,–,"5,053",0.98%,–,,,–,"5,296",1.02%,–,"107,564",20.77%,5.26%,"517,757" +S.C.,"1,091,541",43.43%,–,"1,385,103",55.11%,9,"27,916",1.11%,–,"6,907",0.27%,–,"1,862",0.07%,–,"-293,562",-11.68%,2.59%,"2,513,329" +S.D.,"150,471",35.61%,–,"261,043",61.77%,3,"11,095",2.63%,–,–,–,–,–,–,–,"-110,572",-26.16%,3.63%,"422,609" +Tenn.,"1,143,711",37.45%,–,"1,852,475",60.66%,11,"29,877",0.98%,–,"4,545",0.15%,–,"23,243",0.76%,–,"-708,764",-23.21%,2.80%,"3,053,851" +Texas,"5,259,126",46.48%,–,"5,890,347",52.06%,38,"126,243",1.12%,–,"33,396",0.30%,–,"5,944",0.05%,–,"-631,221",-5.58%,3.41%,"11,315,056" +Utah,"560,282",37.65%,–,"865,140",58.13%,6,"38,447",2.58%,–,"5,053",0.34%,–,"19,367",1.30%,–,"-304,858",-20.48%,-2.40%,"1,488,289" +Vt.,"242,820",66.09%,3,"112,704",30.67%,–,"3,608",0.98%,–,"1,310",0.36%,–,"6,986",1.90%,–,"130,116",35.41%,9.00%,"367,428" +Va.,"2,413,568",54.11%,13,"1,962,430",44.00%,–,"64,761",1.45%,–,,,–,"19,765",0.44%,–,"451,138",10.11%,4.79%,"4,460,524" +Wash.,"2,369,612",57.97%,12,"1,584,651",38.77%,–,"80,500",1.97%,–,"18,289",0.45%,–,"34,579",0.85%,–,"784,961",19.20%,3.49%,"4,087,631" +W.Va.,"235,984",29.69%,–,"545,382",68.62%,5,"10,687",1.34%,–,"2,599",0.33%,–,79,0.01%,–,"-309,398",-38.93%,3.14%,"794,731" +Wis.,"1,630,866",49.45%,10,"1,610,184",48.82%,–,"38,491",1.17%,–,"1,089",0.03%,–,"17,411",0.53%,–,"20,682",0.63%,1.40%,"3,298,041" +Wyo.,"73,491",26.55%,–,"193,559",69.94%,3,"5,768",2.08%,–,,,–,"3,947",1.43%,–,"-120,068",-43.38%,2.92%,"276,765" \ No newline at end of file diff --git a/_assets/scripts/data/wi.csv b/_assets/scripts/data/wi.csv new file mode 100644 index 0000000..b02e6a0 --- /dev/null +++ b/_assets/scripts/data/wi.csv @@ -0,0 +1,35 @@ +AmGreatness/TIPP 10/28 - 10/30 831 LV 3.5 48 48 Tie +AmGreatness/TIPP 8/12 - 8/14 976 LV 3.4 47 47 Tie +Atlas Intel 10/30 - 10/31 673 LV 4.0 49 49 Tie +Atlas Intel 9/20 - 9/25 1077 LV 3.0 48 50 Trump +2 +Bloomberg 10/16 - 10/20 643 LV 4.0 48 48 +Bloomberg 9/19 - 9/25 785 LV 3.0 51 48 Harris +3 +CBS News 9/3 - 9/6 958 LV 4.0 51 49 Harris +2 +CNN* 10/23 - 10/28 736 LV 4.8 51 45 Harris +6 +Cook Political Report 7/26 - 8/2 404 LV — 49 46 Harris +3 +Cook Political Report 9/19 - 9/25 411 LV — 49 47 Harris +2 +Emerson 10/21 - 10/22 800 LV 3.4 49 48 Trump +1 +Fabrizio/Anzalone 9/11 - 9/14 600 LV 4.0 49 48 Harris +1 +InsiderAdvantage 10/26 - 10/27 800 LV 3.5 48 49 Trump +1 +InsiderAdvantage 10/8 - 10/9 800 LV 3.5 48 48 Tie +InsiderAdvantage 8/6 - 8/8 800 LV 3.4 48 49 Trump +1 +InsiderAdvantage 9/11 - 9/12 800 LV 3.5 49 47 Harris +2 +Marist 10/27 - 10/30 1330 LV 3.4 50 48 Harris +2 +Marist 9/12 - 9/17 1194 LV 3.6 50 49 Harris +1 +Marquette 7/24 - 8/1 801 LV 4.8 50 49 Harris +1 +Marquette 8/28 - 9/5 738 LV 4.7 52 48 Harris +4 +Marquette 9/18 - 9/26 798 LV 4.4 52 48 Harris +4 +NY Times/Siena 8/5 - 8/8 661 LV — 50 46 Harris +4 +NY Times/Siena 9/21 - 9/26 680 LV — 49 47 Harris +2 +Quinnipiac 10/17 - 10/21 1108 LV 2.9 48 48 Tie +Quinnipiac 10/3 - 10/7 1073 LV 3.0 47 49 Trump +2 +Quinnipiac 9/12 - 9/16 1075 LV 3.0 49 48 Harris +1 +Rasmussen Reports 8/13 - 8/19 1099 LV — 48 47 Harris +1 +Rasmussen Reports 9/19 - 9/22 1071 LV 3.0 49 49 Tie +The Hill/Emerson 10/5 - 10/8 1000 LV 3.0 49 49 Tie +The Hill/Emerson 8/25 - 8/28 850 LV 3.3 48 49 Trump +1 +The Hill/Emerson 9/15 - 9/18 1000 LV 3.0 48 49 Trump +1 +Trafalgar Group (R) 10/18 - 10/20 1083 LV 2.9 47 47 Tie +Trafalgar Group (R) 8/28 - 8/30 1083 LV 2.9 46 47 Trump +1 +Trafalgar Group (R) 9/28 - 9/30 1079 LV 2.9 46 47 Trump +1 +ieo/efficient 9/4 - 9/6 917 LV 3.1 47 47 Tie diff --git a/_assets/scripts/date.jl b/_assets/scripts/date.jl index d02d290..2f19e89 100644 --- a/_assets/scripts/date.jl +++ b/_assets/scripts/date.jl @@ -14,11 +14,16 @@ # mon = sep2 # MON = "sep2" # Mon = "sep2" -prior_month = "sep2" -mon = oct1 -MON = "oct1" -Mon = "oct1" -prior_month = "oct1" +# prior_month = "sep2" +# mon = oct1 +# MON = "oct1" +# Mon = "oct1" +# prior_month = "oct1" +# mon = oct2 +# MON = "oct2" +# Mon = "oct2" +prior_month = "oct2" mon = oct2 MON = "oct2" -Mon = "oct2" \ No newline at end of file +Mon = "oct2" + diff --git a/_assets/scripts/debris/CreateOutcomes.jl b/_assets/scripts/debris/CreateOutcomes.jl deleted file mode 100644 index 1acfee1..0000000 --- a/_assets/scripts/debris/CreateOutcomes.jl +++ /dev/null @@ -1,75 +0,0 @@ -# purpose: create a dataframe `outcomes` with variables state containing states -# that vote in combination in the sample space, the collective electoral votes -# and whether that results in a Harris win, loss or draw - -using CSV -using DataFrames -using Colors -using Combinatorics -using HTTP -using PlotlyJS - -# Include files -include("constants.jl") -include("utils.jl") - -# see college_table.jl for production of 2024vote.csv -base = CSV.read("/Users/ro/projects/swingwatch/_assets/objs/2024vote.csv",DataFrame) -# base.vote = base.harris_col .+ base.trump_col -# base.pop = base.harris_pop .+ base.trump_pop -# base.pct = base.harris_pop ./ base.pop -# base = base[:,[1,4,5,6,7,8,9]] -# new_names = ["st","harris","trump","margin","vote","pop","pct"] -# rename!(base, Symbol.(new_names)) -rename!(base,:biden_pop => "harris_pop") -rename!(base,:biden_col => "harris_col") -base.vote = base.harris_col + base.trump_col - -# create an iterable -votes = Dict(state => base[findfirst(isequal(state), base.st), :vote][1] for state in STATES) -states = collect(keys(votes)) - -# Initialize an object to hold the collected combinations -combos = Dict() - -# To collect combinations for n = 1:7 -Dict{Any, Any}() - -for n in 1:7 - # Generate combinations of length n - combinations_n = combinations(STATES, n) - # Collect combinations and store them in the dictionary - combos[n] = collect(combinations_n) -end - -# harris won 6 of the 7 swing states -blues = sum(base.harris_col) - sum(collect(values(votes))) + votes["NC"] -# trump won NC -reds = sum(base.trump_col) - votes["NC"] - -# expand to dataframe to show each combination with the total -# vote count - -outcome = DataFrame( - combo = [join(combo, ", ", " and ") for combos_list in values(combos) for combo in combos_list], - votes = [sum(votes[state] for state in combo) for combos_list in values(combos) for combo in combos_list] -) - -outcome.harris = outcome.votes .+ blues -outcome.trump = COLLEGE .- outcome.harris -outcome.total = outcome.harris .+ outcome.trump -outcome.check = outcome.total .- COLLEGE -sort!(outcome,:votes) -all(outcome.check .== 0) - -# discard variables used to check arithmetic -outcome = outcome[:,1:4] - -# create variable to show results -outcome.result = Vector{String}(undef, size(outcome, 1)) - -outcome.result[outcome[:,:harris] .< TIE] .= "Trump" -outcome.result[outcome[:,:harris] .== TIE] .= "Tie" -outcome.result[outcome[:,:harris] .> TIE] .= "Harris" - -#CSV.write("/Users/ro/projects/swingwatch/_assets/objs/outcome.csv",outcome) diff --git a/_assets/scripts/debris/ElectionAnalysis.jl b/_assets/scripts/debris/ElectionAnalysis.jl deleted file mode 100644 index 62ddbdc..0000000 --- a/_assets/scripts/debris/ElectionAnalysis.jl +++ /dev/null @@ -1,76 +0,0 @@ -module ElectionAnalysis - -# purpose create a dataframe `outcomes` with variables state containing states # that vote in combination in the sample space, the collective electoral votes -# and whether that results in a Harris win, loss or draw - -using CSV -using DataFrames -using Colors -using Combinatorics -using HTTP -using PlotlyJS - -""" -# Export public functions and types -export find_combinations, electoral_map, determine_result -""" - -# Include your code files -include("/Users/ro/projects/outcomes/code/constants.jl") -include("/Users/ro/projects/outcomes/code/utils.jl") - -# module code - -# see intake.jl for production of 2020vote.csv -base = CSV.read("./objs/2020vote.csv", DataFrame) -base = base[:,[1,4,5]] -base.vote = base.biden_col .+ base.trump_col -new_names = ["st","biden","trump","vote"] -rename!(base, Symbol.(new_names)) - -# create an iterable -votes = Dict(state => base[findfirst(isequal(state), base.st), :vote][1] for state in STATES) -states = collect(keys(votes)) - -# Initialize an object to hold the collected combinations -combos = Dict() - -# To collect combinations for n = 1:7 -Dict{Any, Any}() - -for n in 1:7 - # Generate combinations of length n - combinations_n = combinations(STATES, n) - # Collect combinations and store them in the dictionary - combos[n] = collect(combinations_n) -end - -# biden won 6 of the 7 swing states -blues = sum(base.biden) - sum(collect(values(votes))) -# trump won NC -reds = sum(base.trump) - votes["NC"] - -# expand to dataframe to show each combination with the total -# vote count - -outcome = DataFrame( - combo = [join(combo, ", ", " and ") for combos_list in values(combos) for combo in combos_list], - votes = [sum(votes[state] for state in combo) for combos_list in values(combos) for combo in combos_list] -) - -outcome.biden = outcome.votes .+ blues -outcome.trump = COLLEGE .- outcome.biden -outcome.total = outcome.biden .+ outcome.trump -outcome.check = outcome.total .- COLLEGE -sort!(outcome,:votes) -all(outcome.check .== 0) - -outcome = outcome[:,1:4]] - -outcome.result = Vector{String}(undef, size(outcome, 1)) - -outcome.result[outcome[:,:biden] .< TIE] .= "Trump" -outcome.result[outcome[:,:biden] .== TIE] .= "Tie" -outcome.result[outcome[:,:biden] .> TIE] .= "Harris" - -end # end of module diff --git a/_assets/scripts/debris/MI.jl b/_assets/scripts/debris/MI.jl deleted file mode 100644 index 27f3b87..0000000 --- a/_assets/scripts/debris/MI.jl +++ /dev/null @@ -1,124 +0,0 @@ -ST = "MI" -#------------------------------------------------------------------ -POLLSTER = "Big Data" -B = 41 -T = 46 -N = 1218 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -TYPE_POLL = "3-way" -B = 40 -T = 44 -result = spread(B,T,N) -#------------------------------------------------------------------ - -B = 38 -T = 43 -TYPE_POLL = "3-way" -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "CNN/ssrs" -N = 1097 -B = 42 -T = 50 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -TYPE_POLL = "3-way" -B = 34 -T = 40 -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "Emerson College" - -N = 1000 -B = 44 -T = 45 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -B = 41 -T = 43 -TYPE_POLL = "3-way" -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "Highpoint" -N = -B = -T = -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -B = -T = -TYPE_POLL = "3-way" -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "Marist" -N = -B = -T = -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -B = -T = -TYPE_POLL = "3-way" -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "Quinnipiac University" -N = 1487 -B = 45 -T = 48 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -B = 36 -T = 41 -TYPE_POLL = "3-way" -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "Spry" -N = 709 -B = 44 -T = 48 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -TYPE_POLL = "3-way" -B = 40 -T = 43 -result = spread(B,T,N) - -#------------------------------------------------------------------ -POLLSTER = Suquehanna -N = -B = -T = -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -B = -T = -TYPE_POLL = "3-way" -result = spread(B,T,N) -#------------------------------------------------------------------ -POLLSTER = "WSJ" -N = 600 -B = 45 -T = 48 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -B = 40 -T = 48 -TYPE_POLL = "3-way (long)" -result = spread(B,T,N) - -B = 37 -T = 39 -TYPE_POLL = "3-way (short)" -result = spread(B,T,N) - -#------------------------------------------------------------------ diff --git a/_assets/scripts/debris/_dat.jl b/_assets/scripts/debris/_dat.jl deleted file mode 100644 index af1a0bf..0000000 --- a/_assets/scripts/debris/_dat.jl +++ /dev/null @@ -1,34 +0,0 @@ -@enum Month mar apr may jun jul aug sep oct nov - -MO = may -add_poll!(MO, AZ, bl2,,,,) -add_poll!(MO, PA, bi2,,,,) -add_poll!(MO, MI, bi2,,,,) -add_poll!(MO, PA, bl2,,,,) -add_poll!(MO, GA, bl2,,,,) -add_poll!(MO, NC, bl2,,,,) -add_poll!(MO, MI, bl2,,,,) -add_poll!(MO, AZ, bl2,,,,) -add_poll!(MO, WI, bl2,,,,) -add_poll!(MO, NV, bl2,,,,) -add_poll!(MO, GA, cb2,,,,) -add_poll!(MO, PA, cn2,,,,) -add_poll!(MO, MI, cn2,,,,) -add_poll!(MO, PA, ec2,,,,) -add_poll!(MO, GA, ec2,,,,) -add_poll!(MO, MI, ec2,,,,) -add_poll!(MO, PA, fm2,,,,) -add_poll!(MO, PA, fo2,,,,) -add_poll!(MO, NC, hi2,,,,) -add_poll!(MO, NC, ma2,,,,) -add_poll!(MO, NC, mi2,,,,) -add_poll!(MO, MI, qi2,,,,) -add_poll!(MO, MI, sp2,,,,) -add_poll!(MO, PA, wa2,,,,) -add_poll!(MO, PA, ws2,,,,) -add_poll!(MO, GA, ws2,,,,) -add_poll!(MO, NC, ws2,,,,) -add_poll!(MO, MI, ws2,,,,) -add_poll!(MO, AZ, ws2,,,,) -add_poll!(MO, WI, ws2,,,,) -add_poll!(MO, NV, ws2,,,,) diff --git a/_assets/scripts/debris/aggreg.jl b/_assets/scripts/debris/aggreg.jl deleted file mode 100644 index d602029..0000000 --- a/_assets/scripts/debris/aggreg.jl +++ /dev/null @@ -1,136 +0,0 @@ -const DESIGN_ERROR = 0.012 - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -polls_structure = Dict{String, Dict{String, Vector{Poll}}}() - -function add_poll!(structure, month, state, poll) - if !haskey(structure, month) - structure[month] = Dict{String, Vector{Poll}}() - end - if !haskey(structure[month], state) - structure[month][state] = Vector{Poll}() - end - push!(structure[month][state], poll) -end - -# Example Polls -polls = [ - Poll(0.40, 0.46, 1305), - Poll(0.45, 0.45, 807), - Poll(0.56, 0.46, 520), - Poll(0.50, 0.50, 1000), - Poll(0.43, 0.47, 1000), - Poll(0.48, 0.38, 431), - Poll(0.43, 0.47, 1000), - Poll(0.43, 0.47, 600) -] - -# Assuming you have month and state information for each poll -# For demonstration, let's add them to "January" and "Washington" -for poll in polls - add_poll!(polls_structure, "March", "Pennsylvania", poll) -end - -# Serialize -# bson("savit.bson",polls_structure) -# - -""" - margin_of_error(sample_size::Int64) - -Calculates the margin of error for a given sample size, assuming a 95% confidence level and a maximum variability (p = 0.5). - -# Arguments -- `sample_size::Int64`: The size of the sample. - -# Returns -- `Float64`: The margin of error. - -# Notes -- The margin of error is calculated using the formula: sqrt(0.5 * 0.5 / sample_size) + DESIGN_ERROR, where DESIGN_ERROR is a constant representing the design effect or any additional errors introduced by the sampling procedure. -- The formula assumes a 95% confidence level and a maximum variability of 0.5 (i.e., p = 0.5 and q = 0.5, where p is the estimated proportion of the population with the characteristic of interest, and q = 1 - p). -- The margin of error is a measure of the precision of the estimate and represents the maximum expected difference between the true population parameter and the sample estimate, with a certain level of confidence. - -# Examples -```julia -julia> margin_of_error(100) -0.09799799799799998 - -julia> margin_of_error(1000) -0.031623031623031625 -""" -function margin_of_error(sample_size) - sqrt(0.5 * 0.5 / sample_size) + DESIGN_ERROR -end - -polls = [ - Poll(0.40, 0.46, 1305), - Poll(0.45, 0.45, 807), - Poll(0.56, 0.46, 520), - Poll(0.50, 0.50, 1000), - Poll(0.43, 0.47, 1000), - Poll(0.48, 0.38, 431), - Poll(0.43, 0.47, 1000), - Poll(0.43, 0.47, 600) -] - -total_sample_size = sum(poll.sample_size for poll in polls) - -""" - weighted_average(polls::Vector{<:AbstractPoll}, candidate::Symbol) - -Calculates the weighted average of a candidate's poll results across multiple polls, where -the weights are determined by the inverse of the squared margin of error for each poll. - -# Arguments -- `polls::Vector{<:AbstractPoll}`: A vector of poll objects, each containing information about the poll, such as sample size, candidate results, etc. -- `candidate::Symbol`: The symbol representing the candidate for whom the weighted average is to be calculated. - -# Returns -- `Float64`: The weighted average of the candidate's poll results. - -# Notes -- This function assumes that each poll object has fields named `sample_size` and a field named after the `candidate` symbol, containing the poll result for that candidate. -- The weight for each poll is calculated as `poll.sample_size / (margin_of_error(poll.sample_size)^2)`, which gives more weight to polls with larger sample sizes and smaller margins of error. -- The weighted average is calculated as the sum of (poll result * weight) for all polls, divided by the sum of weights for all polls. -- This method of calculating the weighted average is commonly used in aggregating poll results, as it accounts for the precision of each poll based on its sample size and margin of error. - -# Examples -```julia -# Assuming there are two poll objects, `poll1` and `poll2`, with fields `sample_size`, `:candidate1`, and `:candidate2` -polls = [poll1, poll2] -weighted_avg_candidate1 = weighted_average(polls, :candidate1) -weighted_avg_candidate2 = weighted_average(polls, :candidate2) -""" - -function weighted_average(polls, candidate) - sum( - getfield(poll, candidate) * poll.sample_size / (margin_of_error(poll.sample_size)^2) - for poll in polls - ) / sum( - poll.sample_size / (margin_of_error(poll.sample_size)^2) - for poll in polls - ) -end - -biden_weighted_avg = weighted_average(polls, :biden_support) -trump_weighted_avg = weighted_average(polls, :trump_support) - -function aggregate_margin_of_error(polls) - sqrt( - sum( - (margin_of_error(poll.sample_size)^2) * (poll.sample_size / total_sample_size)^2 - for poll in polls - ) - ) * 1.96 -end - -aggregate_moe = aggregate_margin_of_error(polls) - -println("Aggregated Biden support: $(round(biden_weighted_avg * 100, digits=2))% ± $(round(aggregate_moe * 100, digits=2))%") -println("Aggregated Trump support: $(round(trump_weighted_avg * 100, digits=2))% ± $(round(aggregate_moe * 100, digits=2))%") \ No newline at end of file diff --git a/_assets/scripts/debris/all_votes.jl b/_assets/scripts/debris/all_votes.jl deleted file mode 100644 index 7da706e..0000000 --- a/_assets/scripts/debris/all_votes.jl +++ /dev/null @@ -1,29 +0,0 @@ - find popular votes for all candidates in swing STATES -# for purpose of applying a finite population correction factor -# BUT only in the event of a sample so large as to represent -# MORE than 5% of the population; this possibly could be -# used to assess a large random sample of the previous -# election as a Bayesian prior—see note -using CSV -using DataFrames - -const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] - -votes = CSV.read("../data/votes.csv", DataFrame)[2:57,:] -votes = votes[:,[1,20]] -votes = replace.(votes[:,[1,2]], "," => "") -votes = rename(votes,["state","total"]) - elec = [ - "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", - "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME","ME1", "ME2","MD", - "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NE1", "NE2", "NE3", "NV", "NH", - "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", - "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY" - ] -votes[:,1] = elec -votes[!, :total] = parse.(Int64, votes[:, :total]) - - -votes = filter(row -> row.state in STATES, votes) - -CSV.write("../objs/swing_all_totals.csv",votes) diff --git a/_assets/scripts/debris/alt_swing.jl b/_assets/scripts/debris/alt_swing.jl deleted file mode 100644 index b53f4eb..0000000 --- a/_assets/scripts/debris/alt_swing.jl +++ /dev/null @@ -1,67 +0,0 @@ -using Combinatorics -using CSV -using DataFrames - -const STATES = ["FL","NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const VOTES = [30, 6, 10, 11, 16, 15, 20, 16] -const COLLEGE = 538 -const VICTORY = 270 -const TIE = 269 - -# Initialize an object to hold the collected combinations -combos = Dict() - -# To collect combinations for n = 1:8 -for n in 1:8 - # Generate combinations of length n - combinations_n = combinations(STATES, n) - # Collect combinations and store them in the dictionary - combos[n] = collect(combinations_n) -end - -const BLUE = 212 -const RED = 187 - -base = CSV.read("../objs/2020vote.csv", DataFrame) -base.vote = base.biden_col .+ base.trump_col -base.pop = base.biden_pop .+ base.trump_pop -base.pct = base.biden_pop ./ base.pop -base = base[:,[1,4,5,6,7,8,9]] -new_names = ["st","biden","trump","margin","vote","pop","pct"] -rename!(base, Symbol.(new_names)) - -# create an iterable -votes = Dict(state => base[findfirst(isequal(state), base.st), :vote][1] for state in STATES) - -# biden won 6 of the 7 swing states -blues = 212 -# trump won NC -reds = 187 - -# expand to dataframe to show each combination with the total -# vote count - -outcome = DataFrame( - combo = [join(combo, ", ", " and ") for combos_list in values(combos) for combo in combos_list], - votes = [sum(votes[state] for state in combo) for combos_list in values(combos) for combo in combos_list] -) - -outcome.biden = outcome.votes .+ blues -outcome.trump = COLLEGE .- outcome.biden -outcome.total = outcome.biden .+ outcome.trump -outcome.check = outcome.total .- COLLEGE -sort!(outcome,:votes) -all(outcome.check .== 0) - -# discard variables used to check arithmetic -outcome = outcome[:,1:4] - -# create variable to show results -outcome.result = Vector{String}(undef, size(outcome, 1)) - -outcome.result[outcome[:,:biden] .< TIE] .= "Trump" -outcome.result[outcome[:,:biden] .== TIE] .= "Tie" -outcome.result[outcome[:,:biden] .> TIE] .= "Harris" - -states = collect(keys(votes)) - diff --git a/_assets/scripts/debris/apr_dat.jl b/_assets/scripts/debris/apr_dat.jl deleted file mode 100644 index 12c02ec..0000000 --- a/_assets/scripts/debris/apr_dat.jl +++ /dev/null @@ -1,20 +0,0 @@ -add_poll!(apr AZ bl2 43. 49. 801) -add_poll!(apr GA bl2 45. 47. 802) -add_poll!(apr MI bi2 43. 51. 708) -add_poll!(apr AZ ec2 44. 48. 1000) -add_poll!(apr GA ec2 44. 47. 1000) -add_poll!(apr MI ec2 44. 45. 1000) -add_poll!(apr NV ec2 44. 45. 1000) -add_poll!(apr NC ec2 42. 47. 1000) -add_poll!(apr PA ec2 45. 47. 1000) -add_poll!(apr WI ec2 45. 47. 1000) -add_poll!(apr PA bi2 46. 47. 803) -add_poll!(apr WI bl2 44. 48. 703) -add_poll!(apr GA fo2 45. 51. 1128) -add_poll!(apr MI mr2 36. 42. 600) -add_poll!(apr MI fo2 46. 49. 1106) -add_poll!(apr MI cb2 51. 49. 1287) -add_poll!(apr NC bl2 41. 51. 703) -add_poll!(apr NV bl2 43. 51. 450) -add_poll!(apr PA cb2 49. 50. 1306) -add_poll!(apr WI fo2 48. 48. 1198) \ No newline at end of file diff --git a/_assets/scripts/debris/bayes.jl b/_assets/scripts/debris/bayes.jl deleted file mode 100644 index 88292c4..0000000 --- a/_assets/scripts/debris/bayes.jl +++ /dev/null @@ -1,341 +0,0 @@ -using LinearAlgebra -using Serialization -using StatsPlots -using Turing - -const DESIGN_ERROR = 0.012 - -@enum Month mar apr may jun jul aug sep oct nov - -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -struct NormalizedPoll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -const months = Dict(mar => Dict(), apr => Dict(), may => Dict(), jun => Dict(), jul => Dict(), aug => Dict(), sep => Dict(), oct => Dict(), nov => Dict()) - -# Initialize the nested dictionaries for each state within each month -for month in instances(Month) - for state in instances(State) - months[month][state] = Dict{Pollster, Vector{NormalizedPoll}}() - for pollster in instances(Pollster) - months[month][state][pollster] = NormalizedPoll[] - end - end -end -""" - normalize_poll(poll::Poll) - -Normalizes the poll results for Harris and Trump by dividing their respective support values -by the total support, and returns a `NormalizedPoll` object with the normalized values and sample size. - -# Arguments -- `poll::Poll`: A `Poll` object containing the raw poll data, including `biden_support`, `trump_support`, and `sample_size` fields. - -# Returns -- `NormalizedPoll`: A `NormalizedPoll` object with the following fields: - - `normalized_biden::Float64`: The normalized support for Harris (between 0 and 1). - - `normalized_trump::Float64`: The normalized support for Trump (between 0 and 1). - - `sample_size::Int64`: The sample size of the poll. - -# Notes -- This function assumes that the `Poll` object has fields named `biden_support`, `trump_support`, and `sample_size`. -- The normalization is performed by dividing the `biden_support` and `trump_support` values by the total support (sum of `biden_support` and `trump_support`). -- The normalized values represent the proportion of support for each candidate out of the total support. -- The `NormalizedPoll` object is created with the normalized values and the original `sample_size`. - -# Examples -```julia -# Assuming there is a `Poll` object `poll` with fields `biden_support`, `trump_support`, and `sample_size` -""" -function normalize_polls!(month) - for state in keys(months[month]) - for pollster in keys(months[month][state]) - for poll in months[month][state][pollster] - total = poll.biden_support + poll.trump_support - normalized_biden = poll.biden_support / total - normalized_trump = poll.trump_support / total - poll.biden_support = normalized_biden - poll.trump_support = normalized_trump - end - end - end -end - -function add_poll!(month::Month, state::State, pollster::Pollster, poll::Poll) - normalized_poll = NormalizedPoll(poll.biden_support, poll.trump_support, poll.sample_size) - push!(months[month][state][pollster], normalized_poll) -end - -add_poll!(mar, AZ, bl2, Poll(42., 49., 788)) -add_poll!(mar, PA, bi2, Poll(40., 46., 1305)) -add_poll!(mar, MI, bi2, Poll(42., 45., 1218)) -add_poll!(mar, PA, bl2, Poll(45., 45., 807)) -add_poll!(mar, GA, bl2, Poll(42., 49., 788)) -add_poll!(mar, NC, bl2, Poll(43., 49., 699)) -add_poll!(mar, MI, bl2, Poll(44., 46., 447)) -add_poll!(mar, AZ, bl2, Poll(42., 49., 788)) -add_poll!(mar, WI, bl2, Poll(46., 45., 697)) -add_poll!(mar, NV, bl2, Poll(43., 49., 699)) -add_poll!(mar, GA, cb2, Poll(48., 51., 1133)) -add_poll!(mar, PA, cn2, Poll(46., 46., 1132)) -add_poll!(mar, MI, cn2, Poll(42., 50., 1097)) -add_poll!(mar, PA, ec2, Poll(43., 45., 1000)) -add_poll!(mar, GA, ec2, Poll(42., 46., 1000)) -add_poll!(mar, MI, ec2, Poll(44., 45., 1000)) -add_poll!(mar, PA, fm2, Poll(48., 38., 431)) -add_poll!(mar, PA, fo2, Poll(45., 49., 1121)) -add_poll!(mar, NC, hi2, Poll(38., 44., 1016)) -add_poll!(mar, NC, ma2, Poll(48., 51., 1295)) -add_poll!(mar, NC, mi2, Poll(44., 47., 626)) -add_poll!(mar, MI, qi2, Poll(45., 48., 1487)) -add_poll!(mar, MI, sp2, Poll(44., 48., 709)) -add_poll!(mar, PA, wa2, Poll(45., 50., 736)) -add_poll!(mar, PA, ws2, Poll(44., 47., 600)) -add_poll!(mar, GA, ws2, Poll(43., 44., 600)) -add_poll!(mar, NC, ws2, Poll(43., 49., 600)) -add_poll!(mar, MI, ws2, Poll(45., 48., 600)) -add_poll!(mar, AZ, ws2, Poll(44., 47., 600)) -add_poll!(mar, WI, ws2, Poll(46., 46., 600)) -add_poll!(mar, NV, ws2, Poll(44., 48., 600)) - -# Define the states and their electoral votes - -#states = ["PA", "MI", "GA", "NC", "AZ", "WI", "NV"] -electoral_votes = [19, 15, 16, 16, 11, 10, 6] - -prior_probs = Dict( - "AZ" => 1672143 / (1672143 + 1661686), - "GA" => 2473633 / (2473633 + 2461854), - "MI" => 2804040 / (2804040 + 2649852), - "NC" => 2684292 / (2684292 + 2758775), - "PA" => 3458229 / (3458229 + 3377674), - "WI" => 1630866 / (1630866 + 1610184), - "NV" => 703486 / ( 703486 + 669890) -) - -function get_state_polls(month::Month) - state_polls = Dict{State, Vector{PollData}}() - for state in instances(State) - polls = PollData[] - for pollster in instances(Pollster) - if haskey(master_polls.data, pollster) && - haskey(master_polls.data[pollster], month) && - haskey(master_polls.data[pollster][month].data, state) - poll_data = master_polls.data[pollster][month].data[state][1] - if !ismissing(poll_data.biden_support) && !ismissing(poll_data.trump_support) && !ismissing(poll_data.sample_size) - push!(polls, poll_data) - end - end - end - if !isempty(polls) - state_polls[state] = polls - end - end - return state_polls -end - -state_polls_mar = get_state_polls(mar) - - - -# Define the model -# -# @model function election_model(normalized_state_polls, prior_probs) -# # Define the model parameters -# state_probs = Dict(state => Uniform(0, 1) for state in keys(normalized_state_polls)) -# -# # Define the likelihood -# for (state, polls) in normalized_state_polls -# for poll in polls -# biden_support = poll.biden_support -# trump_support = poll.trump_support -# sample_size = poll.sample_size -# -# # Likelihood of the poll data given the state probability -# biden_count = round(Int, biden_support * sample_size) -# biden_count ~ Binomial(sample_size, state_probs[state]) -# end -# end -# -# # Define the prior -# for (state, prior_prob) in prior_probs -# state_probs[state] ~ Beta(prior_prob, 1 - prior_prob) -# end -# -# # Return the state probabilities -# return state_probs -# end - -# # Assign prior probabilities to each state based on relative votes -# -# state_probs = Vector{Float64}(undef, length(states)) -# for i in 1:length(states) -# state = states[i] -# prior_prob = prior_probs[state] -# state_probs[i] ~ Beta(prior_prob * 10, (1 - prior_prob) * 10) -# end -# # Return the state probabilities -# return state_probs -# end - -function outcome_probability(combination) - prob = 1.0 - for i in 1:length(states) - if combination[i] == 1 - prob *= mean(p_samples[:, i]) - else - prob *= 1 - mean(p_samples[:, i]) - end - end - return prob -end - -# Run the inference - -# INDIFFERENT -@model function election_model(normalized_state_polls, prior_probs) - # Define the model parameters - state_probs = Dict(state => Uniform(0, 1) for state in keys(normalized_state_polls)) - - # Define the likelihood - for (state, polls) in normalized_state_polls - for poll in polls - biden_support = poll.biden_support - trump_support = poll.trump_support - sample_size = poll.sample_size - - # Sample the state probability from the Uniform distribution - state_prob = rand(state_probs[state]) - - # Likelihood of the poll data given the state probability - biden_count = round(Int, biden_support * sample_size) - biden_count ~ Binomial(sample_size, state_prob) - end - end - - # Define the prior - for (state, prior_prob) in prior_probs - state_probs[state] ~ Beta(prior_prob, 1 - prior_prob) - end - - # Return the state probabilities - return state_probs -end - -@model function election_model(normalized_state_polls, prior_probs) - # Define the model parameters - state_probs = Dict(state => Uniform(0, 1) for state in keys(normalized_state_polls)) - - # Define the likelihood - for (state, polls) in normalized_state_polls - for poll in polls - biden_support = poll.biden_support - trump_support = poll.trump_support - sample_size = poll.sample_size - - # Sample the state probability from the Uniform distribution - state_prob = rand(state_probs[state]) - - # Likelihood of the poll data given the state probability - biden_count = round(Int, biden_support * sample_size) - biden_count ~ Binomial(sample_size, state_prob) - end - end - - # Define the prior - for (state, prior_prob) in prior_probs - state_probs[state] ~ Beta(prior_prob, 1 - prior_prob) - end - - # Return the state probabilities directly - return state_probs -end - -chain = sample(election_model(normalized_state_polls, prior_probs), NUTS(), MCMCThreads(), num_samples, num_chains) - -# Extract the posterior samples -posterior_samples = chain[:state_probs] - -# Calculate the posterior probabilities -global post_win = 0.0 -global post_lose = 0.0 - -for combination in Iterators.product(fill(0:1, length(states))...) - combination_vector = collect(combination) - if dot(combination_vector, electoral_votes) >= 45 # 270 - 225 BLUE - global post_win += outcome_probability(combination_vector) - else - global post_lose += outcome_probability(combination_vector) - end -end - -post_tie = 1 - post_win - post_lose - -println("Posterior probabilities:") -println("Win: ", post_win) -println("Lose: ", post_lose) -println("Tie: ", post_tie) -println("Sum: ", sum([post_win, post_lose, post_tie])) - -# diagnostics - -summarystats(chain) -plot(chain) -autocor(chain) -ess(chain) - - - -# Column names to round -columns_to_round = [:votes, :low, :mean, :high, :expect] - -# Apply rounding using column names -for col_name in columns_to_round - df[!, col_name] = round.(df[!, col_name], digits = 2) -end diff --git a/_assets/scripts/debris/bayes2.jl b/_assets/scripts/debris/bayes2.jl deleted file mode 100644 index b5ef1ff..0000000 --- a/_assets/scripts/debris/bayes2.jl +++ /dev/null @@ -1,131 +0,0 @@ -using LinearAlgebra -using Serialization -using StatsPlots -using Turing - -const DESIGN_ERROR = 0.012 - -@enum Month mar apr may jun jul aug sep oct nov - -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -struct NormalizedPoll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -const months = Dict(mar => Dict(), apr => Dict(), may => Dict(), jun => Dict(), jul => Dict(), aug => Dict(), sep => Dict(), oct => Dict(), nov => Dict()) - -# Initialize the nested dictionaries for each state within each month -for month in instances(Month) - for state in instances(State) - months[month][state] = Dict{Pollster, Vector{NormalizedPoll}}() - for pollster in instances(Pollster) - months[month][state][pollster] = NormalizedPoll[] - end - end -end - -function normalize_polls!(month) - for state in keys(months[month]) - for pollster in keys(months[month][state]) - for poll in months[month][state][pollster] - total = poll.biden_support + poll.trump_support - normalized_biden = poll.biden_support / total - normalized_trump = poll.trump_support / total - poll.biden_support = normalized_biden - poll.trump_support = normalized_trump - end - end - end -end - -function add_poll!(month::Month, state::State, pollster::Pollster, poll::Poll) - normalized_poll = NormalizedPoll(poll.biden_support, poll.trump_support, poll.sample_size) - push!(months[month][state][pollster], normalized_poll) -end - -add_poll!(mar, AZ, bl2, Poll(42., 49., 788)) -add_poll!(mar, AZ, ec2, Poll(44., 48., 1000)) -add_poll!(mar, AZ, ws2, Poll(44., 47., 600)) -add_poll!(mar, GA, bl2, Poll(42., 49., 788)) -add_poll!(mar, GA, cb2, Poll(48., 51., 1133)) -add_poll!(mar, GA, ec2, Poll(42., 46., 1000)) -add_poll!(mar, GA, ws2, Poll(43., 44., 600)) -add_poll!(mar, MI, bi2, Poll(42., 45., 1218)) -add_poll!(mar, MI, bl2, Poll(44., 46., 447)) -add_poll!(mar, MI, cn2, Poll(42., 50., 1097)) -add_poll!(mar, MI, ec2, Poll(44., 45., 1000)) -add_poll!(mar, MI, qi2, Poll(45., 48., 1487)) -add_poll!(mar, MI, sp2, Poll(44., 48., 709)) -add_poll!(mar, MI, ws2, Poll(45., 48., 600)) -add_poll!(mar, NC, bl2, Poll(43., 49., 699)) -add_poll!(mar, NC, hi2, Poll(38., 44., 1016)) -add_poll!(mar, NC, ma2, Poll(48., 51., 1295)) -add_poll!(mar, NC, mi2, Poll(44., 47., 626)) -add_poll!(mar, NC, ws2, Poll(43., 49., 600)) -add_poll!(mar, NV, bl2, Poll(43., 49., 699)) -add_poll!(mar, NV, ws2, Poll(44., 48., 600)) -add_poll!(mar, PA, bi2, Poll(40., 46., 1305)) -add_poll!(mar, PA, bl2, Poll(45., 45., 807)) -add_poll!(mar, PA, cn2, Poll(46., 46., 1132)) -add_poll!(mar, PA, ec2, Poll(43., 45., 1000)) -add_poll!(mar, PA, fm2, Poll(48., 38., 431)) -add_poll!(mar, PA, fo2, Poll(45., 49., 1121)) -add_poll!(mar, PA, wa2, Poll(45., 50., 736)) -add_poll!(mar, PA, ws2, Poll(44., 47., 600)) -add_poll!(mar, WI, bl2, Poll(46., 45., 697)) -add_poll!(mar, WI, ws2, Poll(46., 46., 600)) - -function filter_empty_entries(dict::Dict{Pollster, Vector{NormalizedPoll}}) - return Dict(pollster => polls for (pollster, polls) in dict if !isempty(polls)) -end - -# Create a new dictionary of dictionaries with non-empty NormalizedPoll objects -filtered_months = Dict(state => filter_empty_entries(subject[state]) for state in instances(State)) - - - diff --git a/_assets/scripts/debris/bayes_head.jl b/_assets/scripts/debris/bayes_head.jl deleted file mode 100644 index 094ce37..0000000 --- a/_assets/scripts/debris/bayes_head.jl +++ /dev/null @@ -1,80 +0,0 @@ -using DataFrames -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -const DESIGN_ERROR = 0.012 - -@enum Month mar apr may jun jul aug sep oct nov - -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - - -const months = Dict(mar => Dict(), apr => Dict(), may => Dict(), jun => Dict(), jul => Dict(), aug => Dict(), sep => Dict(), oct => Dict(), nov => Dict()) - -# prior_probs = Dict( -# AZ => 1672143 / (1672143 + 1661686), -# GA => 2473633 / (2473633 + 2461854), -# MI => 2804040 / (2804040 + 2649852), -# NC => 2684292 / (2684292 + 2758775), -# PA => 3458229 / (3458229 + 3377674), -# WI => 1630866 / (1630866 + 1610184), -# NV => 703486 / ( 703486 + 669890) -# ) -# -# -# prior_probs = Dict( -# AZ => 1672143 / (1672143 + 1661686), -# GA => 2473633 / (2473633 + 2461854), -# MI => 2804040 / (2804040 + 2649852), -# NC => 2684292 / (2684292 + 2758775), -# PA => 3458229 / (3458229 + 3377674), -# WI => 1630866 / (1630866 + 1610184), -# NV => 703486 / ( 703486 + 669890) -# ) \ No newline at end of file diff --git a/_assets/scripts/debris/bayes_main.jl b/_assets/scripts/debris/bayes_main.jl deleted file mode 100644 index a43d367..0000000 --- a/_assets/scripts/debris/bayes_main.jl +++ /dev/null @@ -1,97 +0,0 @@ -@model function election_model(state_polls, prior_prob) - # Define the model parameters - biden_prob ~ Uniform(0, 1) - trump_prob = 1 - biden_prob - - # Define the likelihood - for (_, polls) in state_polls - for poll in polls - biden_count = poll.biden_support - trump_count = poll.trump_support - sample_size = poll.sample_size - - # Convert counts to proportions - biden_prop = biden_count / sample_size - trump_prop = trump_count / sample_size - - # Likelihood of the poll data given the state probabilities - biden_prop ~ Normal(biden_prob, 0.1) - trump_prop ~ Normal(trump_prob, 0.1) - end - end - - # Define the prior - biden_prob ~ Beta(prior_prob, 1 - prior_prob) - - # Return the Harris and Trump probabilities - return (biden_prob, trump_prob) -end - -current_model = election_model(current_mon, prior_probs[ST]) - -current_samples = sample(current_model, NUTS(), 1_000_000) - -# Summary statistics -summarystats(current_samples) - -# Autocorrelation -autocor(current_samples) - -# Effective sample size -ess(current_samples) - -# Trace plot -plot(current_samples) - -# Or using HMC sampler with a specified step size and number of leapfrog steps -# ETA 2.5 days, not run -# current_samples = sample(current_model, HMC(0.1, 10), 10_000) - -# runs within minutes, but not pooled, so don't use -# current_samples = sample(current_model, NUTS(0.65), MCMCThreads(), 500, 50) -# summarystats(current_samples) -# plot(current_samples) -# autocor(current_samples) -# ess(current_samples) - -biden_prob_samples = current_samples[:biden_prob] -biden_prob_mode = mode(biden_prob_samples) - -biden_prob_mean = mean(biden_prob_samples) -biden_prob_median = median(biden_prob_samples) -biden_prob_sd = std(biden_prob_samples) -biden_prob_credible_interval = quantile(biden_prob_samples, [0.025, 0.975]) -trump_prob_samples = 1 .- current_samples[:biden_prob] -trump_prob_mode = mode(trump_prob_samples) - -trump_prob_mean = mean(trump_prob_samples) -trump_prob_median = median(trump_prob_samples) -trump_prob_sd = std(trump_prob_samples) -trump_prob_credible_interval = quantile(trump_prob_samples, [0.025, 0.975]) -println("Harris Probability:") -println(" Mean: ", biden_prob_mean) -println(" Mode: ", biden_prob_mode) -println(" Median: ", biden_prob_median) -println(" Standard Deviation: ", biden_prob_sd) -println(" 95% Credible Interval: ", biden_prob_credible_interval) - - -summary_df = DataFrame( - Parameter = ["Harris likelihood", "Trump likelihood"], - Mean = [biden_prob_mean, trump_prob_mean], - Mode = [biden_prob_mode, trump_prob_mode], - Median = [biden_prob_median, trump_prob_median], - CI_Lower = [biden_prob_credible_interval[1], trump_prob_credible_interval[1]], - CI_Upper = [biden_prob_credible_interval[2], trump_prob_credible_interval[2]] -) - -# Define a formatter function that formats floating-point numbers to four decimal places -formatter = (v, i, j) -> isa(v, Float64) ? @sprintf("%.4f", v) : v - -# Apply the formatter to all columns of the table -pretty_table(summary_df, - backend = Val(:html), - header = names(summary_df), - formatters = formatter, - standalone = false) - diff --git a/_assets/scripts/debris/blank_dat.csv b/_assets/scripts/debris/blank_dat.csv deleted file mode 100644 index 6a6ffdf..0000000 --- a/_assets/scripts/debris/blank_dat.csv +++ /dev/null @@ -1,31 +0,0 @@ -add_poll!(apr, AZ, bl2,,,,) -add_poll!(apr, PA, bi2,,,,) -add_poll!(apr, MI, bi2,,,,) -add_poll!(apr, PA, bl2,,,,) -add_poll!(apr, GA, bl2,,,,) -add_poll!(apr, NC, bl2,,,,) -add_poll!(apr, MI, bl2,,,,) -add_poll!(apr, AZ, bl2,,,,) -add_poll!(apr, WI, bl2,,,,) -add_poll!(apr, NV, bl2,,,,) -add_poll!(apr, GA, cb2,,,,) -add_poll!(apr, PA, cn2,,,,) -add_poll!(apr, MI, cn2,,,,) -add_poll!(apr, PA, ec2,,,,) -add_poll!(apr, GA, ec2,,,,) -add_poll!(apr, MI, ec2,,,,) -add_poll!(apr, PA, fm2,,,,) -add_poll!(apr, PA, fo2,,,,) -add_poll!(apr, NC, hi2,,,,) -add_poll!(apr, NC, ma2,,,,) -add_poll!(apr, NC, mi2,,,,) -add_poll!(apr, MI, qi2,,,,) -add_poll!(apr, MI, sp2,,,,) -add_poll!(apr, PA, wa2,,,,) -add_poll!(apr, PA, ws2,,,,) -add_poll!(apr, GA, ws2,,,,) -add_poll!(apr, NC, ws2,,,,) -add_poll!(apr, MI, ws2,,,,) -add_poll!(apr, AZ, ws2,,,,) -add_poll!(apr, WI, ws2,,,,) -add_poll!(apr, NV, ws2,,,,) diff --git a/_assets/scripts/debris/cohorts.jl b/_assets/scripts/debris/cohorts.jl deleted file mode 100644 index bd02113..0000000 --- a/_assets/scripts/debris/cohorts.jl +++ /dev/null @@ -1,40 +0,0 @@ -using BSON: @save -using CSV -using DataFrames -using PrettyTables - - -mutable struct MetaFrames - meta::Dict{Symbol, Any} - data::DataFrame -end - -cohort2020 = CSV.read("../data/2020age.csv",DataFrame) -cohort2022 = CSV.read("../data/2022age.csv",DataFrame) - -using Missings -cohort2022.vot = map(Int64, collect(skipmissing(cohort2022.vot))) - -meta_info_2020 = Dict( - :source => "U.S. Census Bureau, Current Population Survey, November 2022", - :url => "https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-585.html", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022" -) - -meta_info_2022 = Dict( -:source => "U.S. Census Bureau, Current Population Survey, November 2022", -:url => "https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-586.html", -:title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022") - -meta_cohort_2020 = MetaFrames(meta_info_2020, cohort2020) -meta_cohort_2022 = MetaFrames(meta_info_2022, cohort2022) - -@save "../objs/meta_cohort_2020.bson" meta_cohort_2020 -@save "../objs/meta_cohort_2022.bson" meta_cohort_2022 - - -cohort2020 = cohort2020[cohort2020.cohort .== "18 to 24", :] -cohort2022 = cohort2022[cohort2022.cohort .== "18 to 24 years", :] - - - diff --git a/_assets/scripts/debris/college_table.jl b/_assets/scripts/debris/college_table.jl deleted file mode 100644 index 591c316..0000000 --- a/_assets/scripts/debris/college_table.jl +++ /dev/null @@ -1,92 +0,0 @@ -# 2024 electoral college table -using CSV -using DataFrames -using PrettyTables - -df = CSV.read("/Users/ro/projects/swingwatch/_assets/objs/college.csv", DataFrame) -t1 = df[:,[1,2]] -t2 = df[:,[3,4]] -t3 = df[:,[5,6]] -header = ["st","ev"] -rename!(t1, 1 => Symbol(header[1]), 2 => Symbol(header[2])) -rename!(t2, 1 => Symbol(header[1]), 2 => Symbol(header[2])) -rename!(t3, 1 => Symbol(header[1]), 2 => Symbol(header[2])) -df = vcat(t1,t2,t3) -# change ME to 2 and add ME1 and ME2 at one each -df[20,2] = 2 -push!(df,("ME1",1)) -push!(df,("ME2",1)) -# change NB to 2 and add NE1, NE2, and NE3 at one each -df[28,2] = 2 -push!(df,("NB1",1)) -push!(df,("NB2",1)) -push!(df,("NB3",1)) -sort!(df,:st) - -po = ["AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC","FL", - "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", - "ME1", "ME2", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", - "NE1", "NE2", "NE3", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", - "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", - "VT", "VA", "WA", "WV", "WI", "WY"] -df = hcat(df,po) -new_swing = ["PA","GA","NC","MI","AZ","WI","NV"] -old_swing = ["PA","GA", "MI","AZ","WI","NV"] - -mask = [any(occursin(pattern, string) for pattern in old_swing) for string in df.x1] -new = df[:,[:x1,:ev]] -rename!(new, 1 => Symbol(header[1]), 2 => Symbol(header[2])) -sort!(new,:st) -old = df = CSV.read("/Users/ro/projects/swingwatch/_assets/objs/2020vote.csv", DataFrame) -new = innerjoin(old, new, on = :st) -new.old = new.biden_col + new.trump_col -new.chg = new.ev - new.old -change = new[new.chg .!= 0,:] -losers = new[new.chg .<0,:] -winners = new[new.chg .>0,:] -new.biden_col_adjust = ifelse.(new.biden_col .!= 0, new.biden_col .+ new.chg, new.biden_col) -new.trump_col_adjust = ifelse.(new.trump_col .!= 0, new.trump_col .+ new.chg, new.trump_col) - -old_blue = sum(new.biden_col) -old_red = sum(new.trump_col) -new_blue = sum(new.biden_col_adjust) -new_red = sum(new.trump_col_adjust) - -# Create a boolean mask for states not in old_swing -mask_out = .!in.(new.st, Ref(old_swing)) -mask_in = in.(new.st, Ref(old_swing)) -mask_new = in.(new,st, Ref(new_swing)) -# Calculate the sum of biden_col_adj excluding old_swing states -blue_start = new_blue - sum(new[mask_in, :biden_col_adjust]) -# Subtract NC from trump_col_adj -red_start = sum(new.trump_col_adjust) - new[30,:ev] -swing_voles = sum(new[mask_new,:ev]) -votes = new[:,[:st,:biden_pop,:trump_pop,:margin,:biden_col_adjust,:trump_col_adjust]] -header = ["st","biden_pop","trump_pop","margin","biden_col","trump_col"] - -# Assume you have a DataFrame named 'df' -# and a vector of new column names called 'header' - -# Create a dictionary to map old column names to new column names -name_dict = Dict(zip(names(votes), header)) - -# Rename the columns using the dictionary -rename!(votes, name_dict) - -# CSV.write("/Users/ro/projects/swingwatch/_assets/objs/2024vote.csv",votes) - -# 2024 table -# changes - - -const FLAGRED = "#B22234" -const FLAGBLUE = "#3C3B6E" -change.color = ifelse.(change.biden_col .!= 0, FLAGBLUE,FLAGRED) -change.party = ifelse.(change.biden_col .!= 0, "Harris","Trump") -sort!(tab1,[:party,:st]) -tab1 = change[:,[:st,:ev,:old,:chg,:party]] -sort!(tab1,[:party,:st]) -tab2 = change[:,[:st,:ev,:old,:chg,:color]] - -header = ["State","2024 Electoral Votes","2020 Electoral Votes","Change","Won by"] -pretty_table(tab1, backend = Val(:html), header = header, standalone = false) \ No newline at end of file diff --git a/_assets/scripts/debris/commons.jl b/_assets/scripts/debris/commons.jl deleted file mode 100644 index 4fdc6e2..0000000 --- a/_assets/scripts/debris/commons.jl +++ /dev/null @@ -1,254 +0,0 @@ -using BSON: @load, @save -using Colors -using Combinatorics -using CSV -using DataFrames -using Format -using HTTP -using GLMakie -using KernelDensity -using LinearAlgebra -using MCMCChains -using Missings -using PlotlyJS -using Plots -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing -#------------------------------------------------------------------ -@enum Month mar apr may jun jul aug sep oct nov -@enum State PA GA NC MI AZ WI NV -STATE = State -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end -#------------------------------------------------------------------ -const states = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const FLAGRED = "rgb(178, 34, 52)" -const FLAGBLUE = "rgb(60, 59, 110)" -const PURPLE = "rgb(119, 47, 81)" -const GREENBAR = "rgb(47, 119, 78)" -#------------------------------------------------------------------ -mutable struct MetaFrame - meta::Dict{Symbol, Any} - data::DataFrame -end -#------------------------------------------------------------------ -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end -#------------------------------------------------------------------ -""" - remove_empty_entries(dict::Dict{Pollster, Vector{Poll}}) -> Dict{Pollster, Vector{Poll}} - -Filter out entries in a dictionary where the values are empty vectors. - -# Arguments -- `dict::Dict{Pollster, Vector{Poll}}`: A dictionary where the keys are of type `Pollster` and the values are vectors of type `Poll`. - -# Returns -- `Dict{Pollster, Vector{Poll}}`: A new dictionary containing only the entries from the input dictionary where the vectors are not empty. - -# Description -The `remove_empty_entries` function iterates over each key-value pair in the provided dictionary. It constructs a new dictionary that includes only those entries where the value (a vector of `Poll` objects) is not empty. - -# Example -```julia -# Define types for the example -struct Pollster - name::String -end - -struct Poll - question::String - response::String -end - -# Create a dictionary with some empty and non-empty vectors -pollster1 = Pollster("Pollster A") -pollster2 = Pollster("Pollster B") -poll1 = Poll("Question 1", "Response 1") -poll2 = Poll("Question 2", "Response 2") - -dict = Dict( - pollster1 => [poll1, poll2], - pollster2 => [] -) - -# Filter out entries with empty vectors -filtered_dict = remove_entries(dict) -println(filtered_dict) -# Output: -# Dict{Pollster, Vector{Poll}} with 1 entry: -# Pollster("Pollster A") => Poll[Poll("Question 1", "Response 1"), Poll("Question 2", "Response 2")] -""" -function remove_empties(the_month::Dict) - Dict(state => Dict(pollster => polls for (pollster, polls) in pollsters - if !isempty(polls)) for (state, pollsters) in the_month) -end -#------------------------------------------------------------------ -""" - metahelp() - -shows MetaFrame structure and give example - -mutable struct MetaFrame - meta::Dict{Symbol, Any} - data::DataFrame -end - -# Example usage -df = DataFrame(name=["John", "Jane"], age=[28, 34]) -meta_info = Dict(:source => "Survey Data", :year => 2021) - -df = MetaFrame(meta_info, df) - -meta_info = Dict( - :source => "Census Bureau, Current Population Survey, November 2022", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022", - :url => "https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-586.html", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022") -""" -function metahelp() - println("Display with ?metahelp") -end -#------------------------------------------------------------------ -""" - radix(df::DataFrame) - -Format integer columns in a DataFrame with thousands separators and return a new DataFrame -with the formatted columns appended. - -# Arguments -- `df::DataFrame`: The input DataFrame containing the columns to be formatted. - -# Returns -- `DataFrame`: A new DataFrame with the original columns and the formatted columns appended. - The formatted columns have "_formatted" suffix added to their names. - -# Example -```julia -julia> using DataFrames - -julia> df = DataFrame(A = [1000, 2000, 3000], B = ["text1", "text2", "text3"], C = [4000, 5000, 6000]) -3×3 DataFrame - Row │ A B C - │ Int64 String Int64 -─────┼────────────────────── - 1 │ 1000 text1 4000 - 2 │ 2000 text2 5000 - 3 │ 3000 text3 6000 - -julia> radix(df) -3×5 DataFrame - Row │ A B C A_formatted C_formatted - │ Int64 String Int64 String String -─────┼─────────────────────────────────────────────── - 1 │ 1000 text1 4000 "1,000" "4,000" - 2 │ 2000 text2 5000 "2,000" "5,000" - 3 │ 3000 text3 6000 "3,000" "6,000" -In the example above, the radix function is applied to a DataFrame df containing integer -columns. The function formats the integer columns with thousands separators and returns a new -DataFrame with the formatted columns appended. The formatted columns have "_formatted" suffix -added to their names. -""" -function radix(df::DataFrame) - formatted_df = copy(df) - for col in names(formatted_df) - if eltype(formatted_df[:, col]) <: Integer - formatted_col_name = Symbol(string(col) * "_formatted") - formatted_df[:, formatted_col_name] = map(x -> format(x, commas=true), formatted_df[:, col]) - end - end - return formatted_df -end -#------------------------------------------------------------------ -""" - format_table(summary_df::DataFrame) - -Format floating-point numbers in a DataFrame to four decimal places and display the table using PrettyTables.jl. - -# Arguments -- `summary_df::DataFrame`: The DataFrame containing the data to be formatted and displayed. - -# Description -The `format_table` function formats all floating-point numbers in the provided DataFrame to four decimal places. It uses the PrettyTables.jl package to display the formatted table in HTML format. The function applies a formatter to each cell in the DataFrame, checking if the value is of type `Float64` and formatting it accordingly. Non-floating-point values are left unchanged. - -# Example -```julia -using DataFrames, PrettyTables, Printf - -# Create a sample DataFrame -summary_df = DataFrame(A = [1.123456, 2.234567, 3.345678], B = [4.456789, 5.567890, 6.678901]) - -# Define the format_table function -function format_table(summary_df::DataFrame) - formatter = (v, i, j) -> isa(v, Float64) ? @sprintf("%.4f", v) : v - # Apply the formatter to all columns of the table - pretty_table(summary_df, - backend = Val(:html), - header = names(summary_df), - formatters = formatter, - standalone = false) -end - -# Call the function to format and display the table -format_table(summary_df) -# Formats floating-point numbers to four decimal places in table -""" -function format_table(summary_df::DataFrame) - formatter = (v, i, j) -> isa(v, Float64) ? @sprintf("%.4f", v) : v - # Apply the formatter to all columns of the table - PrettyTables::pretty_table(summary_df, - backend = Val(:html), - header = names(summary_df), - formatters = formatter, - standalone = false) -end -#------------------------------------------------------------------ -function remove_empties(the_month::Dict) - Dict(state => Dict(pollster => polls for (pollster, polls) in pollsters - if !isempty(polls)) for (state, pollsters) in the_month) -end -#------------------------------------------------------------------ -function process_polls(polls::Vector{Poll}) - result = Int64.(collect(collect([(p.biden_support, p.sample_size) for p in polls])[1])) - return [Int64(floor(result[1] / 100 * result[2])), result[2]] -end \ No newline at end of file diff --git a/_assets/scripts/debris/cons.jl b/_assets/scripts/debris/cons.jl deleted file mode 100644 index a6eb83a..0000000 --- a/_assets/scripts/debris/cons.jl +++ /dev/null @@ -1,34 +0,0 @@ -# Set directory hierarchy - -root = "." -code = root * "/code/" -made = root * "/objs/" -data = root * "/data/" - -# Define the state abbreviations and their corresponding electoral votes - -const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const VOTES = [6, 10, 11, 16, 16, 20, 16] - -# Initialize an object to hold the collected combinations -collected_combinations = Dict() - -# To collect combinations for n = 1:7 -for n in 1:7 - # Generate combinations of length n - combinations_n = combinations(STATES, n) - # Collect combinations and store them in the dictionary - collected_combinations[n] = collect(combinations_n) -end - -# Now `collected_combinations` holds all the collected combinations for n = 1:7 - -# votes in Electoral College -const COLLEGE = 538 -const VICTORY = 270 -const TIE = 269 - -# Create a color scale with discrete colors for each value - -const PURPLES = ["#CFA2DB", "#B583A4", "#9A7AA0", "#886F90", "#7A5980", "#695070", "#5A4060"] -const GREENS = ["#77DD77", "#8FBC8F", "#556B2F", "#6B8E23", "#4F7942", "#404627", "#2E5E21"] diff --git a/_assets/scripts/debris/constants.jl b/_assets/scripts/debris/constants.jl deleted file mode 100644 index 67d73ad..0000000 --- a/_assets/scripts/debris/constants.jl +++ /dev/null @@ -1,54 +0,0 @@ -# Set directory hierarchy - -root = "." -code = root * "/code/" -made = root * "/objs/" -data = root * "/data/" - -using CSV -using DataFrames -using Colors -using Combinatorics -using HTTP -using PlotlyJS - - -# Define the state abbreviations and their corresponding electoral votes - -const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const VOTES = [6, 10, 11, 16, 15, 19, 16] -const TIED = 269 -const FLAGRED = "#B22234" -const FLAGBLUE = "#3C3B6E" -const PURPLE = "#772F51" -const GREENBAR = "#2F774E" - -# Initialize an object to hold the collected combinations -combos = Dict() - -# To collect combinations for n = 1:7 -for n in 1:7 - # Generate combinations of length n - combinations_n = combinations(STATES, n) - # Collect combinations and store them in the dictionary - combos[n] = collect(combinations_n) -end - -# Now `collected_combinations` holds all the collected combinations for n = 1:7 -join(STATES,", ") -# gives: "NV, WI, AZ, GA, MI, PA, NC" - -# votes in Electoral College -const COLLEGE = 538 -const VICTORY = 270 -const TIE = 269 - -# biden won 6 of the 7 swing states -# trump won NC -const BLUE = 226 -const RED = 219 - -# Create a color scale with discrete colors for each value - -const PURPLES = ["#CFA2DB", "#B583A4", "#9A7AA0", "#886F90", "#7A5980", "#695070", "#5A4060"] -const GREENS = ["#77DD77", "#8FBC8F", "#556B2F", "#6B8E23", "#4F7942", "#404627", "#2E5E21"] diff --git a/_assets/scripts/debris/converter b/_assets/scripts/debris/converter deleted file mode 100755 index c12af98..0000000 Binary files a/_assets/scripts/debris/converter and /dev/null differ diff --git a/_assets/scripts/debris/converter.go b/_assets/scripts/debris/converter.go deleted file mode 100644 index 1643ce1..0000000 --- a/_assets/scripts/debris/converter.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - inputLines := []string{ - "bl2,mar,AZ,42,49,788", - "bi2,mar,PA,40,46,1305", - "bi2,mar,MI,42,45,1218", - "bl2,mar,PA,45,45,807", - "bl2,mar,GA,42,49,788", - "bl2,mar,NC,43,49,699", - "bl2,mar,MI,44,46,447", - "bl2,mar,AZ,42,49,788", - "bl2,mar,WI,46,45,697", - "bl2,mar,NV,43,49,699", - "cb2,mar,GA,48,51,1133", - "cn2,mar,PA,46,46,1132", - "cn2,mar,MI,42,50,1097", - "ec2,mar,PA,43,45,1000", - "ec2,mar,GA,42,46,1000", - "ec2,mar,MI,44,45,1000", - "fm2,mar,PA,48,38,431", - "fo2,mar,PA,45,49,1121", - "hi2,mar,NC,38,44,1016", - "ma2,mar,NC,48,51,1295", - "mi2,mar,NC,44,47,626", - "qi2,mar,MI,45,48,1487", - "sp2,mar,MI,44,48,709", - "wa2,mar,PA,45,50,736", - "ws2,mar,PA,44,47,600", - "ws2,mar,GA,43,44,600", - "ws2,mar,NC,43,49,600", - "ws2,mar,MI,45,48,600", - "ws2,mar,AZ,44,47,600", - "ws2,mar,WI,46,46,600", - "ws2,mar,NV,44,48,600", - } - - for _, line := range inputLines { - parts := strings.Split(line, ",") - if len(parts) == 6 { - pollster, month, state, bidenSupport, trumpSupport, sampleSize := parts[0], parts[1], parts[2], parts[3], parts[4], parts[5] - fmt.Printf("add_poll!(%s, %s, %s, %s, %s, %s)\n", month, state, pollster, bidenSupport, trumpSupport, sampleSize) - } - } -} \ No newline at end of file diff --git a/_assets/scripts/debris/count_bayes.jl b/_assets/scripts/debris/count_bayes.jl deleted file mode 100644 index 2aec956..0000000 --- a/_assets/scripts/debris/count_bayes.jl +++ /dev/null @@ -1,66 +0,0 @@ -using BSON: @load -using CSV -using DataFrames -include("election_priors.jl") -@enum Month mar apr may jun jul aug sep oct nov -@enum State PA GA NC MI AZ WI NV -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -@load "../objs/apr_polls.bson" months - - -function process_polls(polls::Vector{Poll}) - result = Int64.(collect(collect([(p.biden_support, p.sample_size) for p in polls])[1])) - return [Int64(floor(result[1] / 100 * result[2])), result[2]] -end - - -processed_polls = Dict(state => Dict(pollster => process_polls(polls) for (pollster, polls) in pollsters) for (state, pollsters) in march) - - -processed_polls_totals = Dict(state => Dict( - "num_wins" => sum(first(values(polls)) for polls in values(pollsters)), - "num_votes" => sum(last(values(polls)) for polls in values(pollsters)) -) for (state, pollsters) in processed_polls) - - diff --git a/_assets/scripts/debris/election_priors.jl b/_assets/scripts/debris/election_priors.jl deleted file mode 100644 index 9f656eb..0000000 --- a/_assets/scripts/debris/election_priors.jl +++ /dev/null @@ -1,11 +0,0 @@ -using CSV -using DataFrames -const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] - -votes = CSV.read("../objs/2020vote.csv", DataFrame) -election_priors = filter(row -> row.st in STATES, votes) -election_priors = election_priors[:,[1,2,3]] -election_priors.tot = election_priors.biden_pop .+ election_priors.trump_pop -election_priors = election_priors[:,[:st,:biden_pop,:tot]] -rename!(election_priors,["st","num_wins","num_votes"]) -# CSV.write("../objs/election_priors",election_priors) \ No newline at end of file diff --git a/_assets/scripts/debris/fetch_gist.jl b/_assets/scripts/debris/fetch_gist.jl deleted file mode 100644 index e50e980..0000000 --- a/_assets/scripts/debris/fetch_gist.jl +++ /dev/null @@ -1,14 +0,0 @@ -using CSV -using DataFrames -using HTTP - -# URL of the raw CSV file from the GitHub Gist -gist_url = "https://gist.githubusercontent.com/technocrat/18810a6c1c3d6d2c443876f06df0ad28/raw/a4b7ebf2d6429c5224417a133caa61dedfaa433e/2020vote.csv" - -# Fetch the CSV data from the Gist URL -csv_data = HTTP.get(gist_url).body - -# Read the CSV data into a DataFrame -base = CSV.read(IOBuffer(csv_data), DataFrame) - -# Now `df` contains the data from the CSV file \ No newline at end of file diff --git a/_assets/scripts/debris/first_posterior.jl b/_assets/scripts/debris/first_posterior.jl deleted file mode 100644 index e82275f..0000000 --- a/_assets/scripts/debris/first_posterior.jl +++ /dev/null @@ -1,46 +0,0 @@ -include("first_posterior_forepart.jl") -# Set the number of votes and wins - last_election = CSV.read("../objs/election_priors.csv", DataFrame) - -#------------------------------------------------------------------ -# row indexed to state in alpha order; repeat for each of 1:7 -#------------------------------------------------------------------ -ST = last_election[4, :st] -num_wins = last_election[4, :num_wins] -num_votes = last_election[4, :num_votes] -margins = CSV.read("../objs/margins.csv", DataFrame) -margin = first(margins[margins.st .== ST, :pct]) - -chain = sample(election_model(num_votes, num_wins), sampler, - num_samples, init_params=init_params) - -p_intv = quantile(chain[:p], [0.025, 0.975]) -p_mean = summarystats(chain)[1, :mean] -p_mcse = summarystats(chain)[1, :mcse] -p_rhat = summarystats(chain)[1, :rhat] -p_df = DataFrame(median = median(chain[:p]), - mean = mean(chain[:p]), - mode = mode(chain[:p]), - q025 = p_intv[1], - q975 = p_intv[2], - mcse = summarystats(chain)[1, :mcse], - rhat = summarystats(chain)[1, :rhat]) - -p_samples = chain[:p] -p_vec = vec(p_samples) -kde_result = kde(p_vec) - -include("first_posterior_aftpart.jl") - -posterior_interval = p_intv -fig = draw_density() -deep = deepcopy(chain) - -@save ("../objs/$ST" * "_2020_p_sample.bson") deep -save(("../img/models/$ST" * "_2020.png"), fig) - -out = Vector(p_df[1,:]) -out = round.(out,digits = 4) -p_df[1,:] = out -pretty_table(p_df,backend=Val(:html), show_subheader = false) - diff --git a/_assets/scripts/debris/first_posterior_aftpart.jl b/_assets/scripts/debris/first_posterior_aftpart.jl deleted file mode 100644 index 0b4995c..0000000 --- a/_assets/scripts/debris/first_posterior_aftpart.jl +++ /dev/null @@ -1,65 +0,0 @@ -""" - draw_density() - -Draw a density plot of the parameter `p` with a shaded credible interval. - -# Returns -- `fig`: A `Figure` object containing the density plot. - -# Description -This function creates a density plot of the parameter `p` using the `kde_result` and `p_vec` variables, -which are assumed to be available in the current scope. The plot includes a shaded region representing -the credible interval specified by `posterior_interval`. - -The density curve is plotted in green (`#a3b35c`) with a stroke width of 8. The shaded credible interval -is filled in orange (`#e1aa6e`). - -The x-axis label is set to "p", the y-axis label is set to "Density", and the plot title is set to -"Density Plot of p for $ST", where `$ST` is a string variable assumed to be available in the current scope. - -The x-axis limits are set to the extrema of `p_vec`, and the y-axis limits are set to start from 0. - -A legend is added to the plot using `axislegend(ax)`. - -# Example -```julia -# Assume kde_result, p_vec, posterior_interval, and ST are available in the current scope -fig = draw_density() -""" -function draw_density() - # Create a new figure with specified resolution - fig = Figure(size = (600, 400)) - - # Add an axis to the figure - ax = Axis(fig[1, 1], xlabel = "Likelihood of Harris win", ylabel = "Number of draws", title = "Model: Harris results in $ST from 2020 election before polling") - - # Plot the full density curve - lines!(ax, kde_result.x, kde_result.density, color = "#a3b35c", linewidth = 3, strokewidth = 4, strokecolor = GREENBAR, label = "Draws") - - # Find the indices corresponding to the posterior interval - indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) - - # Extract the x and y values within the posterior interval - x_region = kde_result.x[indices] - y_region = kde_result.density[indices] - - # Fill the specific area under the curve - band!(ax, x_region, fill(0, length(x_region)), y_region, color = (LORANGE), label = "Credible Interval") - - # Find the y-value corresponding to the specified x-value - y_value = kde_result.density[argmin(abs.(kde_result.x .- margin))] - - # Add a vertical line at the specified x-value from 0 to the y-value - vlines!(ax, [margin], [0, y_value], color = FLAGBLUE, linestyle = :dash, linewidth = 4, label = "2020 Actual") - - # Add a legend to the plot - axislegend(ax) - - # Adjust the plot limits to fit the density line - Makie.xlims!(ax, extrema(p_vec)) - Makie.ylims!(ax, 0, nothing) - - # Display the figure - fig -end -#------------------------------------------------------------------ diff --git a/_assets/scripts/debris/first_posterior_forepart.jl b/_assets/scripts/debris/first_posterior_forepart.jl deleted file mode 100644 index db0b031..0000000 --- a/_assets/scripts/debris/first_posterior_forepart.jl +++ /dev/null @@ -1,46 +0,0 @@ -using BSON: @load, @save -using CSV -using DataFrames -using Format -using GLMakie -using KernelDensity -using LinearAlgebra -using MCMCChains -using Missings -using PrettyTables -using Printf -using Serialization -using Statistics -using Turing -#------------------------------------------------------------------ -const FLAGRED = "rgb(178, 34, 52)" -const FLAGBLUE = "rgb( 60, 59, 110)" -const PURPLE = "rgb(119, 47, 81)" -const GREENBAR = "rgb( 47, 119, 78)" -const LORANGE = "rgb(225, 170, 110)" -#------------------------------------------------------------------ - -# Define the model -@model function election_model(num_votes::Int64, num_wins::Int64) - # Prior: Beta(2, 2) equivalent to a close race going in - p ~ Beta(2,2) - # Likelihood - num_wins ~ Binomial(num_votes, p) -end - -sampler = NUTS(0.65) -num_samples = 10000 -num_chains = 4 - - -init_params = [Dict(:p => 0.5)] - -Month_names = Dict( - "mar" => "March", - "apr" => "April", - "may" => "May", - "jun" => "June", - "aug" => "August", - "sep" => "September", - "oct" => "October") -#------------------------------------------------------------------ diff --git a/_assets/scripts/debris/func.jl b/_assets/scripts/debris/func.jl deleted file mode 100644 index 731b400..0000000 --- a/_assets/scripts/debris/func.jl +++ /dev/null @@ -1,56 +0,0 @@ -""" - without_states(lost::Vector{String}) -> DataFrame - -Find and return rows from the `outcomes` DataFrame where the `combo` column does not contain any of the states specified in the `lost` vector and where the result is "Harris". - -# Arguments -- `lost::Vector{String}`: A vector of strings where each string represents a state to be excluded from the `combo` column. - -# Returns -- `DataFrame`: A DataFrame containing rows that meet the criteria. - -# Examples -```julia -without_states(["PA", "NC"]) -header = ["Scenario", "Electoral Votes", "Harris Total", "Trump Total", "Result"] -pretty_table(without_states["PA"]; backend = Val(:html), header = header, standalone = false) -""" -function without_states(lost::Vector{String}) - filter(row -> all(!occursin(state, row.combo) for state in lost) && row.result == "Harris", outcomes) -end -#------------------------------------------------------------------ -""" - metahelp() - -shows MetaFrame structure and give example - -mutable struct MetaFrame - meta::Dict{Symbol, Any} - data::DataFrame -end - -# Example usage -df = DataFrame(name=["John", "Jane"], age=[28, 34]) -meta_info = Dict(:source => "Survey Data", :year => 2021) - -df = MetaFrame(meta_info, df) - -meta_info = Dict( - :source => "Census Bureau, Current Population Survey, November 2022", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022", - :url => "https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-586.html", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022") -""" -function metahelp() - println("Display with ?metahelp") -end -#------------------------------------------------------------------ - -function radix(df::DataFrame) - for col in names(df) - if eltype(df[:, col]) == Int64 - df[:, col] = format.(df[:, col], commas=true) - end - end -end - diff --git a/_assets/scripts/debris/gaming.jl b/_assets/scripts/debris/gaming.jl deleted file mode 100644 index 6be3ad9..0000000 --- a/_assets/scripts/debris/gaming.jl +++ /dev/null @@ -1,52 +0,0 @@ -# draft calculator for allocation of campaign effort -using Combinatorics - -function optimal_betting_strategy(target_tokens, wagers) - # Initialize the dynamic programming table - dp = zeros(Int, target_tokens + 1) - dp[1] = 1 - - # Initialize the combinations array - combinations = [[] for _ in 0:target_tokens] - - # Iterate over each wager - for wager in wagers - new_dp = zeros(Int, target_tokens + 1) - - # Iterate over the possible number of tokens - for tokens in 0:target_tokens - if dp[tokens + 1] > 0 - # Update the dynamic programming table based on the wager - if tokens + wager[1] <= target_tokens - new_dp[tokens + wager[1] + 1] += dp[tokens + 1] * wager[2] - push!(combinations[tokens + wager[1] + 1], [(wager[3], wager[2])]) - end - if tokens - wager[1] >= 0 - new_dp[tokens - wager[1] + 1] += dp[tokens + 1] * (100 - wager[2]) - push!(combinations[tokens - wager[1] + 1], [(wager[3], 100 - wager[2])]) - end - end - end - - dp = new_dp - end - - return combinations -end - -# Define the wagers (using integer probabilities and wager names) -wagers = [(1, 50, "MN"), (1, 50, "NC"), (1, 50, "ME"), (2, 50, "NV")] - -# Calculate the optimal betting strategy -target_tokens = 26 -combos = optimal_betting_strategy(target_tokens, wagers) - -# Print all combinations of wagers that can reach the target -println("Combinations of wagers that can reach the target:") -for combo in combos[end] - println("Combination:") - for (wager, probability) in combo - println(" Wager: $wager, Probability: $(probability)%") - end - println() -end \ No newline at end of file diff --git a/_assets/scripts/debris/generate_results.jl b/_assets/scripts/debris/generate_results.jl deleted file mode 100644 index 8823354..0000000 --- a/_assets/scripts/debris/generate_results.jl +++ /dev/null @@ -1,27 +0,0 @@ -# Parent file to run all scripts which may generate -# some output that you want to display on the website. -# this can be used as a tester to check that all the code -# on your website runs properly. - -dir = @__DIR__ - -""" - genplain(s) - -Small helper function to run some code and redirect the output (stdout) to a file. -""" -function genplain(s::String) - open(joinpath(dir, "output", "$(splitext(s)[1]).txt"), "w") do outf - redirect_stdout(outf) do - include(joinpath(dir, s)) - end - end -end - -# output - -genplain("script1.jl") - -# plots - -include("script2.jl") diff --git a/_assets/scripts/debris/gentab.jl b/_assets/scripts/debris/gentab.jl deleted file mode 100644 index 3848322..0000000 --- a/_assets/scripts/debris/gentab.jl +++ /dev/null @@ -1,12 +0,0 @@ -using CSV -using DataFrames -using PrettyTables - -header = ["Scenario", "Electoral Votes", "Biden Total", "Trump Total", "Result"] -csv_path = "/Users/ro/projects/SwingWatch/_src/objs/outcome.csv" -df = CSV.read(csv_path, DataFrame) - -open("_assets/tab1/pa.txt", "w") do io - pretty_table(io, df; backend = Val(:html), header = header, standalone = false) -end - diff --git a/_assets/scripts/debris/gmt.history b/_assets/scripts/debris/gmt.history deleted file mode 100644 index 7b4bbde..0000000 --- a/_assets/scripts/debris/gmt.history +++ /dev/null @@ -1,8 +0,0 @@ -# GMT 6 Session common arguments shelf -BEGIN GMT 6.6.0 -B afWSen -J X -JX X15c/0 -R 0/1/0/1 -@L 1 -END diff --git a/_assets/scripts/debris/hypo.jl b/_assets/scripts/debris/hypo.jl deleted file mode 100644 index 2b865f0..0000000 --- a/_assets/scripts/debris/hypo.jl +++ /dev/null @@ -1,78 +0,0 @@ -""" -To illustrate the limitations of presidential preference polling it is possible to simulate accuracy of polling conducted for the Georgia election in 2020. It is assumed that one or more pollsters independently sample after polls close election night but before official results are released. The pollsters each ask three questions: - -1. Did you vote? -2. Did you vote for one of Donald Trump or Joe Harris? -3. Which one? - -until some preset number of replies to the third question are obtained. - -The objective is to determine - -1. The minimum sample size needed to have a 97.5% probablility of identifying a vote spread less than or equal to 246775, or 0.5% of the total cast for Trump and Harris, which is the threshhold for a mandatory recount. -2. The probability that the mean spread is positive (a Harris win) at the 97.5% confidence interval, which is 39 chances in 40 of being correct. -3. The probability that all polls will show a positive spread at the 97.5% confidence interval -4. The probability that at least one poll will show a negative spread (Trump win) at the 97.5% confidence interval -""" - -using Distributions -using Plots -using Statistics - -z = 1.96 # z-score for 97.5% confidence level -p = 0.5 # assumed population proportion -margin_of_error = 0.005 # 0.5% margin of error - -# Solve for the sample size -n = ceil(Int, (z^2 * p * (1 - p)) / margin_of_error^2) - -println("Minimum sample size needed: $n") - -biden = 2473633 -trump = 2461854 -total_votes = biden + trump -spread = biden - trump -recount = 246775 -actual_spread = (biden - trump) / total_votes - -sample_size = 1000 -repetitions = 10 - -predicted_spreads = zeros(repetitions) - -for i in 1:repetitions - sample = rand(1:total_votes, sample_size) - sample_biden = count(sample .<= biden) - sample_trump = sample_size - sample_biden - - predicted_spread = (sample_biden - sample_trump) / sample_size - predicted_spreads[i] = predicted_spread -end - -mean_predicted_spread = mean(predicted_spreads) - -result = Int64.(floor.(total_votes .* predicted_spreads)) -mean(result) - -mean_spread = mean(predicted_spreads) -std_spread = std(predicted_spreads) - -# Calculate the z-score for the mean spread -z_score = mean_spread / (std_spread / sqrt(repetitions)) - -# Calculate the probability using the cumulative distribution function (cdf) -prob_positive_mean = 1 - cdf(Normal(), z_score) - -println("Probability that the mean spread is positive: $(round(prob_positive_mean, digits=4))") - -# Calculate the z-score for a spread of 0 -z_score = 0 / std_spread - -# Calculate the probability of a single poll showing a positive spread -prob_positive_poll = 1 - cdf(Normal(), z_score) - -# Calculate the probability of all polls showing a positive spread -prob_all_positive = prob_positive_poll^repetitions - -println("Probability that all polls will show a positive spread: $(round(prob_all_positive, digits=4))") - diff --git a/_assets/scripts/debris/insert_apr.jl b/_assets/scripts/debris/insert_apr.jl deleted file mode 100644 index eaf89d5..0000000 --- a/_assets/scripts/debris/insert_apr.jl +++ /dev/null @@ -1,80 +0,0 @@ -using BSON: @save, @load -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -const DESIGN_ERROR = 0.012 - -@enum Month mar apr may jun jul aug sep oct nov - -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end -# -@load "../objs/mar_Polls.bson" months - -months[apr][AZ][bl2] = [Poll(43,49, 801)] -months[apr][AZ][ec2] = [Poll(44,48,1000)] -months[apr][GA][bl2] = [Poll(45,47, 802)] -months[apr][GA][ec2] = [Poll(44,47,1000)] -months[apr][GA][fo2] = [Poll(45,51,1128)] -months[apr][MI][bi2] = [Poll(43,51, 708)] -months[apr][MI][ec2] = [Poll(44,45,1000)] -months[apr][MI][fo2] = [Poll(46,49,1106)] -months[apr][MI][mr2] = [Poll(46,42, 600)] -months[apr][NC][ec2] = [Poll(42,47,1000)] -months[apr][NC][bl2] = [Poll(41,51, 703)] -months[apr][NC][ma2] = [Poll(43,49, 645)] -months[apr][NC][qi2] = [Poll(46,48,1401)] -months[apr][NV][ec2] = [Poll(44,45,1000)] -months[apr][PA][bi2] = [Poll(46,47, 803)] -months[apr][PA][ec2] = [Poll(45,47,1000)] -months[apr][WI][bl2] = [Poll(44,48, 703)] -months[apr][WI][ec2] = [Poll(45,47,1000)] -@save "../objs/apr_polls.bson" months - -#@load "../objs/apr_polls.bson" months diff --git a/_assets/scripts/debris/insert_aug1.jl b/_assets/scripts/debris/insert_aug1.jl deleted file mode 100644 index a9808d0..0000000 --- a/_assets/scripts/debris/insert_aug1.jl +++ /dev/null @@ -1,98 +0,0 @@ -using BSON: @save, @load -using CSV -using DataFrames -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -@enum Month mar apr may jul jul2 aug1 aug2 sep1 sep2 oct1 sep2 fin - -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cj - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ny2 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int64 -end - - -@load "../objs/jul2_polls.bson" months - -months[aug1][AZ][ny2] = [Poll(49,45,677)] -months[aug1][AZ][tr] = [Poll(47,48,1000)] -months[aug1][GA][ny2] = [Poll(44,51,661)] -months[aug1][MI][tr] = [Poll(49,47,800)] -months[aug1][NC][cj] = [Poll(44,47,600)] -months[aug1][NV][tr] = [Poll(45,49,1000)] -months[aug1][NV][ny2] = [Poll(42,45,677)] -months[aug1][PA][ec2] = [Poll(47,47,1000)] -months[aug1][PA][tr] = [Poll(44,46,1000)] -months[aug1][PA][qi2] = [Poll(48,45,1738)] -months[aug1][WI][tr] = [Poll(48,49,800)] - - - - -# needs to be done manually rather than with include() -@save "../objs/aug1_polls.bson" months - - diff --git a/_assets/scripts/debris/insert_aug2.jl b/_assets/scripts/debris/insert_aug2.jl deleted file mode 100644 index f5d3a2e..0000000 --- a/_assets/scripts/debris/insert_aug2.jl +++ /dev/null @@ -1,112 +0,0 @@ -using BSON: @save, @load -using CSV -using DataFrames -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -@enum Month mar apr may jul jul2 aug1 aug2 sep oct nov last - -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cj - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ny2 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - harris_support::Float64 - trump_support::Float64 - sample_size::Int64 -end - - -@load "../objs/aug1_polls.bson" months - -months[aug2][AZ][bl2] = [Poll(48,48,805)] -months[aug2][AZ][ec2] = [Poll(47,50,720)] -months[aug2][AZ][fo2] = [Poll(50,49,1014)] -months[aug2][AZ][ia] = [Poll(48,49,800)] -months[aug2][AZ][cn2] = [Poll(44,49,800)] -months[aug2][GA][bl2] = [Poll(49,47,801)] -months[aug2][GA][ec2] = [Poll(49,48,800)] -months[aug2][GA][fo2] = [Poll(49,49,1014)] -months[aug2][GA][ia] = [Poll(48,48,800)] -months[aug2][MI][bl2] = [Poll(49,46,702)] -months[aug2][MI][ec2] = [Poll(50,47,800)] -months[aug2][MI][ep] = [Poll(44,44,600)] -months[aug2][MI][tr] = [Poll(47,47,1089)] -months[aug2][NC][bl2] = [Poll(50,45,803)] -months[aug2][NC][ec2] = [Poll(48,49,775)] -months[aug2][NC][eu] = [Poll(47,48,720)] -months[aug2][NC][fo2] = [Poll(49,50,999)] -months[aug2][NC][ia] = [Poll(48,49,800)] -months[aug2][NV][bl2] = [Poll(49,45,700)] -months[aug2][NV][ec2] = [Poll(49,48,1168)] -months[aug2][NV][fo2] = [Poll(50,48,1026)] -months[aug2][NV][ia] = [Poll(47,48,800)] -months[aug2][PA][bl2] = [Poll(51,47,803)] -months[aug2][PA][ec2] = [Poll(48,48,950)] -months[aug2][PA][tr] = [Poll(45,47,1087)] -months[aug2][WI][tr] = [Poll(46,47,1083)] - - - -# needs to be done manually rather than with include() -#@save "../objs/aug2_polls.bson" months # comes out empty - - diff --git a/_assets/scripts/debris/insert_hypo.jl b/_assets/scripts/debris/insert_hypo.jl deleted file mode 100644 index 3a55ef6..0000000 --- a/_assets/scripts/debris/insert_hypo.jl +++ /dev/null @@ -1,113 +0,0 @@ -using BSON: @save, @load -using CSV -using DataFrames -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -@enum Month mar apr may jul jul2 aug1 hyp sep oct nov - -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cj - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ny2 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - harris_support::Float64 - trump_support::Float64 - sample_size::Int64 -end - - -@load "../objs/aug2_polls.bson" months - -months[hyp][AZ][bl2] = [Poll(60,40,805)] -months[hyp][AZ][ec2] = [Poll(60,40,720)] -months[hyp][AZ][fo2] = [Poll(60,40,1014)] -months[hyp][AZ][ia] = [Poll(60,40,800)] -months[hyp][AZ][cn2] = [Poll(60,40,800)] - -months[hyp][GA][bl2] = [Poll(54,46,801)] -months[hyp][GA][ec2] = [Poll(54,36,800)] -months[hyp][GA][fo2] = [Poll(44,36,1014)] -months[hyp][GA][ia] = [Poll(53,47,800)] -months[hyp][MI][bl2] = [Poll(54,46,702)] -months[hyp][MI][ec2] = [Poll(55,45,800)] -months[hyp][MI][ep] = [Poll(49,30,600)] -months[hyp][MI][tr] = [Poll(52,48,1089)] -months[hyp][NC][bl2] = [Poll(55,45,803)] -months[hyp][NC][ec2] = [Poll(53,47,775)] -months[hyp][NC][eu] = [Poll(52,48,720)] -months[hyp][NC][fo2] = [Poll(54,46,999)] -months[hyp][NC][ia] = [Poll(53,47,800)] -months[hyp][NV][bl2] = [Poll(54,46,700)] -months[hyp][NV][ec2] = [Poll(44,46,1168)] -months[hyp][NV][fo2] = [Poll(54,46,1026)] -months[hyp][NV][ia] = [Poll(53,48,800)] -months[hyp][PA][bl2] = [Poll(56,44,803)] -months[hyp][PA][ec2] = [Poll(53,47,950)] -months[hyp][PA][tr] = [Poll(50,50,1087)] -months[hyp][WI][tr] = [Poll(51,49,1083)] - - - -# needs to be done manually rather than with include() -#@save "../objs/hyp_polls.bson" months # comes out empty - - diff --git a/_assets/scripts/debris/insert_jul.jl b/_assets/scripts/debris/insert_jul.jl deleted file mode 100644 index ec6d9a8..0000000 --- a/_assets/scripts/debris/insert_jul.jl +++ /dev/null @@ -1,113 +0,0 @@ -using BSON: @save, @load -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -@enum Month mar apr may jul jul2 aug sep oct nov - -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end - - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int64 -end - - -@load "../objs/jun_polls.bson" months - -months[jul][AZ][bl2] = [Poll(45,48,781)] -months[jul][AZ][ec2] = [Poll(40,50,1000)] -months[jul][AZ][ia] = [Poll(44,49,800)] -months[jul][AZ][pp] = [Poll(43,51,596)] -months[jul][AZ][yg] = [Poll(37,44,900)] -months[jul][GA][bl2] = [Poll(41,43,790)] -months[jul][GA][ec2] = [Poll(48,41,1000)] -months[jul][GA][ia] = [Poll(42,48,800)] -months[jul][GA][yg] = [Poll(40,44,1000)] -months[jul][MI][bl2] = [Poll(45,39,694)] -months[jul][MI][ec2] = [Poll(42,45,1000)] -months[jul][MI][ep] = [Poll(36,42,600)] -months[jul][MI][tr] = [Poll(43,45,1059)] -months[jul][MI][yg] = [Poll(40,42,1000)] -months[jul][NC][bl2] = [Poll(42,40,696)] -months[jul][NC][ec2] = [Poll(41,48,1000)] -months[jul][NC][yg] = [Poll(40,44,1000)] -months[jul][NV][bl2] = [Poll(39,45,452)] -months[jul][NV][ec2] = [Poll(40,56,1000)] -months[jul][NV][ia] = [Poll(42,49,800)] -months[jul][NV][yg] = [Poll(42,46,800)] -months[jul][PA][bl2] = [Poll(44,51,794)] -months[jul][PA][ia] = [Poll(45,49,800)] -months[jul][PA][yg] = [Poll(40,43,1000)] -months[jul][PA][ec2] = [Poll(43,48,1000)] -months[jul][PA][ny] = [Poll(43,47,1000)] -months[jul][WI][bl2] = [Poll(47,44,695)] -months[jul][WI][ec2] = [Poll(43,48,1000)] -months[jul][WI][ia] = [Poll(47,47,546)] -months[jul][WI][ns] = [Poll(44,46,600)] -months[jul][WI][yg] = [Poll(39,43,900)] - - -# needs to be done manually rather than with include() -#@save "../objs/jul_polls.bson" months - - diff --git a/_assets/scripts/debris/insert_jul2.jl b/_assets/scripts/debris/insert_jul2.jl deleted file mode 100644 index 3205c6e..0000000 --- a/_assets/scripts/debris/insert_jul2.jl +++ /dev/null @@ -1,98 +0,0 @@ -using BSON: @save, @load -using CSV -using DataFrames -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -@enum Month mar apr may jul jul2 aug1 aug2 sep1 sep2 oct1 oct2 nov fin - -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int64 -end - - -@load "../objs/jul_polls.bson" months - -months[jul2][AZ][bl2] = [Poll(48,47,804)] -months[jul2][AZ][ec2] = [Poll(44,49,800)] -months[jul2][GA][bl2] = [Poll(47,47,799)] -months[jul2][GA][ec2] = [Poll(46,48,800)] -months[jul2][MI][bl2] = [Poll(53,42,706)] -months[jul2][MI][ec2] = [Poll(45,46,800)] -months[jul2][MI][fo2] = [Poll(43,45,1012)] -months[jul2][NC][bl2] = [Poll(46,48,706)] -months[jul2][NV][bl2] = [Poll(47,45,454)] -months[jul2][PA][bl2] = [Poll(46,50,804)] -months[jul2][PA][fo2] = [Poll(45,43,1034)] -months[jul2][PA][am] = [Poll(45,47,600)] -months[jul2][PA][ec2] = [Poll(46,48,850)] -months[jul2][WI][bl2] = [Poll(49,47,700)] -months[jul2][WI][ec2] = [Poll(47,47,854)] -months[jul2][WI][fo2] = [Poll(46,46,1046)] - -# needs to be done manually rather than with include() -@save "../objs/jul2_polls.bson" months - - diff --git a/_assets/scripts/debris/insert_jul_pre.jl b/_assets/scripts/debris/insert_jul_pre.jl deleted file mode 100644 index c87ea2d..0000000 --- a/_assets/scripts/debris/insert_jul_pre.jl +++ /dev/null @@ -1,112 +0,0 @@ -using BSON: @save, @load -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -@enum Month mar apr may jun jul jul2 aug sep oct nov - -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int64 -end - - -@load "../objs/jun_polls.bson" months - -months[jul][AZ][bl2] = [Poll(45,48,781)] -months[jul][AZ][ec2] = [Poll(40,50,1000)] -months[jul][AZ][ia] = [Poll(44,49,800)] -months[jul][AZ][pp] = [Poll(43,51,596)] -months[jul][AZ][yg] = [Poll(37,44,900)] -months[jul][GA][bl2] = [Poll(41,43,790)] -months[jul][GA][ec2] = [Poll(48,41,1000)] -months[jul][GA][ia] = [Poll(42,48,800)] -months[jul][GA][yg] = [Poll(40,44,1000)] -months[jul][MI][bl3] = [Poll(45,39,694)] -months[jul][MI][ec3] = [Poll(42,45,1000)] -months[jul][MI][ep] = [Poll(36,42,600)] -months[jul][MI][tr] = [Poll(43,45,1059)] -months[jul][MI][yg] = [Poll(40,42,1000)] -months[jul][NC][bl3] = [Poll(42,40,696)] -months[jul][NC][ec3] = [Poll(41,48,1000)] -months[jul][NC][yg] = [Poll(40,44,1000)] -months[jul][NV][bl3] = [Poll(39,45,452)] -months[jul][NV][ec3] = [Poll(40,56,1000)] -months[jul][NV][ia] = [Poll(42,49,800)] -months[jul][NV][yg] = [Poll(42,46,800)] -months[jul][PA][bl2] = [Poll(44,51,794)] -months[jul][PA][ia] = [Poll(45,49,800)] -months[jul][PA][yg] = [Poll(40,43,1000)] -months[jul][PA][ec2] = [Poll(43,48,1000)] -months[jul][PA][ny] = [Poll(43,47,1000)] -months[jul][WI][bl2] = [Poll(47,44,695)] -months[jul][WI][ec2] = [Poll(43,48,1000)] -months[jul][WI][ia] = [Poll(47,47,546)] -months[jul][WI][ns] = [Poll(44,46,600)] -months[jul][WI][yg] = [Poll(39,43,900)] - - -# needs to be done manually rather than with include() -@save "../objs/jul_polls.bson" months - - diff --git a/_assets/scripts/debris/insert_jun.jl b/_assets/scripts/debris/insert_jun.jl deleted file mode 100644 index 3a5962f..0000000 --- a/_assets/scripts/debris/insert_jun.jl +++ /dev/null @@ -1,114 +0,0 @@ -using BSON: @save, @load -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -# const DESIGN_ERROR = . - -@enum Month mar apr may jul jul aug sep oct nov - -@enum Pollster begin - ag - aj - am - bi - bi - bl - bl - cb - cb - cn - cn - ea - ec - ec - ep - eu - fm - fm - fo - fo - hi - hi - hp - ia - ma - ma - mi - mi - mq - mr - mr - ns - pp - ny - qi - qi - rr - si - si - sp - sp - su - su - tr - wa - wa - ws - wsl - wss - yg -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float - trump_support::Float - sample_size::Int -end - - -@load "../objs/jun_polls.bson" months - -months[jul][AZ][bl] = [Poll(45,48,781)] -months[jul][AZ][ec] = [Poll(40,50,1000)] -months[jul][AZ][ia] = [Poll(44,49,800)] -months[jul][AZ][pp] = [Poll(43,51,596)] -months[jul][AZ][yg] = [Poll(37,44,900)] -months[jul][GA][bl] = [Poll(41,43,790)] -months[jul][GA][ec] = [Poll(48,41,1000)] -months[jul][GA][ia] = [Poll(42/,48,800)] -months[jul][GA][yg] = [Poll(40,44,1000)] -months[jul][MI][bl] = [Poll(45,39,694)] -months[jul][MI][ec] = [Poll(42,45,1000)] -months[jul][MI][ep] = [Poll(36,42,600)] -months[jul][MI][tr] = [Poll(43,45,1059)] -months[jul][MI][yg] = [Poll(40,42,1000)] -months[jul][NC][bl] = [Poll(42,40,696)] -months[jul][NC][ec] = [Poll(41,48,1000)] -months[jul][NC][yg] = [Poll(40,44,1000)] -months[jul][NV][bl] = [Poll(39,45,452)] -months[jul][NV][ec] = [Poll(40,56,1000)] -months[jul][NV][ia] = [Poll(42,49,800)] -months[jul][NV][yg] = [Poll(42,46,800)] -months[jul][PA][bl] = [Poll(44,51,794)] -months[jul][PA][ia] = [Poll(45,49,800)] -months[jul][PA][yg] = [Poll(40,43,1000)] -months[jul][PA][ec] = [Poll(43,48,1000)] -months[jul][PA][ny] = [Poll(43,47,1000)] -months[jul][WI][bl] = [Poll(47,44,695)] -months[jul][WI][ec] = [Poll(43,48,1000)] -months[jul][WI][ia] = [Poll(47,47,546)] -months[jul][WI][ns] = [Poll(44,46,600)] -months[jul][WI][yg] = [Poll(39,43,900)] - - -# needs to be done manually rather than with include() -#@save "../objs/jul_polls.bson" months - - diff --git a/_assets/scripts/debris/insert_mar.jl b/_assets/scripts/debris/insert_mar.jl deleted file mode 100644 index a0e3730..0000000 --- a/_assets/scripts/debris/insert_mar.jl +++ /dev/null @@ -1,108 +0,0 @@ -using BSON -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -const DESIGN_ERROR = 0.012 - -@enum Month mar apr may jun jul aug sep oct nov - -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end - -@enum State PA GA NC MI AZ WI NV - -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end - -const current_mon = Dict(mar => Dict(), apr => Dict(), may => Dict(), jun => Dict(), jul => Dict(), aug => Dict(), sep => Dict(), oct => Dict(), nov => Dict()) - -# Initialize the nested dictionaries for each state within each month -for month in instances(Month) - for state in instances(State) - months[month][state] = Dict{Pollster, Vector{Poll}}() - for pollster in instances(Pollster) - months[month][state][pollster] = Poll[] - end - end -end - - -months[mar][AZ][bl2] = [Poll(42, 49, 788)] -months[mar][AZ][ec2] = [Poll(44, 48, 1000)] -months[mar][AZ][ws2] = [Poll(44, 47, 600)] -months[mar][GA][bl2] = [Poll(42, 49, 788)] -months[mar][GA][cb2] = [Poll(48, 51, 1133)] -months[mar][GA][ec2] = [Poll(42, 46, 1000)] -months[mar][GA][ws2] = [Poll(43, 44, 600)] -months[mar][MI][bi2] = [Poll(42, 45, 1218)] -months[mar][MI][bl2] = [Poll(44, 46, 447)] -months[mar][MI][cn2] = [Poll(42, 50, 1097)] -months[mar][MI][ec2] = [Poll(44, 45, 1000)] -months[mar][MI][qi2] = [Poll(45, 48, 1487)] -months[mar][MI][sp2] = [Poll(44, 48, 709)] -months[mar][MI][ws2] = [Poll(45, 48, 600)] -months[mar][NC][bl2] = [Poll(43, 49, 699)] -months[mar][NC][hi2] = [Poll(38, 44, 1016)] -months[mar][NC][ma2] = [Poll(48, 51, 1295)] -months[mar][NC][mi2] = [Poll(44, 47, 626)] -months[mar][NC][ws2] = [Poll(43, 49, 600)] -months[mar][NV][bl2] = [Poll(43, 49, 699)] -months[mar][NV][ws2] = [Poll(44, 48, 600)] -months[mar][PA][bi2] = [Poll(40, 46, 1305)] -months[mar][PA][bl2] = [Poll(45, 45, 807)] -months[mar][PA][cn2] = [Poll(46, 46, 1132)] -months[mar][PA][ec2] = [Poll(43, 45, 1000)] -months[mar][PA][fm2] = [Poll(48, 38, 431)] -months[mar][PA][fo2] = [Poll(45, 49, 1121)] -months[mar][PA][wa2] = [Poll(45, 50, 736)] -months[mar][PA][ws2] = [Poll(44, 47, 600)] -months[mar][WI][ws2] = [Poll(46, 46, 600)] -months[mar][WI][bl2] = [Poll(46, 45, 697)] - - -using BSON: @save, @load - -#@save "../objs/mar_polls.bson" months - -#@load "../objs/mar_polls.bson" months \ No newline at end of file diff --git a/_assets/scripts/debris/insert_may.jl b/_assets/scripts/debris/insert_may.jl deleted file mode 100644 index d7969b6..0000000 --- a/_assets/scripts/debris/insert_may.jl +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - bi2 - bi3 - biden_support::Float64 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ea2 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp2 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - ny2 - qi2 - qi3 - si2 - si3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -@enum Month mar apr may jun jul aug sep oct nov -@enum Pollster begin -@enum State PA GA NC MI AZ WI NV -@load "../objs/apr_polls.bson" months -# -# const DESIGN_ERROR = 0.012 -# needs to be done manually rather than with include() -#@save "../objs/may_polls.bson" months -end -end -months[may][AZ][am2] = [Poll(42,48, 600)] -months[may][AZ][ec2] = [Poll(43,47,1000)] -months[may][AZ][rr2] = [Poll(42,47, 750)] -months[may][GA][aj2] = [Poll(38,43,1000)] -months[may][GA][ec2] = [Poll(41,45,1000)] -months[may][GA][qi2] = [Poll(44,49,1203)] -months[may][MI][ep2] = [Poll(45,49, 600)] -months[may][MI][ec2] = [Poll(49,51,1000)] -months[may][MI][mi2] = [Poll(45,46, 697)] -months[may][NC][ea2] = [Poll(43,48,1332)] -months[may][NV][fo2] = [Poll(45,50,1000)] -months[may][NV][ec2] = [Poll(39,41,1000)] -months[may][PA][ec2] = [Poll(45,47,1000)] -months[may][WI][ec2] = [Poll(42,44,1000)] -months[may][WI][mq2] = [Poll(50,50, 811)] -struct Poll -using BSON: @save, @load -using LinearAlgebra -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing diff --git a/_assets/scripts/debris/intake.jl b/_assets/scripts/debris/intake.jl deleted file mode 100644 index f4827b7..0000000 --- a/_assets/scripts/debris/intake.jl +++ /dev/null @@ -1,31 +0,0 @@ -# intake.jl -# preprocess source data from https://www.wikiwand.com/en/2020_United_States_presidential_election#Results_by_state 2024-03-16 - -using CSV - -votes = CSV.read("./data/votes.csv", DataFrame)[2:57,:][:,[1,2,4,5,7]] -votes[:,1] = elec -new_names = ["state","biden_pop","biden_col","trump_pop","trump_col"] -rename!(votes, new_names) - -elec = [ - "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", - "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME","ME1", "ME2","MD", - "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NE1", "NE2", "NE3", "NV", "NH", - "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", - "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY" -] - -pop = replace.(votes[:,[2,4]], "," => "") -pop[!, :biden_pop] = parse.(Int64, pop[:, :biden_pop]) -pop[!, :trump_pop] = parse.(Int64, pop[:, :trump_pop]) -col = replace.(votes[:,[3,5]], "–" => 0) -col[!, :biden_col] = parse.(Int64, col[:, :biden_col]) -col[!, :trump_col] = parse.(Int64, col[:, :trump_col]) -result = hcat(pop,col) -result = hcat(elec,result) -new_names = ["state","biden_pop","biden_col","trump_pop","trump_col"] -result.margin = result.biden_pop - result.trump_pop - -rename!(votes, new_names) -CSV.write("./objs/2020vote.csv",result) diff --git a/_assets/scripts/debris/jig b/_assets/scripts/debris/jig deleted file mode 100755 index 84fd25c..0000000 Binary files a/_assets/scripts/debris/jig and /dev/null differ diff --git a/_assets/scripts/debris/jig.awk b/_assets/scripts/debris/jig.awk deleted file mode 100755 index 2ed72ab..0000000 --- a/_assets/scripts/debris/jig.awk +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/awk -f - -{ - FS = "[]=[ ]+" - if ($1 == "master_polls.data") { - pollster = $2 - month = $3 - state = $5 - poll_data = $7 - n = split(poll_data, poll_values, ",") - if (n == 4) { - # Trim "PollData(" and ")" - poll_data = poll_values[2] "," poll_values[3] "," poll_values[4] - printf "add_poll!(%s, %s, %s, %s)\n", month, state, pollster, poll_data - } - } -} diff --git a/_assets/scripts/debris/jig.go b/_assets/scripts/debris/jig.go deleted file mode 100644 index d9ba69a..0000000 --- a/_assets/scripts/debris/jig.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "os" - "strings" -) - -func main() { - if len(os.Args) < 2 { - fmt.Println("Usage:", os.Args[0], "") - os.Exit(1) - } - - inputFile, err := os.Open(os.Args[1]) - if err != nil { - fmt.Println("Error opening input file:", err) - os.Exit(1) - } - defer inputFile.Close() - - scanner := bufio.NewScanner(inputFile) - var pollster, month, state string - for scanner.Scan() { - line := scanner.Text() - parts := strings.Split(line, "]") - if len(parts) >= 3 && strings.HasPrefix(parts[0], "master_polls.data[") { - pollsterAndMonth := strings.TrimPrefix(parts[0], "master_polls.data[") - pollsterAndMonthParts := strings.Split(pollsterAndMonth, "][") - if len(pollsterAndMonthParts) >= 2 { - pollster = pollsterAndMonthParts[0] - month = pollsterAndMonthParts[1] - state = strings.TrimPrefix(parts[1], ".data[") - } else { - fmt.Println("Invalid pollster and month format, skipping line") - continue - } - } else if strings.HasPrefix(line, "PollData(") { - pollData := strings.TrimPrefix(line, "PollData(") - pollData = strings.TrimSuffix(pollData, ")") - pollValues := strings.Split(pollData, ",") - if len(pollValues) == 3 { - fmt.Printf("add_poll!(%s, %s, %s, %s, %s, %s)\n", month, state, pollster, pollValues[0], pollValues[1], pollValues[2]) - } else { - fmt.Println("Invalid poll data format, skipping line") - } - } - } - - if err := scanner.Err(); err != nil { - fmt.Println("Error reading input file:", err) - os.Exit(1) - } -} \ No newline at end of file diff --git a/_assets/scripts/debris/jig.rs b/_assets/scripts/debris/jig.rs deleted file mode 100644 index c35bba4..0000000 --- a/_assets/scripts/debris/jig.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::env; -use std::fs::File; -use std::io::{BufRead, BufReader}; - -fn main() { - let args: Vec = env::args().collect(); - - if args.len() < 2 { - eprintln!("Usage: {} ", args[0]); - std::process::exit(1); - } - - let input_file = &args[1]; - let file = File::open(input_file).expect("Failed to open input file"); - let reader = BufReader::new(file); - - for line in reader.lines() { - let line = line.expect("Failed to read line"); - let parts: Vec<&str> = line.split(&['[', ']', '=', ' ', '(', ')'][..]).filter(|s| !s.is_empty()).collect(); - - if parts.len() >= 8 && parts[0] == "master_polls.data" { - let pollster = parts[1]; - let month = parts[2]; - let state = parts[4]; - let poll_data: Vec<&str> = parts[6].split(',').collect(); - - if poll_data.len() == 3 { - let biden_support = poll_data[0]; - let trump_support = poll_data[1]; - let sample_size = poll_data[2]; - - println!( - "add_poll!({}, {}, {}, {}, {}, {})", - month, state, pollster, biden_support, trump_support, sample_size - ); - } - } - } -} \ No newline at end of file diff --git a/_assets/scripts/debris/main.jl b/_assets/scripts/debris/main.jl deleted file mode 100644 index 99251d2..0000000 --- a/_assets/scripts/debris/main.jl +++ /dev/null @@ -1,104 +0,0 @@ -# base = CSV.read("./objs/2020vote.csv", DataFrame) - -# Fetch the CSV electoral_votes_by_state from the Gist URL -# csv_electoral_votes_by_state = HTTP.get(gist_url).body - -# Read the CSV electoral_votes_by_state into a DataFrame -base = CSV.read(IOBuffer(csv_electoral_votes_by_state), DataFrame) - - -electoral_votes_by_state = Dict( - "Arizona" => base[3,7], - "Georgia" => base[11,7], - "Wisconsin" => base[55,7], - "Michigan" => base[25,7], - "Nevada" => base[34,7], - "North Carolina" => base[39,7], - "Pennsylvania" => base[44,7] -) - -""" -vote_margin_by_state = Dict( - "Arizona" => base[3,6], - "Georgia" => base[11,6], - "Wisconsin" => base[55,6], - "Michigan" => base[25,6], - "Nevada" => base[34,6], - "North Carolina" => base[39,6], - "Pennsylvania" => base[44,6] -) -""" - -swing_col = collect(values(electoral_votes_by_state)) -# swing_pop = collect(values(vote_margin_by_state)) -# subtract the number of swing states' electoral votes -blue = sum(base.biden_col) - sum(collect(swing_col)) -red = sum(base.trump_col) - sum(collect(swing_col)) -biden_win = victory - blue -trump_win = victory - blue -target = impass -results = find_combinations(IMPASS) - -# Function to process each element of updated_results -function process_result(vec, key) - state_names = join(vec, ", ") - state_count = length(vec) - state_sum = sum(electoral_votes_by_state[state] for state in vec) - margin_sum = sum(electoral_votes_by_state[state] for state in vec) - return (key = key, st = state_names, count = state_sum, num_states = - state_count, votes = margin_sum) -end - -# Create a vector that maps indices to state names -state_mapping = collect(keys(electoral_votes_by_state)) - -# Function to replace values in a vector with corresponding state names -function replace_with_states(vec) - return [join(state_mapping[v]) for v in vec] -end - -# Create a new named tuple with updated values -updated_results = (map(replace_with_states, results[1]), - map(replace_with_states, results[2]), - map(replace_with_states, results[3])) - -""" -# Apply process_result function to each element of updated_results with separate keys -outcome_electoral_votes_by_state = vcat( - x , - process_result.(updated_results[2], "tie"), - process_result.(updated_results[3], "win") -) -""" - -# Create the outcome electoral_votes_by_state from the processed electoral_votes_by_state -outcome = DataFrame(outcome_electoral_votes_by_state) -outcome.biden = outcome.count .+ blue -outcome.trump = college .- outcome.biden -outcome.electoral = outcome.biden .+ outcome.trump -outcome.check = if(outcome.electoral .- college == 0, true) - else false - end -all(outcome.check .== true) -sort!(outcome,:count) - - - -# Function to determine the result based on the value of `biden` -function determine_result(biden_value) - if biden_value == 269 - return "tie" - elseif biden_value < 269 - return "Trump" - else - return "Harris" - end -end - -# Apply the function to each row of the electoral_votes_by_state and create the `result` column -outcome.result = determine_result.(outcome.biden) - -# Ensure the `result` column is of type String -outcome.result = string.(outcome.result) - -# The `outcome` DataFrame now has a new column `result` with the appropriate values diff --git a/_assets/scripts/debris/mar_dat.jl b/_assets/scripts/debris/mar_dat.jl deleted file mode 100644 index c27c662..0000000 --- a/_assets/scripts/debris/mar_dat.jl +++ /dev/null @@ -1,31 +0,0 @@ -add_poll!(mar, AZ, bl2, 42, 49, 788) -add_poll!(mar, PA, bi2, 40, 46, 1305) -add_poll!(mar, MI, bi2, 42, 45, 1218) -add_poll!(mar, PA, bl2, 45, 45, 807) -add_poll!(mar, GA, bl2, 42, 49, 788) -add_poll!(mar, NC, bl2, 43, 49, 699) -add_poll!(mar, MI, bl2, 44, 46, 447) -add_poll!(mar, AZ, bl2, 42, 49, 788) -add_poll!(mar, WI, bl2, 46, 45, 697) -add_poll!(mar, NV, bl2, 43, 49, 699) -add_poll!(mar, GA, cb2, 48, 51, 1133) -add_poll!(mar, PA, cn2, 46, 46, 1132) -add_poll!(mar, MI, cn2, 42, 50, 1097) -add_poll!(mar, PA, ec2, 43, 45, 1000) -add_poll!(mar, GA, ec2, 42, 46, 1000) -add_poll!(mar, MI, ec2, 44, 45, 1000) -add_poll!(mar, PA, fm2, 48, 38, 431) -add_poll!(mar, PA, fo2, 45, 49, 1121) -add_poll!(mar, NC, hi2, 38, 44, 1016) -add_poll!(mar, NC, ma2, 48, 51, 1295) -add_poll!(mar, NC, mi2, 44, 47, 626) -add_poll!(mar, MI, qi2, 45, 48, 1487) -add_poll!(mar, MI, sp2, 44, 48, 709) -add_poll!(mar, PA, wa2, 45, 50, 736) -add_poll!(mar, PA, ws2, 44, 47, 600) -add_poll!(mar, GA, ws2, 43, 44, 600) -add_poll!(mar, NC, ws2, 43, 49, 600) -add_poll!(mar, MI, ws2, 45, 48, 600) -add_poll!(mar, AZ, ws2, 44, 47, 600) -add_poll!(mar, WI, ws2, 46, 46, 600) -add_poll!(mar, NV, ws2, 44, 48, 600) diff --git a/_assets/scripts/debris/mar_poll.jl b/_assets/scripts/debris/mar_poll.jl deleted file mode 100644 index 017ce40..0000000 --- a/_assets/scripts/debris/mar_poll.jl +++ /dev/null @@ -1,20 +0,0 @@ -@enum State PA GA NC MI AZ WI NV -@enum Month mar apr may jun jul aug sep oct - - -STATE = State -prior_month = "mar" -mon = mar -MON = "mar" -Mon = "mar" -st = "NV" -ST = NV - -include("mar_poll_head.jl") -prior_poll = BSON.load("../objs/"*"$st"*"_2020_p_sample.bson") -@load "../objs/"*"$MON"*"_Polls.bson" months - -current_month = remove_empties(months[mon]) - -include("polls_foot.jl") - diff --git a/_assets/scripts/debris/mar_poll_foot.jl b/_assets/scripts/debris/mar_poll_foot.jl deleted file mode 100644 index 76a92aa..0000000 --- a/_assets/scripts/debris/mar_poll_foot.jl +++ /dev/null @@ -1,72 +0,0 @@ - -@model function poll_model(num_votes::Int64, num_wins::Int64, prior_dist::Distribution) - # Define the prior using the informed prior distribution - p ~ prior_dist - # Define the likelihood with additional uncertainty - num_wins ~ Binomial(num_votes, p) -end - -processed_polls = Dict(state => - Dict(pollster => - process_polls(polls) for (pollster, polls) in pollsters) - for (state, pollsters) in current_month) - -processed_polls_totals = Dict(state => - Dict("num_wins" => - sum(first(values(polls)) for polls in values(pollsters)), - "num_votes" => - sum(last(values(polls)) for polls in values(pollsters))) - for (state, pollsters) in processed_polls) - -num_wins = processed_polls_totals[ST]["num_wins"] -num_votes = processed_polls_totals[ST]["num_votes"] - -poll_posterior = prior_poll - -posterior_mean = mean(poll_posterior[:deep][:p]) -posterior_var = var(poll_posterior[:deep][:p]) -prior_alpha = posterior_mean * - (posterior_mean * (1 - posterior_mean) / posterior_var - 1) -prior_beta = (1 - posterior_mean) * (posterior_mean * - (1 - posterior_mean) / posterior_var - 1) -prior_dist = Beta(prior_alpha, prior_beta) - -model = poll_model(num_votes, num_wins, prior_dist) -sampler = NUTS(0.65) -num_samples = 10000 -num_chains = 4 -init_params = [Dict(:p => 0.5)] -chain = sample(poll_model(num_votes, num_wins, prior_dist), - sampler, num_samples, init_params=init_params) - -p_intv = quantile(chain[:p], [0.025, 0.975]) -p_mean = summarystats(chain)[1,:mean] -p_mcse = summarystats(chain)[1,:mcse] -p_rhat = summarystats(chain)[1,:rhat] -p_df = DataFrame(median = median(chain[:p]), - mean = mean(chain[:p]), - mode = mode(chain[:p]), - q025 = p_intv[1], - q975 = p_intv[2], - mcse = summarystats(chain)[1,:mcse], - rhat = summarystats(chain)[1,:rhat]) - -p_samples = chain[:p] -p_vec = vec(p_samples) -kde_result = kde(p_vec) - -posterior_interval = p_intv -fig = draw_density() -save(("../img/models/"*"$st"*"_"*"$mon"*".png"), fig) - -deep = deepcopy(chain) -@save "../objs/"*"$st"*"_"*"$mon"*"_p_sample.bson" deep - -out = Vector(p_df[1,:]) -out = round.(out,digits = 4) -p_df[1,:] = out -pretty_table(p_df,backend=Val(:html),show_subheader = false) -chain -summarystats(chain) -autocor(chain) -hpd(chain) \ No newline at end of file diff --git a/_assets/scripts/debris/mar_poll_head.jl b/_assets/scripts/debris/mar_poll_head.jl deleted file mode 100644 index adb16b9..0000000 --- a/_assets/scripts/debris/mar_poll_head.jl +++ /dev/null @@ -1,215 +0,0 @@ -using BSON: @load, @save -using BSON -using Colors -using Combinatorics -using CSV -using DataFrames -using Distributions -using Format -using HTTP -using GLMakie -using KernelDensity -using LinearAlgebra -using MCMCChains -using Missings -using PlotlyJS -using Plots -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing -#------------------------------------------------------------------ - - -# @enum State PA GA NC MI AZ WI NV -# STATE = State -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ec2 - ec3 - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - ma2 - ma3 - mi2 - mi3 - mr2 - mr3 - qi2 - qi3 - si2 - si3 - sp2 - sp3 - su2 - su3 - wa2 - wa3 - ws2 - ws3l - ws3s -end -#------------------------------------------------------------------ -const states = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const FLAGRED = "rgb(178, 34, 52)" -const FLAGBLUE = "rgb( 60, 59, 110)" -const PURPLE = "rgb(119, 47, 81)" -const GREENBAR = "rgb( 47, 119, 78)" -const LORANGE = "rgb(225, 170, 110)" -#------------------------------------------------------------------ -mutable struct MetaFrame - meta::Dict{Symbol, Any} - data::DataFrame -end -#------------------------------------------------------------------ -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int -end -#------------------------------------------------------------------ -Month_names = Dict( - "mar" => "March", - "apr" => "April", - "may" => "May", - "jun" => "June", - "aug" => "August", - "sep" => "September", - "oct" => "October") -#------------------------------------------------------------------ -margins = CSV.read("../objs/margins.csv", DataFrame) -margin = first(margins[margins.st .== st, :pct]) -#------------------------------------------------------------------ -""" - filter_empty_entries(dict::Dict{Pollster, Vector{Poll}}) -> Dict{Pollster, Vector{Poll}} - -Filter out entries in a dictionary where the values are empty vectors. - -# Arguments -- `dict::Dict{Pollster, Vector{Poll}}`: A dictionary where the keys are of type `Pollster` and the values are vectors of type `Poll`. - -# Returns -- `Dict{Pollster, Vector{Poll}}`: A new dictionary containing only the entries from the input dictionary where the vectors are not empty. - -# Description -The `filter_empty_entries` function iterates over each key-value pair in the provided dictionary. It constructs a new dictionary that includes only those entries where the value (a vector of `Poll` objects) is not empty. - -# Example -```julia -# Define types for the example -struct Pollster - name::String -end - -struct Poll - question::String - response::String -end - -# Create a dictionary with some empty and non-empty vectors -pollster1 = Pollster("Pollster A") -pollster2 = Pollster("Pollster B") -poll1 = Poll("Question 1", "Response 1") -poll2 = Poll("Question 2", "Response 2") - -dict = Dict( - pollster1 => [poll1, poll2], - pollster2 => [] -) - -# Filter out entries with empty vectors -filtered_dict = filter_empty_entries(dict) -println(filtered_dict) -# Output: -# Dict{Pollster, Vector{Poll}} with 1 entry: -# Pollster("Pollster A") => Poll[Poll("Question 1", "Response 1"), Poll("Question 2", "Response 2")] -""" -function remove_empties(the_month::Dict) - Dict(state => Dict(pollster => polls for (pollster, polls) in pollsters - if !isempty(polls)) for (state, pollsters) in the_month) -end -#------------------------------------------------------------------ -function process_polls(polls::Vector{Poll}) - result = Int64.(collect(collect([(p.biden_support, p.sample_size) for p in polls])[1])) - return [Int64(floor(result[1] / 100 * result[2])), result[2]] -end -#------------------------------------------------------------------ - -""" - draw_density() - -Draw a density plot of the parameter `p` with a shaded credible interval. - -# Returns -- `fig`: A `Figure` object containing the density plot. - -# Description -This function creates a density plot of the parameter `p` using the `kde_result` and `p_vec` variables, -which are assumed to be available in the current scope. The plot includes a shaded region representing -the credible interval specified by `posterior_interval`. - -The density curve is plotted in green (`#a3b35c`) with a stroke width of 8. The shaded credible interval -is filled in orange (`#e1aa6e`). - -The x-axis label is set to "p", the y-axis label is set to "Density", and the plot title is set to -"Density Plot of p for $ST", where `$ST` is a string variable assumed to be available in the current scope. - -The x-axis limits are set to the extrema of `p_vec`, and the y-axis limits are set to start from 0. - -A legend is added to the plot using `axislegend(ax)`. - -# Example -```julia -# Assume kde_result, p_vec, posterior_interval, and ST are available in the current scope -fig = draw_density() -""" -function draw_density() - # Create a new figure with specified resolution - fig = Figure(size = (600, 400)) - - # Add an axis to the figure - ax = Axis(fig[1, 1], xlabel = "Likelihood of Biden win", ylabel = "Number of draws", title = "Model: Biden results in $ST from 2020 election and polling through " * Month_names[Mon]) - - # Plot the full density curve - lines!(ax, kde_result.x, kde_result.density, color = "#a3b35c", linewidth = 3, strokewidth = 4, strokecolor = GREENBAR, label = "Draws") - - # Find the indices corresponding to the posterior interval - indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) - - # Extract the x and y values within the posterior interval - x_region = kde_result.x[indices] - y_region = kde_result.density[indices] - - # Fill the specific area under the curve - band!(ax, x_region, fill(0, length(x_region)), y_region, color = (LORANGE), label = "Credible Interval") - - # Find the y-value corresponding to the specified x-value - y_value = kde_result.density[argmin(abs.(kde_result.x .- margin))] - - # Add a vertical line at the specified x-value from 0 to the y-value - vlines!(ax, [margin], [0, y_value], color = FLAGBLUE, linestyle = :dash, linewidth = 4, label = "2020 Actual") - - # Add a legend to the plot - axislegend(ax) - - # Adjust the plot limits to fit the density line - Makie.xlims!(ax, extrema(p_vec)) - Makie.ylims!(ax, 0, nothing) - - # Display the figure - fig -end -#------------------------------------------------------------------ \ No newline at end of file diff --git a/_assets/scripts/debris/metrics.jl b/_assets/scripts/debris/metrics.jl deleted file mode 100644 index 3fb1a08..0000000 --- a/_assets/scripts/debris/metrics.jl +++ /dev/null @@ -1,64 +0,0 @@ -""" -Yes, there are several additional metrics you can consider when assessing the election outcome based on your Bayesian model: - -1. Posterior mean or median: The mean or median of the posterior distribution can provide a point estimate of the proportion of voters supporting each candidate. This can give you a single "best guess" of the election outcome based on your model. - -2. Probability of winning: You can calculate the probability that a candidate will win the election by computing the proportion of posterior samples where their vote share exceeds 50%. This gives you a direct measure of the likelihood of each candidate winning based on your model. - -3. Posterior probability of a tie: You can also compute the probability of a tie by calculating the proportion of posterior samples where the vote shares are exactly equal (or within a small margin to account for rounding). - -4. Marginal likelihood or Bayes factor: If you want to compare different models (e.g., with different priors or likelihood functions), you can compute the marginal likelihood or Bayes factor. These metrics provide a way to assess the relative fit of different models to the data while accounting for model complexity. - -5. Sensitivity analysis: You can explore how sensitive your results are to the choice of prior or other model assumptions. This can help you assess the robustness of your conclusions and identify which assumptions are most critical. - -6. Predictive accuracy: If you have historical data from previous elections, you can assess the predictive accuracy of your model by comparing its predictions to the actual outcomes. This can help you calibrate your model and understand how well it performs in practice. - -These additional metrics can provide a more comprehensive understanding of the election outcome and the uncertainty associated with your predictions. They can also help you communicate your results to a wider audience and make more informed decisions based on your analysis. - -Certainly! In Julia, you can use the DynamicLinearModels.jl package for Kalman filtering and state-space modeling. This package provides a flexible and efficient framework for working with dynamic linear models, including the Kalman filter. - -To install the DynamicLinearModels.jl package, you can use the following command in the Julia REPL: - -```julia -using Pkg -Pkg.add("DynamicLinearModels") -``` - -Once the package is installed, you can use it to implement Kalman filtering for your poll aggregation. Here's a basic example of how you can use DynamicLinearModels.jl to create a Kalman filter for tracking the true state of the race over time: - -```julia -using DynamicLinearModels - -# Define the state-space model -model = LocalLevel(1.0) - -# Initialize the Kalman filter -kf = kalman_filter(model, 1.0) - -# Iterate over the polls -for poll in polls - # Extract the poll date, sample size, and candidate support - date = poll.date - sample_size = poll.sample_size - candidate_support = poll.candidate_support - - # Update the Kalman filter with the new poll - update_kalman_filter!(kf, date, candidate_support, sample_size) -end - -# Get the filtered estimates of the true state -filtered_state = get_filtered_state(kf) -``` - -In this example, we define a `LocalLevel` model, which assumes that the true state of the race follows a random walk over time. We then initialize a Kalman filter with an initial estimate of the state. - -For each poll, we extract the relevant information (date, sample size, and candidate support) and update the Kalman filter using the `update_kalman_filter!` function. The function takes the Kalman filter object, the poll date, the candidate support (as a proportion), and the sample size. - -After processing all the polls, we can retrieve the filtered estimates of the true state using the `get_filtered_state` function. - -DynamicLinearModels.jl provides a wide range of options for customizing the state-space model, handling missing data, and estimating model parameters. You can refer to the package documentation for more details and examples: https://github.com/LAMPSPUC/DynamicLinearModels.jl - -Keep in mind that Kalman filtering assumes that the polls are noisy observations of the true state, and it tries to estimate the true state by balancing the information from the polls with the assumed dynamics of the state. The performance of the Kalman filter will depend on the quality of the polls, the appropriateness of the state-space model, and the choice of model parameters. - -As with any model, it's important to validate the Kalman filter's assumptions and performance using historical data or out-of-sample predictions before relying on it for real-time poll aggregation. -""" \ No newline at end of file diff --git a/_assets/scripts/debris/models.jl b/_assets/scripts/debris/models.jl deleted file mode 100644 index f8ef5eb..0000000 --- a/_assets/scripts/debris/models.jl +++ /dev/null @@ -1,21 +0,0 @@ - -# deprecated until conformed to current usage -@model function election_model(num_votes, num_wins) - # Prior: Beta(2, 2) equivalent to a close race going in - p ~ Beta(2, 2) - - # Likelihood: Binomial(num_votes, p) - num_wins ~ Binomial(num_votes, p) -end - -election_posterior = sample(election_model(num_votes, num_wins), sampler, num_samples, init_params=init_params) - -prior_dist = Empirical(vec(election_posterior[:p].value[:])) - -@model function poll_model(Int64, num_wins::Int64) - # Define the prior using the posterior from the previous analysis - p ~ prior_dist - - # Define the likelihood - num_wins ~ Binomial(num_votes, p) -end \ No newline at end of file diff --git a/_assets/scripts/debris/moe.jl b/_assets/scripts/debris/moe.jl deleted file mode 100644 index edced0f..0000000 --- a/_assets/scripts/debris/moe.jl +++ /dev/null @@ -1,38 +0,0 @@ -using DataFrames -using Distributions -using Formatting -using Statistics - -const recount = 0.025 # based on Georgia recount rule of half-percent - -# confidence interval, alpha, proportion and z scores -cis = [0.01, 0.025, 0.05, 0.10, 0.20] # 99% 97.5% 95% 90% 80% -alf = 1 .- cis -""" -The assumption of p = 0.5 for the population proportion is based on the concept of maximum variance in a binomial distribution. In a binomial distribution, the variance is calculated as p * (1 - p) * n, where p is the probability of success, and n is the number of trials. The maximum variance occurs when p = 0.5, which means that the probability of success is equal to the probability of failure. When calculating the sample size for a proportion, if there is no prior knowledge about the population proportion, it is common practice to assume p = 0.5. This assumption provides the most conservative estimate of the sample size needed to achieve a desired level of precision. By setting p = 0.5, we are essentially assuming the worst-case scenario in terms of variability, which leads to the largest possible sample size. This ensures that the sample size is sufficient to achieve the desired level of precision, regardless of the actual population proportion. -""" -p = 0.5 # assumed proportion - -# one tailed test - -zzs = quantile(Normal, 1 .- alf) - -labs = map(f -> @sprintf("%.2f%%", f * 100), alf) -rads = Formatting.format.(n, commas=true) - - -# Solve for the sample size - -n = ceil.(Int, (zzs.^2 * p * (1 - p)) / recount^2) - -rads = Formatting.format.(n, commas=true) - -tab = DataFrame( - ci = labs, - n = rads -) - -header = ["Confidence level", "Required sample"] - -pretty_tables(tab, backend = Val(:html), header = header, subhead = false) - diff --git a/_assets/scripts/debris/multi_color_map.jl b/_assets/scripts/debris/multi_color_map.jl deleted file mode 100644 index e7d1996..0000000 --- a/_assets/scripts/debris/multi_color_map.jl +++ /dev/null @@ -1,94 +0,0 @@ -using PlotlyJS - -const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] - -const VOTES = [6, 10, 11, 16, 15, 19, 16] - -const TIED = 269 - -const FLAGRED = "rgb(178, 34, 52)" - -const FLAGBLUE = "rgb(60, 59, 110)" - -const PURPLE = "rgb(119, 47, 81)" - -const GREENBAR = "rgb(47, 119, 78)" - -const STATE_COLORS = Dict( - "PA" => FLAGRED, - "NC" => FLAGRED, - "NV" => PURPLE, - "MI" => PURPLE, - "WI" => PURPLE, - "AZ" => PURPLE, - "GA" => PURPLE -) - -votes = Dict( - "NV" => 6, - "MI" => 15, - "WI" => 10, - "NC" => 16, - "AZ" => 11, - "PA" => 19, - "GA" => 16 -) - -data = [votes[state] for state in STATES] - -function electoral_map_with_colors(data, state_colors) - # Create the data for the choropleth map - choropleth_trace = PlotlyJS.choropleth( - locationmode="USA-states", - locations=STATES, - z=data, - colorscale=[[0, "rgba(0,0,0,0)"], [1, "rgba(0,0,0,0)"]], - showscale=false, - marker=attr(line=attr(color="white", width=2)), - hoverinfo="location+text" - ) - - # Create the data for the state colors - color_traces = [ - PlotlyJS.choropleth( - locationmode="USA-states", - locations=[state], - z=[1], - colorscale=[[0, color], [1, color]], - showscale=false, - marker=attr(line=attr(color="white", width=2)), - hoverinfo="none" - ) - for (state, color) in state_colors - ] - - # Create the data for the state labels - label_trace = PlotlyJS.scattergeo( - locationmode="USA-states", - locations=STATES, - text=data, - textfont=attr(size=12, color="white"), - mode="text", - showlegend=false, - hoverinfo="none" - ) - - # Create the layout for the map - layout = PlotlyJS.Layout( - title= "Without PA & NC: 58 Swing State Electoral Votes (45 required to win)", - geo=attr( - scope="usa", - projection=attr(type="albers usa"), - showlakes=true, - lakecolor="rgb(255, 255, 255)" - ) - ) - - # Create the figure with all traces - fig = PlotlyJS.plot(vcat(choropleth_trace, color_traces..., label_trace), layout) - - # Save the plot as an image file - PlotlyJS.savefig(fig, "/Users/ro/projects/SwingWatch/_assets/img/maps/no_pa_nc.png") -end - -electoral_map_with_colors(data, STATE_COLORS) \ No newline at end of file diff --git a/_assets/scripts/debris/mydatabase.db b/_assets/scripts/debris/mydatabase.db deleted file mode 100644 index 18172f7..0000000 Binary files a/_assets/scripts/debris/mydatabase.db and /dev/null differ diff --git a/_assets/scripts/debris/naive_prior.jl b/_assets/scripts/debris/naive_prior.jl deleted file mode 100644 index 9818bfc..0000000 --- a/_assets/scripts/debris/naive_prior.jl +++ /dev/null @@ -1,55 +0,0 @@ - -using MCMCChains -using StatsPlots -using Statistics -using Turing - -# Set the number of votes and wins for PA -num_votes = 6835903 -num_wins = 3458229 - -# Define the model -@model function election_model(num_votes, num_wins) - # Prior: Beta(2, 2) equivalent to a close race going in - p ~ Beta(2, 2) - - # Likelihood: Binomial(num_votes, p) - num_wins ~ Binomial(num_votes, p) -end - -# Set up the sampler -sampler = NUTS(0.65) - -# Specify the number of samples and chains -num_samples = 10000 -num_chains = 4 - -# Sample from the posterior -init_params = [Dict(:p => 0.5)] -chain = sample(election_model(num_votes, num_wins), sampler, MCMCThreads(), num_samples, num_chains) - - -# Plot the posterior density -plot(chain, xlabel="Probability of Winning", ylabel="Density", - title="Posterior Distribution of Winning Probability") - -# Compute posterior mean and 95% credible interval -# 67%, 89%, and 97% -posterior_mean = mean(chain[:p]) -posterior_interval = quantile(chain[:p], [0.025, 0.975]) -posterior_interval = quantile(chain[:p], [0.67, 0.89, 0.97]) - -println("Posterior mean: ", posterior_mean) -println("95% credible interval: ", posterior_interval) - -# Summary statistics -summarystats(chain) - -# Trace plot -plot(chain) - -# Autocorrelation -autocor(chain) - -# Effective sample size -ess(chain) \ No newline at end of file diff --git a/_assets/scripts/debris/national_map.jl b/_assets/scripts/debris/national_map.jl deleted file mode 100644 index b404d01..0000000 --- a/_assets/scripts/debris/national_map.jl +++ /dev/null @@ -1,195 +0,0 @@ -using PlotlyJS - -#const STATES = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const STATES = ["AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", "GA", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "ME1", "ME2", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", "NE1", "NE2", "NE3", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA", "WI", "WV", "WY"] - -# const VOTES = [6, 10, 11, 16, 15, 19, 16] - -# const TIED = 269 - -const FLAGRED = "rgb(178, 34, 52)" - -const FLAGBLUE = "rgb(60, 59, 110)" - -const PURPLE = "rgb(119, 47, 81)" - -const GREENBAR = "rgb(47, 119, 78)" - -const STATE_COLORS = Dict( - "PA" => PURPLE, - "NC" => PURPLE, - "NV" => PURPLE, - "MI" => PURPLE, - "WI" => PURPLE, - "AZ" => PURPLE, - "GA" => PURPLE, - "CA" => FLAGBLUE, - "CO" => FLAGBLUE, - "CT" => FLAGBLUE, - "DC" => FLAGBLUE, - "DE" => FLAGBLUE, - "HI" => FLAGBLUE, - "IL" => FLAGBLUE, - "MA" => FLAGBLUE, - "MD" => FLAGBLUE, - "ME" => FLAGBLUE, - "ME1" => FLAGBLUE, - "MI" => FLAGBLUE, - "MN" => FLAGBLUE, - "NE2" => FLAGBLUE, - "NH" => FLAGBLUE, - "NJ" => FLAGBLUE, - "NM" => FLAGBLUE, - "NY" => FLAGBLUE, - "OR" => FLAGBLUE, - "RI" => FLAGBLUE, - "VA" => FLAGBLUE, - "VT" => FLAGBLUE, - "WA" => FLAGBLUE, - "AK" => FLAGRED, - "AL" => FLAGRED, - "AR" => FLAGRED, - "FL" => FLAGRED, - "IA" => FLAGRED, - "ID" => FLAGRED, - "IN" => FLAGRED, - "KS" => FLAGRED, - "KY" => FLAGRED, - "LA" => FLAGRED, - "ME2" => FLAGRED, - "MO" => FLAGRED, - "MS" => FLAGRED, - "MT" => FLAGRED, - "NC" => FLAGRED, - "ND" => FLAGRED, - "NE" => FLAGRED, - "NE1" => FLAGRED, - "NE3" => FLAGRED, - "OH" => FLAGRED, - "OK" => FLAGRED, - "SC" => FLAGRED, - "SD" => FLAGRED, - "TN" => FLAGRED, - "TX" => FLAGRED, - "UT" => FLAGRED, - "WV" => FLAGRED, - "WY" => FLAGRED - ) - -votes = Dict( - "AK" => 3, - "AL" => 9, - "AR" => 6, - "FL" => 30, - "IA" => 6, - "ID" => 4, - "IN" => 11, - "KS" => 6, - "KY" => 8, - "LA" => 8, - "ME2" => 1, - "MO" => 10, - "MS" => 6, - "MT" => 4, - "NC" => 16, - "ND" => 3, - "NE" => 1, - "NE1" => 1, - "NE3" => 2, - "OH" => 17, - "OK" => 7, - "SC" => 9, - "SD" => 3, - "TN" => 11, - "TX" => 40, - "UT" => 6, - "WV" => 4, - "WY" => 3, - "AZ" => 11, - "CA" => 54, - "CO" => 10, - "CT" => 7, - "DC" => 3, - "DE" => 3, - "GA" => 16, - "HI" => 4, - "IL" => 19, - "MA" => 11, - "MD" => 10, - "ME" => 2, - "ME1" => 1, - "MI" => 15, - "MN" => 10, - "NE2" => 1, - "NH" => 4, - "NJ" => 14, - "NM" => 5, - "NV" => 6, - "NY" => 28, - "OR" => 8, - "PA" => 19, - "RI" => 4, - "VA" => 13, - "VT" => 3, - "WA" => 12, - "WI" => 10 - ) - -data = [votes[state] for state in STATES] - -function electoral_map_with_colors(data, state_colors) - # Create the data for the choropleth map - choropleth_trace = PlotlyJS.choropleth( - locationmode="USA-states", - locations=STATES, - z=data, - colorscale=[[0, "rgba(0,0,0,0)"], [1, "rgba(0,0,0,0)"]], - showscale=false, - marker=attr(line=attr(color="white", width=2)), - hoverinfo="location+text" - ) - - # Create the data for the state colors - color_traces = [ - PlotlyJS.choropleth( - locationmode="USA-states", - locations=[state], - z=[1], - colorscale=[[0, color], [1, color]], - showscale=false, - marker=attr(line=attr(color="white", width=2)), - hoverinfo="none" - ) - for (state, color) in state_colors - ] - - # Create the data for the state labels - label_trace = PlotlyJS.scattergeo( - locationmode="USA-states", - locations=STATES, - text=data, - textfont=attr(size=12, color="white"), - mode="text", - showlegend=false, - hoverinfo="none" - ) - - # Create the layout for the map - layout = PlotlyJS.Layout( - title= "93 Swing State Electoral Votes (45 required to win)", - geo=attr( - scope="usa", - projection=attr(type="albers usa"), - showlakes=true, - lakecolor="rgb(255, 255, 255)" - ) - ) - - # Create the figure with all traces - fig = PlotlyJS.plot(vcat(choropleth_trace, color_traces..., label_trace), layout) - - # Save the plot as an image file - PlotlyJS.savefig(fig, "/Users/ro/projects/SwingWatch/_assets/img/maps/base.png") -end - -electoral_map_with_colors(data, STATE_COLORS) diff --git a/_assets/scripts/debris/new_posterior_aftpart.jl b/_assets/scripts/debris/new_posterior_aftpart.jl deleted file mode 100644 index 97873fe..0000000 --- a/_assets/scripts/debris/new_posterior_aftpart.jl +++ /dev/null @@ -1,61 +0,0 @@ -""" - draw_density() - -Draw a density plot of the parameter `p` with a shaded credible interval. - -# Returns -- `fig`: A `Figure` object containing the density plot. - -# Description -This function creates a density plot of the parameter `p` using the `kde_result` and `p_vec` variables, which are assumed to be available in the current scope. The plot includes a shaded region representing the credible interval specified by `posterior_interval`. - -The density curve is plotted in green (`#a3b35c`) with a stroke width of 8. The shaded credible interval is filled in orange (`#e1aa6e`). - -The x-axis label is set to "p", the y-axis label is set to "Density", and the plot title is set to "Density Plot of p for $ST", where `$ST` is a string variable assumed to be a vailable in the current scope. - -The x-axis limits are set to the extrema of `p_vec`, and the y-axis limits are set to start from 0. - -A legend is added to the plot using `axislegend(ax)`. - -# Example -```julia -# Assume kde_result, p_vec, posterior_interval, and ST are available in the current scope -fig = draw_density() -""" -function draw_density() - # Create a new figure with specified resolution - fig = Figure(size = (600, 400)) - - # Add an axis to the figure - ax = Axis(fig[1, 1], xlabel = "Likelihood of Harris win", ylabel = "Number of draws", title = "Model: $ST from beginning assumption of an even contest on July 22 before polling") - - # Plot the full density curve - lines!(ax, kde_result.x, kde_result.density, color = "#a3b35c", linewidth = 3, strokewidth = 4, strokecolor = GREENBAR, label = "Draws") - - # Find the indices corresponding to the posterior interval - indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) - - # Extract the x and y values within the posterior interval - x_region = kde_result.x[indices] - y_region = kde_result.density[indices] - - # Fill the specific area under the curve - band!(ax, x_region, fill(0, length(x_region)), y_region, color = (LORANGE), label = "Credible Interval") - - # Find the y-value corresponding to the specified x-value - y_value = kde_result.density[argmin(abs.(kde_result.x .- margin))] - - # Add a vertical line at the specified x-value from 0 to the y-value - vlines!(ax, [margin], [0, y_value], color = FLAGBLUE, linestyle = :dash, linewidth = 4, label = "2020 Biden %age two-person race") - - # Add a legend to the plot - axislegend(ax) - - # Adjust the plot limits to fit the density line - Makie.xlims!(ax, extrema(p_vec)) - Makie.ylims!(ax, 0, nothing) - - # Display the figure - fig -end -#------------------------------------------------------------------ diff --git a/_assets/scripts/debris/new_prior.jl b/_assets/scripts/debris/new_prior.jl deleted file mode 100644 index 4e1bfb9..0000000 --- a/_assets/scripts/debris/new_prior.jl +++ /dev/null @@ -1,76 +0,0 @@ -#include("first_posterior_forepart.jl") -using BSON: @load, @save -using CSV -using DataFrames -using Format -using GLMakie -using KernelDensity -using LinearAlgebra -using MCMCChains -using Missings -using PrettyTables -using Printf -using Serialization -using Statistics -using Turing -#------------------------------------------------------------------ -const FLAGRED = "rgb(178, 34, 52)" -const FLAGBLUE = "rgb( 60, 59, 110)" -const PURPLE = "rgb(119, 47, 81)" -const GREENBAR = "rgb( 47, 119, 78)" -const LORANGE = "rgb(225, 170, 110)" -#------------------------------------------------------------------ - -# Define the model - -@model function election_model(num_votes::Int64, num_wins::Int64) - p ~ Beta(225, 225) - num_wins ~ Binomial(num_votes, p) -end - -sampler = NUTS(0.65) -num_samples = 30000 -num_chains = 4 -poll_size = 3500 # Typical poll size -num_votes = poll_size -num_wins = poll_size ÷ 2 -init_params = [Dict(:p => 0.5) for _ in 1:num_chains] - - -# margins = CSV.read("../objs/margins.csv", DataFrame) -# margin = first(margins[margins.st .== ST, :pct]) - -chain = sample(election_model(num_votes, num_wins), sampler, - num_samples, init_params=init_params) - -p_intv = quantile(chain[:p], [0.025, 0.975]) -p_mean = summarystats(chain)[1, :mean] -p_mcse = summarystats(chain)[1, :mcse] -p_rhat = summarystats(chain)[1, :rhat] -p_df = DataFrame(median = median(chain[:p]), - mean = mean(chain[:p]), - mode = mode(chain[:p]), - q025 = p_intv[1], - q975 = p_intv[2], - mcse = summarystats(chain)[1, :mcse], - rhat = summarystats(chain)[1, :rhat]) - -p_samples = chain[:p] -p_vec = vec(p_samples) -kde_result = kde(p_vec) - - -# include("first_posterior_aftpart.jl") - -posterior_interval = p_intv -fig = draw_density() -deep = deepcopy(chain) - -@save ("new_prior.bson") deep -save(("../img/models/$ST" * "_new_prior.png"), fig) - -out = Vector(p_df[1,:]) -out = round.(out,digits = 4) -p_df[1,:] = out -pretty_table(p_df,backend=Val(:html), show_subheader = false) - diff --git a/_assets/scripts/debris/old_az.md b/_assets/scripts/debris/old_az.md deleted file mode 100644 index 1f863bd..0000000 --- a/_assets/scripts/debris/old_az.md +++ /dev/null @@ -1,227 +0,0 @@ -In the 2020 election President Biden won 50.16% (0.5016) of the votes cast for Biden or Trump in Arizona. This leaves out votes for third-party candidates. Taking the actual result as a starting point, the model introduces some uncertainty into the result to create a range of outcomes for that election from 50.10% to 50.21%. Next, the results of each month's polling are factored in on a rolling basis. When the plot shows that more of the credible interval lies to the left of the 2020 margin it indicates that Harris is losing ground compared to the 2020 election results, taking the polls at face value. - -Beginning with polls conducted from July 23 - July 31, 2024, the model that used results through July 22, 2024 plus an allowance for the uncertainty introduced by the entry of Vice President Harris in place of President Biden will be used as the starting point, to be updated fortnightly by later poll results. - -## July assessment from beginning of Harris campaign - -Harris wins under the *Relaxed* criterion. - -~~~ - - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50130.50130.50120.50070.50180.01.0
- -~~~ - -## July assessment through end of Biden campaign - -Biden wins under the *Relaxed* criterion. - -~~~ - - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50130.50130.50150.50080.50180.01.0
- - -~~~ - -## June assessment - -Biden wins under the *Relaxed* criterion. - -~~~ - - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50140.50140.50140.50090.50190.01.0008
- - - ~~~ - -## May assessment - -Biden wins under the *Relaxed* criterion. - -~~~ - - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50140.50140.50150.50090.5020.01.0
- - - ~~~ -## April assessment - -Biden wins under the *Relaxed* criterion. -~~~ - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50150.50150.50130.50090.5020.01.0008
- - -~~~ -## March assessment -Biden wins under the *Relaxed* criterion. - - -~~~ - - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50150.50150.50140.5010.50210.01.0001 -
- -~~~ - -## 2020 election - -~~~ - - - - - - - - - - - - - - - - - - - - - - - -
medianmeanmodeq025q975mcserhat
0.50160.50160.50160.5010.50210.01.0002
- -~~~ diff --git a/_assets/scripts/debris/org.mc b/_assets/scripts/debris/org.mc deleted file mode 100644 index 2add5e0..0000000 --- a/_assets/scripts/debris/org.mc +++ /dev/null @@ -1,15 +0,0 @@ -@def title = "" - -hold until it looks like there may be a tie - -## Day One - -On January 3, 2025 at noon, there will be no members of the House of Representatives and the office of Speaker will be vacant. It falls to the Clerk of the House of Representatives to set in motion the process by which the incoming members are identified and a Speaker elected. The Speaker then administers the oath of office to the members. Although the process is usually a formality, the opening in 2021 required 15 rounds of voting to elect Kevin McCarthy as Speaker because he lacked sufficient support from Republicans, who were in the majority. - -Before the House has selected a Speaker, the Clerk presides. Kevin McCumber is the Acting Clerk of the House. He was appointed by Kevin McCarthy following the resignation of the Clerk who was nominated at the organization of the current Congress. McCumber's deputy, who serves at his pleasure, is Lisa Grant. - -## Contingencies - -### There are five election results that would result in a [tied electoral vote](@ref 12th). - -### The House has 435 voting members. Majority control is 218 votes when all members are present. \ No newline at end of file diff --git a/_assets/scripts/debris/outcomes.jl b/_assets/scripts/debris/outcomes.jl deleted file mode 100644 index f01c965..0000000 --- a/_assets/scripts/debris/outcomes.jl +++ /dev/null @@ -1,61 +0,0 @@ -# purpose: create a dataframe `outcomes` with variables state containing states -# that vote in combination in the sample space, the collective electoral votes -# and whether that results in a Harris win, loss or draw - -using CSV -using DataFrames -using Colors -using Combinatorics -using HTTP -using PlotlyJS - -# Include files -include("constants.jl") -include("utils.jl") - -# see college_table.jl for production of 2024vote.csv -# base = CSV.read("../objs/2020vote.csv", DataFrame) -base = CSV.read("/Users/ro/projects/swingwatch/_assets/objs/2024vote.csv", DataFrame) - -# see CreateOutcomes.jl for production of outcome.csv -objs = "../objs/" -outcome = CSV.read(objs * "outcome.csv",DataFrame) - -# pa_outcome = outcome[(occursin.("PA", outcome.combo)) .& (outcome.votes .== 269), :] - -# pa_outcome = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== "Tie"), :] - -red_states = STATES - -""" - show_results(outcome::DataFrame, state::String, result::String) - -Display the results of an election outcome DataFrame for a specific state and result type in a markdown-formatted table. - -# Arguments -- `outcome::DataFrame`: A DataFrame containing election outcome data, with columns for state combinations, results, and other relevant information. -- `state::String`: The name of the state for which to display results. -- `result::String`: The type of result to display (e.g., "winner", "margin", etc.). - -# Returns -- `String`: A markdown-formatted string representing a table containing the requested results. - -# Notes -- This function filters the `outcome` DataFrame to include only rows where the state combination contains the specified `state` and the `result` column matches the specified `result` string. -- The filtered rows are then converted to a markdown table using the `pretty_table` function from the PrettyTables.jl package. -- The `show_subheader` option is set to `false` to exclude column headers from the markdown table. - -# Examples -```julia -# Assuming `outcome` is a DataFrame with columns named "combo", "result", and others -maryland_winner = show_results(outcome, "Maryland", "winner") -println(maryland_winner) - -georgia_margin = show_results(outcome, "Georgia", "margin") -println(georgia_margin) -""" -function show_results(outcome::DataFrame, state::String, result::String) - markdown_table = pretty_table(outcome[(occursin.(state, outcome.combo)) .& (outcome.result .== result), :] , backend = Val(:markdown), show_subheader = false) - return markdown_table -end -# group_counts = combine(groupby(outcome, :result), nrow => :count) \ No newline at end of file diff --git a/_assets/scripts/debris/poll.jl b/_assets/scripts/debris/poll.jl deleted file mode 100644 index d449ef6..0000000 --- a/_assets/scripts/debris/poll.jl +++ /dev/null @@ -1,158 +0,0 @@ -months[aug1][AZ][ny2] = [Poll(49,45, 677)] -months[aug1][AZ][tr] = [Poll(47,48,1000)] -months[aug1][GA][ny2] = [Poll(44,51, 661)] -months[aug1][MI][tr] = [Poll(49,47, 800)] -months[aug1][NC][cj] = [Poll(44,47, 600)] -months[aug1][NV][ny2] = [Poll(42,45, 677)] -months[aug1][NV][tr] = [Poll(45,49,1000)] -months[aug1][PA][ec2] = [Poll(47,47,1000)] -months[aug1][PA][qi2] = [Poll(48,45,1738)] -months[aug1][PA][tr] = [Poll(44,46,1000)] -months[aug1][WI][tr] = [Poll(48,49, 800)] -months[aug2][AZ][bl2] = [Poll(48,48, 805)] -months[aug2][AZ][cn2] = [Poll(44,49, 800)] -months[aug2][AZ][ec2] = [Poll(47,50, 720)] -months[aug2][AZ][fo2] = [Poll(50,49,1014)] -months[aug2][AZ][ia] = [Poll(48,49, 800)] -months[aug2][GA][bl2] = [Poll(49,47, 801)] -months[aug2][GA][ec2] = [Poll(49,48, 800)] -months[aug2][GA][fo2] = [Poll(49,49,1014)] -months[aug2][GA][ia] = [Poll(48,48, 800)] -months[aug2][MI][bl2] = [Poll(49,46, 702)] -months[aug2][MI][ec2] = [Poll(50,47, 800)] -months[aug2][MI][ep] = [Poll(44,44, 600)] -months[aug2][MI][tr] = [Poll(47,47,1089)] -months[aug2][NC][bl2] = [Poll(50,45, 803)] -months[aug2][NC][ec2] = [Poll(48,49, 775)] -months[aug2][NC][eu] = [Poll(47,48, 720)] -months[aug2][NC][fo2] = [Poll(49,50, 999)] -months[aug2][NC][ia] = [Poll(48,49, 800)] -months[aug2][NV][bl2] = [Poll(49,45, 700)] -months[aug2][NV][ec2] = [Poll(49,48,1168)] -months[aug2][NV][fo2] = [Poll(50,48,1026)] -months[aug2][NV][ia] = [Poll(47,48, 800)] -months[aug2][PA][bl2] = [Poll(51,47, 803)] -months[aug2][PA][ec2] = [Poll(48,48, 950)] -months[aug2][PA][tr] = [Poll(45,47,1087)] -months[aug2][WI][tr] = [Poll(46,47,1083)] -months[jul2][AZ][bl2] = [Poll(48,47, 804)] -months[jul2][AZ][ec2] = [Poll(44,49, 800)] -months[jul2][GA][bl2] = [Poll(47,47, 799)] -months[jul2][GA][ec2] = [Poll(46,48, 800)] -months[jul2][MI][bl2] = [Poll(53,42, 706)] -months[jul2][MI][ec2] = [Poll(45,46, 800)] -months[jul2][MI][fo2] = [Poll(43,45,1012)] -months[jul2][NC][bl2] = [Poll(46,48, 706)] -months[jul2][NV][bl2] = [Poll(47,45, 454)] -months[jul2][PA][am] = [Poll(45,47, 600)] -months[jul2][PA][bl2] = [Poll(46,50, 804)] -months[jul2][PA][ec2] = [Poll(46,48, 850)] -months[jul2][PA][fo2] = [Poll(45,43,1034)] -months[jul2][WI][bl2] = [Poll(49,47, 700)] -months[jul2][WI][ec2] = [Poll(47,47, 854)] -months[jul2][WI][fo2] = [Poll(46,46,1046)] -months[sep1][AZ][ag] = [Poll(48,48,1015)] -months[sep1][AZ][ec2] = [Poll(48,49, 868)] -months[sep1][AZ][tr] = [Poll(46,47,1088)] -months[sep1][GA][ag] = [Poll(48,48, 835)] -months[sep1][GA][aj] = [Poll(44,47,1000)] -months[sep1][GA][ec2] = [Poll(47,50, 975)] -months[sep1][GA][qi2] = [Poll(46,49, 969)] -months[sep1][GA][tr] = [Poll(45,46,1098)] -months[sep1][MI][cb2] = [Poll(50,49,1086)] -months[sep1][MI][ec2] = [Poll(49,47, 875)] -months[sep1][MI][ia] = [Poll(48,49, 580)] -months[sep1][MI][ma2] = [Poll(52,47,1138)] -months[sep1][MI][mi2] = [Poll(48,48, 800)] -months[sep1][MI][qi2] = [Poll(51,46, 905)] -months[sep1][NC][ag] = [Poll(46,49, 973)] -months[sep1][NC][cj] = [Poll(45,46, 600)] -months[sep1][NC][ec2] = [Poll(49,48,1000)] -months[sep1][NC][qi2] = [Poll(50,47, 940)] -months[sep1][NC][tr] = [Poll(46,48,1024)] -months[sep1][NC][wr] = [Poll(49,46, 900)] -months[sep1][NV][ec2] = [Poll(48,48, 895)] -months[sep1][NV][tr] = [Poll(45,44,1079)] -months[sep1][PA][cb2] = [Poll(50,50,1085)] -months[sep1][PA][ec2] = [Poll(47,48, 880)] -months[sep1][PA][fm2] = [Poll(49,46, 890)] -months[sep1][PA][ia] = [Poll(48,50, 875)] -months[sep1][PA][ma2] = [Poll(49,49,1486)] -months[sep1][PA][ny2] = [Poll(50,46,1082)] -months[sep1][PA][qi2] = [Poll(51,46,1331)] -months[sep1][PA][us] = [Poll(49,46, 500)] -months[sep1][PA][wa2] = [Poll(48,48,1003)] -months[sep1][WI][cb2] = [Poll(51,49, 959)] -months[sep1][WI][ec2] = [Poll(49,47, 875)] -months[sep1][WI][fa] = [Poll(49,48, 600)] -months[sep1][WI][ia] = [Poll(49,47, 800)] -months[sep1][WI][ma2] = [Poll(50,49,1194)] -months[sep1][WI][mr2] = [Poll(52,48, 738)] -months[sep1][WI][qi2] = [Poll(51,46, 905)] -months[sep2][AZ][ny2] = [Poll(50,45, 713)] -months[sep2][AZ][ra] = [Poll(47,49,1071)] -months[sep2][AZ][ma] = [Poll(49,50,1274)] -months[sep2][AZ][bl2] = [Poll(50,47, 926)] -months[sep2][AZ][fo2] = [Poll(48,51, 754)] -months[sep2][AZ][ai] = [Poll(49,50, 946)] -months[sep2][AZ][us] = [Poll(42,48, 500)] -months[sep2][AZ][ia] = [Poll(48,49, 800)] -months[sep2][AZ][ec2] = [Poll(48,49, 850)] -months[sep2][NV][ia] = [Poll(49,48, 800)] -months[sep2][NV][ag] = [Poll(50,49, 736)] -months[sep2][NV][ai] = [Poll(51,48, 858)] -months[sep2][NV][co] = [Poll(48,47, 409)] -months[sep2][NV][bl2] = [Poll(58,45, 516)] -months[sep2][NV][ra] = [Poll(48,49, 738)] -months[sep2][WI][tr] = [Poll(46,47,1079)] -months[sep2][WI][ny2] = [Poll(49,47, 680)] -months[sep2][WI][ai] = [Poll(48,50,1077)] -months[sep2][WI][mq] = [Poll(52,48, 798)] -months[sep2][WI][co] = [Poll(49,47, 411)] -months[sep2][WI][bl2] = [Poll(51,48, 785)] -months[sep2][WI][ra] = [Poll(49,49,1071)] -months[sep2][MI][tr] = [Poll(45,47,1086)] -months[sep2][MI][ny2] = [Poll(48,47, 688)] -months[sep2][MI][ai] = [Poll(47,51, 918)] -months[sep2][MI][co] = [Poll(51,48, 416)] -months[sep2][MI][bl2] = [Poll(50,47, 800)] -months[sep2][MI][ra] = [Poll(48,48,1086)] -months[sep2][MI][us] = [Poll(48,45, 500)] -months[sep2][PA][ec2] = [Poll(48,48,1000)] -months[sep2][PA][tr] = [Poll(45,48,1090)] -months[sep2][PA][fo2] = [Poll(49,49, 775)] -months[sep2][PA][ai] = [Poll(48,51,1775)] -months[sep2][PA][co] = [Poll(50,49, 474)] -months[sep2][PA][bl2] = [Poll(51,46, 924)] -months[sep2][PA][ra] = [Poll(48,48,1202)] -months[sep2][PA][fa] = [Poll(50,47, 600)] -months[sep2][PA][su] = [Poll(46,46, 700)] -months[sep2][PA][mc] = [Poll(48,48, 450)] -months[sep2][NC][ec2] = [Poll(48,49, 850)] -months[sep2][NC][wp] = [Poll(48,50,1001)] -months[sep2][NC][qi2] = [Poll(48,49, 953)] -months[sep2][NC][ia] = [Poll(49,50, 800)] -months[sep2][NC][ec] = [Poll(47,49,1005)] -months[sep2][NC][cn2] = [Poll(49,49, 931)] -months[sep2][NC][ai] = [Poll(51,48,1173)] -months[sep2][NC][fo2] = [Poll(49,50, 787)] -months[sep2][NC][co] = [Poll(49,49, 411)] -months[sep2][NC][bl2] = [Poll(50,48, 828)] -months[sep2][NC][ma] = [Poll(49,49,1348)] -months[sep2][NC][ra] = [Poll(46,49,1078)] -months[sep2][NC][ny2] = [Poll(47,49, 682)] -months[sep2][GA][qi2] = [Poll(45,50, 942)] -months[sep2][GA][ia] = [Poll(48,48, 800)] -months[sep2][GA][ai] = [Poll(49,50,1200)] -months[sep2][GA][cb2] = [Poll(49,51,1441)] -months[sep2][GA][fo2] = [Poll(51,48, 707)] -months[sep2][GA][co] = [Poll(47,49, 411)] -months[sep2][GA][bl2] = [Poll(49,49, 913)] -months[sep2][GA][ma] = [Poll(49,50,1220)] -months[sep2][GA][ag] = [Poll(48,48, 835)] -months[sep2][GA][ny2] = [Poll(45,49, 682)] - - - - - diff --git a/_assets/scripts/debris/poll_arg.jl b/_assets/scripts/debris/poll_arg.jl deleted file mode 100644 index d4091a9..0000000 --- a/_assets/scripts/debris/poll_arg.jl +++ /dev/null @@ -1,183 +0,0 @@ -@enum Month mar apr may jun jul aug sep oct nov -@enum Pollster begin - bi2 - bi3 - bl2 - bl3 - cn2 - cn3 - ec2 - ec3 - hi2 - hi3 - ma2 - ma3 - qi2 - qi3 - sp2 - sp3 - su2 - su3 - ws2 - ws3l - ws3s -end -@enum State PA GA NC MI AZ WI NV - -struct PollData - biden_support::Union{Float64, Missing} - trump_support::Union{Float64, Missing} - sample_size::Union{Int, Missing} -end - -struct MonthlyData - data::Dict{State, Vector{PollData}} - MonthlyData() = new(Dict(s => [PollData(missing, missing, missing)] for s in instances(State))) -end - -struct MasterPolls - data::Dict{Pollster, Dict{Month, MonthlyData}} - MasterPolls() = new(Dict{Pollster, Dict{Month, MonthlyData}}()) -end - -master_polls = MasterPolls() - -# Add poll data for a specific pollster, month, and state -master_polls.data[bi2] = Dict( - mar => MonthlyData(), - apr => MonthlyData(), - may => MonthlyData(), - jun => MonthlyData(), - jul => MonthlyData(), - aug => MonthlyData(), - sep => MonthlyData(), - oct => MonthlyData(), - nov => MonthlyData() -) - -""" -# Add poll data for a specific pollster, month, and state -master_polls.data[bi2][mar].data[PA] = [ - PollData(0.40, 0.46, 1305), - PollData(0.45, 0.45, 887), - PollData(0.56, 0.46, 5200) -] -""" - -# Access poll data for pollster bi2, month mar, and state PA - -# pa_data = master_polls.data[bi2][mar].data[PA] - -using Serialization - -""" -# Serialize and save the master_polls object to a file -serialize("master_polls.bin", master_polls) - -# Load the serialized master_polls object from the file -loaded_master_polls = deserialize("master_polls.bin") -""" - -""" - save_master_polls(master_polls::MasterPolls, filename::String) - -Serialize and save the `master_polls` object to a file specified by `filename`. - -# Arguments -- `master_polls::MasterPolls`: The `MasterPolls` object to be serialized and saved. -- `filename::String`: The name of the file to save the serialized data. - -# Examples -```julia -save_master_polls(master_polls, "master_polls.bin") -""" -function save_master_polls(master_polls::MasterPolls, filename::String) - open(filename, "w") do f - serialize(f, master_polls) - end - println("Master polls data saved to $filename") -end - -""" - load_master_polls(filename::String) - -Load the serialized MasterPolls object from a file specified by filename. -Arguments - -# Arguments - - - `filename::String`: The name of the file containing the serialized data. - -# Returns - - MasterPolls: The deserialized MasterPolls object. - -# Examples -```julia -codeloaded_master_polls = load_master_polls("master_polls.bin") -""" -function load_master_polls(filename::String) - master_polls = open(filename, "r") do f - deserialize(f) - end - println("Master polls data loaded from $filename") - return master_polls -end - - -""" - enter_data(pollster::Pollster, month::Month, state::State) - -Generate a template for entering poll data into the `master_polls` object. - -The template includes the appropriate `master_polls.data` syntax with placeholders for the `biden_support`, `trump_support`, and `sample_size` values in a single `PollData` entry. - -# Arguments -- `pollster::Pollster`: The pollster enum value for which the data is being entered. -- `month::Month`: The month enum value for which the data is being entered. -- `state::State`: The state enum value for which the data is being entered. - -# Examples -```julia -enter_data(bi2, mar, PA) -# Output -master_polls.data[bi2][mar].data[PA] = [ - PollData( , , ) -] -""" -function enter_data(pollster::Pollster, month::Month, state::State) - println("master_polls.data[$pollster][$month].data[$state] = [PollData( , , ),]") -end - -""" - generate_templates(month::Month) - -Generate templates for entering poll data into the `master_polls` object for all combinations of `Pollster` and `State` for a given `Month`. - -This function iterates over the `Pollster` and `State` enums and calls the `enter_data` function for each combination, using the provided `month` argument. - -# Arguments -- `month::Month`: The month enum value for which the templates are being generated. - -# Examples -```julia -generate_templates(mar) - -This will generate templates for all combinations of Pollster and State for the month of March like this - -master_polls.data[bi2][mar].data[PA] = [ - PollData( , , ) -] … -""" - -function generate_templates(month::Month) - templates = "" - for pollster in instances(Pollster) - for state in instances(State) - templates *= "master_polls.data[$pollster][$month].data[$state] = [\n PollData( , , )\n]\n\n" - end - end - InteractiveUtils.clipboard(templates) - println("Templates copied to clipboard.") -end - diff --git a/_assets/scripts/debris/polls copy.jl b/_assets/scripts/debris/polls copy.jl deleted file mode 100644 index e875c67..0000000 --- a/_assets/scripts/debris/polls copy.jl +++ /dev/null @@ -1,109 +0,0 @@ -using BSON: @load, @save -using BSON -using Colors -using Combinatorics -using CSV -using DataFrames -using Distributions -using Format -using HTTP -using GLMakie -using KernelDensity -using LinearAlgebra -using MCMCChains -using Missings -using PlotlyJS -using Plots -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing - -# -# struct Poll -# question::String -# response::String -# end - -@enum State PA GA NC MI AZ WI NV -STATE = State -@enum Month mar apr may jun jul jul2 aug1 aug2 sep1 sep2 oct1 oct2 fin -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cj - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ny2 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - us - wa2 - wa3 - ws - wsl - wss - yg -end - -prior_month = "sep1" -mon = sep2 -MON = "sep2" -Mon = "sep2" -st = "AZ" -ST = AZ - -#@load "../objs/jul_polls.bson" months -margins = CSV.read("../objs/margins.csv", DataFrame) -margin = first(margins[margins.st .== st, :pct]) -include("polls_head.jl") -#prior_poll = BSON.load("../objs/"*"$st"*"_"*"$prior_month"*"_p_sample.bson") -prior_poll = BSON.load("../objs/new_prior.bson") -#@load "../objs/"*"$MON"*"_polls.bson" months # comes up empty -margin = first(margins[margins.st .== st, :pct]) - -#current_month = remove_empties(months[mon]) -# -include("polls_foot.jl") - - diff --git a/_assets/scripts/debris/polls.jl b/_assets/scripts/debris/polls.jl deleted file mode 100644 index 1bfa3b9..0000000 --- a/_assets/scripts/debris/polls.jl +++ /dev/null @@ -1,60 +0,0 @@ -using DataFrames -using Dates - -polls = DataFrame( - state = String[], - biden = Float64[], - trump = Float64[], - n = Int64[], - type = String[], - base_moe = Float64[], - house_moe = Float64[], - organization = String[], - url_hash = String[], - start = Date[], - finish = Date[] -) - -# example -hashed = shorten_url("https://pro-assets.morningconsult.com/wp-uploads/2024/03/Bloomberg_2024-Election-Tracking-Wave-6.pdf") - -push!(polls, ["Arizona", - 0.43, - 0.48, - 796, - "TK", - 0.03, - 0.0, - "Bloomberg", - hashed, - Date(2024, 3,8), - Date(2024, 3, 5)]) - - - - -# Create an empty DataFrame to store the URLs and their hash keys -urlhash = DataFrame(original_url = String[], hash_key = String[]) - -# Function to generate a unique hash key for a URL -function generate_hash_key(url) - hash_key = bytes2hex(SHA.sha256(url)) - return hash_key[1:8] # Use the first 8 characters of the hash as the key -end - -# Function to shorten a URL and store it in the DataFrame -function shorten_url(url) - hash_key = generate_hash_key(url) - push!(urlhash, (original_url = url, hash_key = hash_key)) - return hash_key -end - -# Function to retrieve the original URL from the DataFrame using the hash key -function expand_url(hash_key) - row = filter(row -> row.hash_key == hash_key, urlhash) - if nrow(row) > 0 - return row[1, :original_url] - else - return "URL not found" - end -end diff --git a/_assets/scripts/debris/polls_foot.jl b/_assets/scripts/debris/polls_foot.jl deleted file mode 100644 index 338fee5..0000000 --- a/_assets/scripts/debris/polls_foot.jl +++ /dev/null @@ -1,50 +0,0 @@ -consolidated_polls = consolidate_polls(current_month) -support = calculate_support(consolidated_polls,ST) -num_wins = support[1] -num_votes = support[3] -poll_posterior = prior_poll -posterior_mean = mean(poll_posterior[:deep][:p]) -posterior_var = var(poll_posterior[:deep][:p]) -prior_alpha = posterior_mean * - (posterior_mean * - (1 - posterior_mean) / - posterior_var - 1) -prior_beta = (1 - posterior_mean) * - (posterior_mean * - (1 - posterior_mean) / - posterior_var - 1) -prior_dist = Beta(prior_alpha, prior_beta) -model = poll_model(num_votes, num_wins, prior_dist) -sampler = NUTS(0.65) -num_samples = 10000 -num_chains = 4 -init_params = [Dict(:p => 0.5)] -chain = sample(poll_model(num_votes, num_wins, prior_dist), - sampler, num_samples, init_params=init_params) -p_intv = quantile(chain[:p], [0.025, 0.975]) -p_mean = summarystats(chain)[1,:mean] -p_mcse = summarystats(chain)[1,:mcse] -p_rhat = summarystats(chain)[1,:rhat] -p_df = DataFrame(median = median(chain[:p]), - mean = mean(chain[:p]), - mode = mode(chain[:p]), - min = min(chain[:p]), - max = max(chain[:p]), - q025 = p_intv[1], - q975 = p_intv[2]), -p_samples = chain[:p] -p_vec = vec(p_samples) -kde_result = kde(p_vec)\ -posterior_interval = p_intv -fig = draw_density() -save(("../img/models/"*"$st"*"_"*"$mon"*".png"), fig) -deep = deepcopy(chain) -@save ("../objs/"*"$st"*"_"*"$mon"*"_p_sample.bson") deep -out = Vector(p_df[1,:]) -out = round.(out,digits = 4) -p_df[1,:] = out -pretty_table(p_df,backend=Val(:html),show_subheader = false) -chain -summarystats(chain) -autocor(chain) -hpd(chain) \ No newline at end of file diff --git a/_assets/scripts/debris/polls_head.jl b/_assets/scripts/debris/polls_head.jl deleted file mode 100644 index 18021bc..0000000 --- a/_assets/scripts/debris/polls_head.jl +++ /dev/null @@ -1,205 +0,0 @@ -const states = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const FLAGRED = "rgb(178, 34, 52)" -const FLAGBLUE = "rgb( 60, 59, 110)" -const PURPLE = "rgb(119, 47, 81)" -const GREENBAR = "rgb( 47, 119, 78)" -const LORANGE = "rgb(225, 170, 110)" - -#------------------------------------------------------------------ -struct Poll - harris_support::Float64 - trump_support::Float64 - sample_size::Int64 -end -#------------------------------------------------------------------ -Month_names = Dict( - "mar" => "March", - "apr" => "April", - "may" => "May", - "jun" => "June", - "jul" => "July", - "jul2" => "July-post", - "aug1" => "early August", - "aug2" => "late August", - "sep1" => "early September", - "sep2" => "late September", - "oct1" => "early October", - "oct2" => "late October", - "fin" => "final polling") -#------------------------------------------------------------------ - -#------------------------------------------------------------------ -""" -filter_empty_entries(dict::Dict{Pollster, Vector{Poll}}) -> Dict{Pollster, Vector{Poll}} - -Filter out entries in a dictionary where the values are empty vectors. - -# Arguments -- `dict::Dict{Pollster, Vector{Poll}}`: A dictionary where the keys are of type `Pollster` and the values are vectors of type `Poll`. - -# Returns -- `Dict{Pollster, Vector{Poll}}`: A new dictionary containing only the entries from the input dictionary where the vectors are not empty. - -# Description -The `filter_empty_entries` function iterates over each key-value pair in the provided dictionary. It constructs a new dictionary that includes only those entries where the value (a vector of `Poll` objects) is not empty. - -# Example -```julia -# Define types for the example -struct Pollster - name::String -end - - - -# Create a dictionary with some empty and non-empty vectors -pollster1 = Pollster("Pollster A") -pollster2 = Pollster("Pollster B") -poll1 = Poll("Question 1", "Response 1") -poll2 = Poll("Question 2", "Response 2") - -dict = Dict( - pollster1 => [poll1, poll2], - pollster2 => [] -) - -# Filter out entries with empty vectors -filtered_dict = filter_empty_entries(dict) -println(filtered_dict) -# Output: -# Dict{Pollster, Vector{Poll}} with 1 entry: -# Pollster("Pollster A") => Poll[Poll("Question 1", "Response 1"), Poll("Question 2", "Response 2")] -""" -function remove_empties(the_month::Dict) - Dict(state => Dict(pollster => polls for (pollster, polls) in pollsters - if !isempty(polls)) for (state, pollsters) in the_month) -end -#------------------------------------------------------------------ -function process_polls(polls::Vector{Poll}) - result = Int64.(collect(collect([(p.harris_support, p.sample_size) for p in polls])[1])) - return [Int64(floor(result[1] / 100 * result[2])), result[2]] -end -#------------------------------------------------------------------ - -""" - draw_density() - -Draw a density plot of the parameter `p` with a shaded credible interval. - -# Returns -- `fig`: A `Figure` object containing the density plot. - -# Description -This function creates a density plot of the parameter `p` using the `kde_result` and `p_vec` variables, -which are assumed to be available in the current scope. The plot includes a shaded region representing -the credible interval specified by `posterior_interval`. - -The density curve is plotted in green (`#a3b35c`) with a stroke width of 8. The shaded credible interval -is filled in orange (`#e1aa6e`). - -The x-axis label is set to "p", the y-axis label is set to "Density", and the plot title is set to -"Density Plot of p for $ST", where `$ST` is a string variable assumed to be available in the current scope. - -The x-axis limits are set to the extrema of `p_vec`, and the y-axis limits are set to start from 0. - -A legend is added to the plot using `axislegend(ax)`. - -# Example -```julia -# Assume kde_result, p_vec, posterior_interval, and ST are available in the current scope -fig = draw_density() -""" -function draw_density() - # Create a new figure with specified resolution - fig = Figure(size = (600, 400)) - - # Add an axis to the figure - ax = Axis(fig[1, 1], xlabel = "Likelihood of Harris win", ylabel = "Number of draws", title = "Model: Harris results in $ST with polling through " * Month_names[Mon]) - - # Plot the full density curve - lines!(ax, kde_result.x, kde_result.density, color = "#a3b35c", linewidth = 3, strokewidth = 4, strokecolor = GREENBAR, label = "Draws") - - # Find the indices corresponding to the posterior interval - indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) - - # Extract the x and y values within the posterior interval - x_region = kde_result.x[indices] - y_region = kde_result.density[indices] - - # Fill the specific area under the curve - band!(ax, x_region, fill(0, length(x_region)), y_region, color = (LORANGE), label = "Credible Interval") - - # Find the y-value corresponding to the specified x-value - y_value = kde_result.density[argmin(abs.(kde_result.x .- margin))] - - # Add a vertical line at the specified x-value from 0 to the y-value - vlines!(ax, [margin], [0, y_value], color = FLAGBLUE, linestyle = :dash, linewidth = 4, label = "2020 Actual") - - # Add a legend to the plot - axislegend(ax) - - # Adjust the plot limits to fit the density line - Makie.xlims!(ax, extrema(p_vec)) - Makie.ylims!(ax, 0, nothing) - - # Display the figure - fig -end -#------------------------------------------------------------------ -@model function poll_model(num_votes::Int64, num_wins::Int64, prior_dist::Distribution) - # Define the prior using the informed prior distribution - p ~ prior_dist - # Define the likelihood with additional uncertainty - num_wins ~ Binomial(num_votes, p) -end - -function consolidate_polls(current_month) - consolidated = Dict{State, NamedTuple{(:harris_support, :trump_support, :sample_size), Tuple{Float64, Float64, Int64}}}() - - for (state, pollsters) in current_month - total_harris = 0.0 - total_trump = 0.0 - total_sample = 0 - - for (_, polls) in pollsters - for poll in polls - total_harris += poll.harris_support * poll.sample_size - total_trump += poll.trump_support * poll.sample_size - total_sample += poll.sample_size - end - end - - avg_harris = total_harris / total_sample - avg_trump = total_trump / total_sample - - consolidated[state] = (harris_support = avg_harris, trump_support = avg_trump, sample_size = total_sample) - end - - return consolidated -end - - poll_data = consolidate_polls[state] - - harris_votes = floor(Int, poll_data.sample_size * (poll_data.harris_support / 100)) - trump_votes = floor(Int, poll_data.sample_size * (poll_data.trump_support / 100)) - - return ( - harris_votes = harris_votes, - trump_votes = trump_votes, - sample_size = poll_data.sample_size - ) -end - -function calculate_support(consolidated_polls, state) - poll_data = consolidated_polls[state] - - harris_votes = floor(Int, poll_data.sample_size * (poll_data.harris_support / 100)) - trump_votes = floor(Int, poll_data.sample_size * (poll_data.trump_support / 100)) - - return ( - harris_votes = harris_votes, - trump_votes = trump_votes, - sample_size = poll_data.sample_size - ) -end - diff --git a/_assets/scripts/debris/prep.jl b/_assets/scripts/debris/prep.jl deleted file mode 100644 index dc8a5ce..0000000 --- a/_assets/scripts/debris/prep.jl +++ /dev/null @@ -1,117 +0,0 @@ -#base = CSV.read("./objs/2020vote.csv", DataFrame) -using HTTP -gist_url = "https://gist.githubusercontent.com/technocrat/18810a6c1c3d6d2c443876f06df0ad28/raw/a4b7ebf2d6429c5224417a133caa61dedfaa433e/2020vote.csv" - -# Fetch the CSV data from the Gist URL -csv_data = HTTP.get(gist_url).body - -# Read the CSV data into a DataFrame -base = CSV.read(IOBuffer(csv_data), DataFrame) - -data = Dict( - "Arizona" => base[3,7], - "Georgia" => base[11,7], - "Wisconsin" => base[55,7], - "Michigan" => base[25,7], - "Nevada" => base[34,7], - "North Carolina" => base[39,7], - "Pennsylvania" => base[44,7] -) - -""" -margins = Dict( - "Arizona" => base[3,6], - "Georgia" => base[11,6], - "Wisconsin" => base[55,6], - "Michigan" => base[25,6], - "Nevada" => base[34,6], - "North Carolina" => base[39,6], - "Pennsylvania" => base[44,6] -) -""" - -swing_col = collect(values(data)) -# swing_pop = collect(values(margins)) -# subtract the number of swing states' electoral votes -blue = sum(base.biden_col) - sum(collect(swing_col)) -red = sum(base.trump_col) - sum(collect(swing_col)) -biden_win = victory - blue -trump_win = victory - blue -target = impass -results = find_combinations(target) - -# Function to process each element of updated_results -function process_result(vec, key) - state_names = join(vec, ", ") - state_count = length(vec) - state_sum = sum(data[state] for state in vec) - margin_sum = sum(data[state] for state in vec) - return (key = key, st = state_names, count = state_sum, num_states = - state_count, votes = margin_sum) -end - -# Create a vector that maps indices to state names -state_mapping = collect(keys(data)) - -# Function to replace values in a vector with corresponding state names -function replace_with_states(vec) - return [join(state_mapping[v]) for v in vec] -end - -# Create a new named tuple with updated values -updated_results = (map(replace_with_states, results[1]), - map(replace_with_states, results[2]), - map(replace_with_states, results[3])) - -# Apply process_result function to each element of updated_results with separate keys -outcome_data = vcat( - x , - process_result.(updated_results[2], "tie"), - process_result.(updated_results[3], "win") -) - -# Create the outcome dataframe from the processed data -outcome = DataFrame(outcome_data) -outcome.biden = outcome.count .+ blue -outcome.trump = college .- outcome.biden -outcome.electoral = outcome.biden .+ outcome.trump -outcome.check = if(outcome.electoral .- college == 0, true) - else false - end -all(outcome.check .== true) -sort!(outcome,:count) - - - -if outcome.biden < tie - outcome.result = "Trump" - elseif outcome.bidden == tie - outcome.result = "Trump" - else - outcome.result = "Harris" - end -end - -# Assuming `outcome` is a DataFrame with a column named `biden` -# and you want to create a new column `result` of type String - -using DataFrames - -# Function to determine the result based on the value of `biden` -function determine_result(biden_value) - if biden_value == 269 - return "tie" - elseif biden_value < 269 - return "Trump" - else - return "Harris" - end -end - -# Apply the function to each row of the dataframe and create the `result` column -outcome.result = determine_result.(outcome.biden) - -# Ensure the `result` column is of type String -outcome.result = string.(outcome.result) - -# The `outcome` DataFrame now has a new column `result` with the appropriate values diff --git a/_assets/scripts/debris/reset_prior.jl b/_assets/scripts/debris/reset_prior.jl deleted file mode 100644 index 8934a4d..0000000 --- a/_assets/scripts/debris/reset_prior.jl +++ /dev/null @@ -1,236 +0,0 @@ -@enum State PA GA NC MI AZ WI NV -@enum Month mar apr may jun jul jul2 aug sep oct -#------------------------------------------------------------------ -STATE = State -prior_month = "jul" -mon = jul2 -MON = "jul2" -Mon = "jul2" -st = "PA" -ST = PA -#------------------------------------------------------------------ -using BSON: @load, @save -using BSON -using Colors -using Combinatorics -using CSV -using DataFrames -using Distributions -using Format -using HTTP -using GLMakie -using KernelDensity -using LinearAlgebra -using MCMCChains -using Missings -using PlotlyJS -using Plots -using PrettyTables -using Printf -using Serialization -using Statistics -using StatsPlots -using Turing -#------------------------------------------------------------------ -struct Poll - biden_support::Float64 - trump_support::Float64 - sample_size::Int64 -end -#------------------------------------------------------------------ -@enum Pollster begin - ag - aj - am - bi2 - bi3 - bl2 - bl3 - cb2 - cb3 - cn2 - cn3 - ea - ec2 - ec3 - ep - eu - fm2 - fm3 - fo2 - fo3 - hi2 - hi3 - hp - ia - ma2 - ma3 - mi2 - mi3 - mq - mr2 - mr3 - ns - pp - ny - qi2 - qi3 - rr - si2 - si3 - sp2 - sp3 - su2 - su3 - tr - wa2 - wa3 - ws - wsl - wss - yg -end -#------------------------------------------------------------------ -Month_names = Dict( - "mar" => "March", - "apr" => "April", - "may" => "May", - "jun" => "June", - "jul" => "July", - "jul2" => "July-post", - "aug" => "August", - "sep1" => "early September", - "sep2" => "late September", - "oct1" => "early October", - "oct2" => "late October", - "fin" => "final polls") - -#------------------------------------------------------------------ -const states = ["NV", "WI", "AZ", "GA", "MI", "PA", "NC"] -const FLAGRED = "rgb(178, 34, 52)" -const FLAGBLUE = "rgb( 60, 59, 110)" -const PURPLE = "rgb(119, 47, 81)" -const GREENBAR = "rgb( 47, 119, 78)" -const LORANGE = "rgb(225, 170, 110)" -#------------------------------------------------------------------ -function draw_density() - # Create a new figure with specified resolution - fig = Figure(size = (600, 400)) - - # Add an axis to the figure - ax = Axis(fig[1, 1], xlabel = "Likelihood of Harris win", ylabel = "Number of draws", title = "Model: Harris results in $ST from assumed tie and polling through " * Month_names[Mon]) - # Plot the full density curve - lines!(ax, kde_result.x, kde_result.density, color = "#a3b35c", linewidth = 3, strokewidth = 4, strokecolor = GREENBAR, label = "Draws") - - # Find the indices corresponding to the posterior interval - indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) - - # Extract the x and y values within the posterior interval - x_region = kde_result.x[indices] - y_region = kde_result.density[indices] - - # Fill the specific area under the curve - band!(ax, x_region, fill(0, length(x_region)), y_region, color = (LORANGE), label = "Credible Interval") - - # Find the y-value corresponding to the specified x-value - y_value = kde_result.density[argmin(abs.(kde_result.x .- margin))] - - # Add a vertical line at the specified x-value from 0 to the y-value - vlines!(ax, [margin], [0, y_value], color = FLAGBLUE, linestyle = :dash, linewidth = 4, label = "2020 Actual") - - # Add a legend to the plot - axislegend(ax) - - # Adjust the plot limits to fit the density line - Makie.xlims!(ax, extrema(p_vec)) - Makie.ylims!(ax, 0, nothing) - - # Display the figure - fig -end -#------------------------------------------------------------------ -function process_polls(polls::Vector{Poll}) - result = Int64.(collect(collect([(p.biden_support, p.sample_size) for p in polls])[1])) - return [Int64(floor(result[1] / 100 * result[2])), result[2]] -end -#------------------------------------------------------------------ -function remove_empties(the_month::Dict) - Dict(state => Dict(pollster => polls for (pollster, polls) in pollsters - if !isempty(polls)) for (state, pollsters) in the_month) -end -#------------------------------------------------------------------ -# Define the new model with additional binomial uncertainty -@model function updated_model(y, n) - # Use the existing chain as a prior for p - p ~ Normal(mean(p_prior_flat), std(p_prior_flat)) - - # Ensure p is within [0, 1] - p_clamped = clamp(p, 0, 1) - - # Add additional binomial uncertainty - q ~ Beta(2, 2) # Weakly informative prior for additional uncertainty - - # Ensure the final probability is within [0, 1] - prob = clamp(q * p_clamped, 0, 1) - - # Likelihood - y ~ Binomial(n, prob) -end -#------------------------------------------------------------------ -margins = CSV.read("../objs/margins.csv", DataFrame) -@load "../objs/"*"$MON"*"_polls.bson" months -prior_poll = BSON.load("../objs/"*"$st"*"_"*"$prior_month"*"_p_sample.bson") -#------------------------------------------------------------------ -margin = first(margins[margins.st .== st, :pct]) -current_month = remove_empties(months[mon]) -#------------------------------------------------------------------ -# Extract the relevant data from the existing chain -prior_chain = prior_poll[:deep] -p_prior = Array(prior_chain[:p]) -# Total results of current polls -processed_polls = Dict(state => - Dict(pollster => - process_polls(polls) for (pollster, polls) in pollsters) - for (state, pollsters) in current_month) - -processed_polls_totals = Dict(state => - Dict("num_wins" => - sum(first(values(polls)) for polls in values(pollsters)), - "num_votes" => - sum(last(values(polls)) for polls in values(pollsters))) - for (state, pollsters) in processed_polls) - -num_wins = processed_polls_totals[ST]["num_wins"] -num_votes = processed_polls_totals[ST]["num_votes"] -p_intv = quantile(chain[:p], [0.025, 0.975]) -p_mean = summarystats(chain)[1,:mean] -p_mcse = summarystats(chain)[1,:mcse] -p_rhat = summarystats(chain)[1,:rhat] -p_df = DataFrame(median = median(chain[:p]), - mean = mean(chain[:p]), - mode = mode(chain[:p]), - q025 = p_intv[1], - q975 = p_intv[2], - min = min(chain[:p], - max = max(chain[:p]) - -p_samples = chain[:p] -p_vec = vec(p_samples) -kde_result = kde(p_vec) - -deep = deepcopy(chain) - -posterior_interval = p_intv -fig = draw_density() - -out = Vector(p_df[1,:]) -out = round.(out,digits = 4) -p_df[1,:] = out -pretty_table(p_df,backend=Val(:html),show_subheader = false) -chain -summarystats(chain) -autocor(chain) -hpd(chain) -#------------------------------------------------------------------ -save(("../img/models/"*"$st"*"_"*"$mon"*".png"), fig) -@save ("../objs/"*"$st"*"_"*"$mon"*"_p_sample.bson") deep diff --git a/_assets/scripts/debris/ribbon.jl b/_assets/scripts/debris/ribbon.jl deleted file mode 100644 index 1ab1a8f..0000000 --- a/_assets/scripts/debris/ribbon.jl +++ /dev/null @@ -1,121 +0,0 @@ -using Plots - -const BIDEN_LOW = 42 -const BIDEN_POINT = 48 -const BIDEN_HIGH = 54 -const TRUMP_LOW = 32 -const TRUMP_POINT = 38 -const TRUMP_HIGH = 44 -const SPACE = " " -const NL = "\n" - -const NEW_LINEWIDTH = 10 * 6 # bar height - -state = "PA\n" -poll = "Franklin-Marshall" -date = "Late March" -type = ["Two-way","Three-way"] -N = [431,430] -space = " " -title2way = poll * SPACE * date * SPACE * type[1] * SPACE * NL * state * "Preference" * SPACE * "(N =" * SPACE * string(N[1]) *")" -title3way = poll * SPACE * date * SPACE * type[2] * SPACE * state * "Preference" * SPACE * "(N =" * SPACE * string(N[2]) *")" - -# Define the x-axis ticks and their labels -const X_TICKS = [TRUMP_LOW, BIDEN_LOW, TRUMP_POINT, BIDEN_POINT,BIDEN_HIGH] -const X_TICK_LABELS = string.(X_TICKS) - -# Create the horizontal rectangle chart with increased linewidth and specified x-axis ticks and labels -p = plot(legend=:topright, xlims=(TRUMP_LOW, BIDEN_HIGH), ylims=(0, 0.1), - xticks=(X_TICKS, X_TICK_LABELS), size=(600, 400)) - -# Plotting the segments -plot!([TRUMP_LOW, TRUMP_HIGH], [0, 0], linewidth=NEW_LINEWIDTH, linecolor=:red, label="Trump") -plot!([BIDEN_LOW, BIDEN_HIGH], [0, 0], linewidth=NEW_LINEWIDTH, linecolor=:blue, label="Harris") -plot!([TRUMP_HIGH, BIDEN_LOW], [0, 0], linewidth=NEW_LINEWIDTH, linecolor=:purple, label="Overlap") - -# Add chart title and labels -title!(fittle) -xlabel!("Approval Rating") - -# Show the plot -plot!(p) - -""" - create_ribbon_chart(result, STATE, TYPE_POLL, POLLSTER; filename=nothing) - -Create a ribbon chart visualization to display the ranges and overlap of poll results for two candidates. - -# Arguments -- `result`: A tuple containing two ranges (vectors) representing the poll result ranges for the two candidates. -- `STATE::String`: The name of the state for which the poll results are being displayed. -- `TYPE_POLL::String`: The type of poll being displayed (e.g., "General Election", "Primary", etc.). -- `POLLSTER::String`: The name of the pollster or organization that conducted the poll. -- `filename::Union{String, Nothing}=nothing`: An optional filename to save the plot as an image file. - -# Returns -- `Plots.Plot`: The ribbon chart plot object. - -# Notes -- The function calculates the overlap range and amount between the two candidates' poll result ranges. -- It creates a ribbon chart plot using the Plots.jl package, with the candidates' ranges represented as horizontal bars and the overlap range represented as a third bar. -- The candidate names, overlap amount, and poll details (state, type, and pollster) are annotated on the plot. -- The x-axis ticks are set to the unique values in the combined ranges of the two candidates. -- If a `filename` is provided, the plot is saved as an image file with the specified name. - -# Examples -```julia -# Assuming `result` is a tuple containing two ranges (vectors) for Harris and Trump -biden_range = [46.0, 50.0] -trump_range = [45.0, 49.0] -result = (biden_range, trump_range) - -ribbon_chart = create_ribbon_chart(result, "Florida", "General Election", "ABC News/Washington Post") -display(ribbon_chart) - -# To save the plot as an image file -ribbon_chart = create_ribbon_chart(result, "Florida", "General Election", "ABC News/Washington Post", filename="fl_poll.png") -""" -function create_ribbon_chart(result, STATE, TYPE_POLL, POLLSTER; filename=nothing) - biden_range = result[1] - trump_range = result[2] - - # Calculate the overlap range - overlap_start = max(biden_range[1], trump_range[1]) - overlap_end = min(biden_range[end], trump_range[end]) - overlap_range = [overlap_start, overlap_end] - - # Calculate the overlap amount - overlap_amount = overlap_range[end] - overlap_range[1] - - # Create the ribbon chart - p = plot(size=(800, 300), legend=false, grid=false, yaxis=false, bottom_margin=10Plots.mm, top_margin=15Plots.mm) - - # Plot Harris's and Trump's ranges - plot!([biden_range[1], biden_range[end]], [1.2, 1.2], linewidth=10, color=FLAGBLUE) - plot!([trump_range[1], trump_range[end]], [0.2, 0.2], linewidth=10, color=FLAGRED) - - # Plot the overlap range - plot!([overlap_range[1], overlap_range[end]], [0.7, 0.7], linewidth=10, color=PURPLE) - - # Add candidate names and overlap amount annotation - annotate!((biden_range[1] + biden_range[end]) / 2, 1.2, text("BIDEN", :center, 12, :white)) - annotate!((trump_range[1] + trump_range[end]) / 2, 0.2, text("TRUMP", :center, 12, :white)) - annotate!((overlap_range[1] + overlap_range[end]) / 2, 0.7, text("$(overlap_amount) pts", :center, 12, :white)) - - # Set tick positions and labels - tick_values = sort(unique(vcat(biden_range, trump_range))) - xticks!(tick_values, string.(tick_values)) - - # Add title - title!("$STATE, $TYPE_POLL by $POLLSTER") - - # Adjust the y-axis limits - ylims!((-0.5, 2.0)) - - # Save the plot to a file if a filename is provided - if filename !== nothing - savefig(p, filename) - end - - return p - end diff --git a/_assets/scripts/debris/ribbon_entry.jl b/_assets/scripts/debris/ribbon_entry.jl deleted file mode 100644 index bf4e9e3..0000000 --- a/_assets/scripts/debris/ribbon_entry.jl +++ /dev/null @@ -1,93 +0,0 @@ -ST = \"NC\" - -POLLSTER = \"Big Data\" - -TYPE_POLL = \"2-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"Bullfinch\" - -TYPE_POLL = \"2-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"Bloomberg/Morning Consult\" - -TYPE_POLL = \"2-way\" -result = spread(43, 49, 699) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way\" -result = spread(39, 43, 699) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"Emerson College\" - -TYPE_POLL = \"2-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"CBS\" - -TYPE_POLL = \"2-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"High Point\" - -TYPE_POLL = \"2-way\" -result = spread(42, 45, 1016) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"Quinnipiac\" - -TYPE_POLL = \"2-way\" -result = spread(46, 48, 1401) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way\" -result = spread(38, 41, 1401) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"Spry\" - -TYPE_POLL = \"2-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"Marist\" - -TYPE_POLL = \"2-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way\" -result = spread(x, y, z) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -POLLSTER = \"WSJ\" - -TYPE_POLL = \"2-way\" -result = spread(45, 48, 60) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way (short)\" -result = spread(34, 42, 600) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - -TYPE_POLL = \"3-way (long)\" -result = spread(40, 45, 600) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/save.jl b/_assets/scripts/debris/save.jl deleted file mode 100644 index 2adca10..0000000 --- a/_assets/scripts/debris/save.jl +++ /dev/null @@ -1,3 +0,0 @@ -save(("../img/models/"*"$st"*"_"*"$mon"*".png"), fig) -deep = deepcopy(chain) -@save ("../objs/"*"$st"*"_"*"$mon"*"_p_sample.bson") deep diff --git a/_assets/scripts/debris/savit.bson b/_assets/scripts/debris/savit.bson deleted file mode 100644 index b162888..0000000 Binary files a/_assets/scripts/debris/savit.bson and /dev/null differ diff --git a/_assets/scripts/debris/scene_tables.jl b/_assets/scripts/debris/scene_tables.jl deleted file mode 100644 index 3df787e..0000000 --- a/_assets/scripts/debris/scene_tables.jl +++ /dev/null @@ -1,36 +0,0 @@ - -h1 = "Harris wins" -h2 = "Tie" -h3 = "Trump wins" - - -const STATES = ["NV", "MI", "WI", "NC", "AZ", "PA", "GA"] -const FULL = ["Nevada","Michigan","Wisconsin","North Carolina","Arizona","Pennsylvania","Georgia"] - -state_dict = Dict(zip(STATES, FULL)) - -new_names = [ - "States won by Harris ", - "Electoral Votes", - "Harris Votes", - "Trump Votes", - "Result"] - -# ST = "WI" - -h1 - -pretty_table(outcome[(occursin.(ST, outcome.combo)) .& (outcome.result .== "Harris"), :], backend = Val(:html), header = new_names, standalone = false) - -h2 - -pretty_table(outcome[(occursin.(ST, outcome.combo)) .& (outcome.result .== "Tie"), :], backend = Val(:html), header = new_names, standalone = false) - -h3 - -pretty_table(outcome[(occursin.(ST, outcome.combo)) .& (outcome.result .== "Trump"), :], backend = Val(:html), header = new_names, standalone = false) - -h4 = "Harris wins without $state_dict[ST]" - -pretty_table(outcome[.!(occursin.(ST, outcome.combo)) .& (outcome.result .== "Harris"), :], backend = Val(:html), header = new_names, standalone = false) - diff --git a/_assets/scripts/debris/simuation.jl b/_assets/scripts/debris/simuation.jl deleted file mode 100644 index baa9211..0000000 --- a/_assets/scripts/debris/simuation.jl +++ /dev/null @@ -1,94 +0,0 @@ -using DataFrames -using Distributions -using Statistics - -include("constants.jl") -# needs work -""" - simulate(scenarios::Int64, rv::Int64, biden_pop::Int64, trump_pop::Int64) - -Simulate an election scenario based on the given parameters. - -# Arguments -- `scenarios::Int64`: The number of scenarios to simulate. -- `rv::Int64`: The standard deviation for the random variation in vote counts. -- `biden_pop::Int64`: The base vote count for Biden. -- `trump_pop::Int64`: The base vote count for Trump. - -# Returns -- `simulation_results::Dict`: A dictionary containing the simulation results. - - `base_votes`: The base vote distribution used in the simulation. - - `mean_votes`: The mean votes for each candidate based on the simulated scenarios. - - `median_votes`: The median votes for each candidate based on the simulated scenarios. - - `credible_intervals`: The 95% credible intervals for each candidate's vote count. - -# Example -```julia -biden_pop = 80000000 -trump_pop = 74000000 -num_scenarios = 1000 -standard_deviation = 10000 - -results = simulate(num_scenarios, standard_deviation, biden_pop, trump_pop) -# Example usage -biden_pop = 80000000 -trump_pop = 74000000 -num_scenarios = 1000 -standard_deviation = 10000 - -results = simulate(num_scenarios, standard_deviation, biden_pop, trump_pop) - -# Access the simulation results -base_votes = results["base_votes"] -mean_votes = results["mean_votes"] -median_votes = results["median_votes"] -credible_intervals = results["credible_intervals"] - -# Print the simulation results -println("Base Votes: ", base_votes) -println("Mean Votes: ", mean_votes) -println("Median Votes: ", median_votes) -println("95% Credible Intervals: ", credible_intervals) -""" -function simulate(scenarios::Int64, rv::Int64, biden_pop::Int64, trump_pop::Int64) - # Base vote distribution from the previous election - base_votes = [biden_pop, trump_pop] - - # Simulate multiple scenarios - num_scenarios = scenarios - simulated_votes = zeros(num_scenarios, 2) - - for i in 1:num_scenarios - # Account for random variation - random_variation = rand(Normal(0, rv), 2) - - # Adjust the base vote distribution - adjusted_votes = base_votes + random_variation - - simulated_votes[i, :] = adjusted_votes - end - - # Analyze the results - mean_votes = mean(simulated_votes, dims=1) - median_votes = median(simulated_votes, dims=1) - credible_intervals = [quantile(simulated_votes[:, i], [0.025, 0.975]) for i in 1:size(simulated_votes, 2)] - - # Create a dictionary to store the simulation results - simulation_results = Dict( - "base_votes" => base_votes, - "mean_votes" => mean_votes, - "median_votes" => median_votes, - "credible_intervals" => credible_intervals - ) - - return simulation_results -end - -# see intake.jl for production of 2020vote.csv -base = CSV.read("../objs/2020vote.csv", DataFrame) -votes = filter(row -> row.st in STATES, base) - -results = simulate(num_scenarios, standard_deviation, biden_pop, trump_pop) -# Calculate the probability of Biden winning based on the simulated scenarios -biden_wins = sum(simulated_votes[:, 1] .> simulated_votes[:, 2]) / num_scenarios -println("Probability of Biden winning: ", biden_wins) \ No newline at end of file diff --git a/_assets/scripts/debris/spread/bi2.jl b/_assets/scripts/debris/spread/bi2.jl deleted file mode 100644 index e5ffc46..0000000 --- a/_assets/scripts/debris/spread/bi2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Big Data" -B = 41 -T = 46 -N = 1218 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/bi3.jl b/_assets/scripts/debris/spread/bi3.jl deleted file mode 100644 index d62f208..0000000 --- a/_assets/scripts/debris/spread/bi3.jl +++ /dev/null @@ -1,9 +0,0 @@ -include("spread.jl") -POLLSTER = "Big Data" -N = 1218 -B = 40 -T = 44 -TYPE_POLL = "3-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - diff --git a/_assets/scripts/debris/spread/bl2.jl b/_assets/scripts/debris/spread/bl2.jl deleted file mode 100644 index 1126e75..0000000 --- a/_assets/scripts/debris/spread/bl2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Bloomberg/Morning Consult" -N = 698 -B = 43 -T = 47 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/bl3.jl b/_assets/scripts/debris/spread/bl3.jl deleted file mode 100644 index 5fda264..0000000 --- a/_assets/scripts/debris/spread/bl3.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Bloomberg/Morning Consult" -N = 698 -B = 38 -T = 43 -TYPE_POLL = "3-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/cn2.jl b/_assets/scripts/debris/spread/cn2.jl deleted file mode 100644 index 11599f2..0000000 --- a/_assets/scripts/debris/spread/cn2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "CNN/ssrs" -N = 1097 -B = 42 -T = 50 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/cn3.jl b/_assets/scripts/debris/spread/cn3.jl deleted file mode 100644 index 295eaa0..0000000 --- a/_assets/scripts/debris/spread/cn3.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "CNN/ssrs" -TYPE_POLL = "3-way" -N = 1097 -B = 34 -T = 40 -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/ec2.jl b/_assets/scripts/debris/spread/ec2.jl deleted file mode 100644 index 9ba0b56..0000000 --- a/_assets/scripts/debris/spread/ec2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Emerson College" -N = 1000 -B = 44 -T = 46 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/ec3.jl b/_assets/scripts/debris/spread/ec3.jl deleted file mode 100644 index 8b6e13c..0000000 --- a/_assets/scripts/debris/spread/ec3.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Emerson College" -N = 1000 -B = 41 -T = 43 -TYPE_POLL = "3-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/hi2.jl b/_assets/scripts/debris/spread/hi2.jl deleted file mode 100644 index a966a45..0000000 --- a/_assets/scripts/debris/spread/hi2.jl +++ /dev/null @@ -1,12 +0,0 @@ -include("spread.jl") -POLLSTER = "Highpoint" -N = 0 -B = 0 -T = 0 -if(N == 0 | B == O | T == 0) - println("No data") -else - TYPE_POLL = "2-way" - result = spread(B,T,N) - create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -end diff --git a/_assets/scripts/debris/spread/hi3.jl b/_assets/scripts/debris/spread/hi3.jl deleted file mode 100644 index a966a45..0000000 --- a/_assets/scripts/debris/spread/hi3.jl +++ /dev/null @@ -1,12 +0,0 @@ -include("spread.jl") -POLLSTER = "Highpoint" -N = 0 -B = 0 -T = 0 -if(N == 0 | B == O | T == 0) - println("No data") -else - TYPE_POLL = "2-way" - result = spread(B,T,N) - create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -end diff --git a/_assets/scripts/debris/spread/ma2.jl b/_assets/scripts/debris/spread/ma2.jl deleted file mode 100644 index 28b04c0..0000000 --- a/_assets/scripts/debris/spread/ma2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Marist" -N = -B = -T = -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/ma3.jl b/_assets/scripts/debris/spread/ma3.jl deleted file mode 100644 index 2b1321c..0000000 --- a/_assets/scripts/debris/spread/ma3.jl +++ /dev/null @@ -1,12 +0,0 @@ -include("spread.jl") -POLLSTER = "Marist" -N = 0 -B = 0 -T = 0 -if(N == 0 | B == O | T == 0) - println("No data") -else - TYPE_POLL = "2-way" - result = spread(B,T,N) - create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) -end diff --git a/_assets/scripts/debris/spread/mar_polls.bson b/_assets/scripts/debris/spread/mar_polls.bson deleted file mode 100644 index 75c5c4b..0000000 Binary files a/_assets/scripts/debris/spread/mar_polls.bson and /dev/null differ diff --git a/_assets/scripts/debris/spread/moe.jl b/_assets/scripts/debris/spread/moe.jl deleted file mode 100644 index 338765a..0000000 --- a/_assets/scripts/debris/spread/moe.jl +++ /dev/null @@ -1,43 +0,0 @@ -""" - intrinsic_margin_of_error(N::Int, confidence_level::Float64 = 0.95) - -Calculate the margin of error for a simple random sample given the sample size and confidence level. - -# Arguments -- `N::Int`: The sample size (number of observations) as an integer. -- `confidence_level::Float64`: The confidence level as a float. Default is 0.95 (95% confidence). - -# Returns -- `::Float64`: The margin of error as a float. - -# Supported Confidence Levels -- 0.90 (90% confidence) -- 0.95 (95% confidence) -- 0.975 (97.5% confidence) -- 0.99 (99% confidence) - -# Formula -The margin of error is calculated using the following formula: -```math -MOE = z * \\sqrt{\\frac{p(1-p)}{N}} -""" -function intrinsic_margin_of_error(N::Int, confidence_level::Float64 = 0.95) - if confidence_level == 0.90 - z = 1.645 - elseif confidence_level == 0.95 - z = 1.96 - elseif confidence_level == 0.975 - z = 2.24 - elseif confidence_level == 0.99 - z = 2.576 - else - error("Unsupported confidence level. Supported levels: 0.90, 0.95, 0.975, 0.99.") - end - - p = 0.5 # Assume maximum variability (p = 0.5) - moe = z * sqrt((p * (1 - p)) / N) - - return moe -end - -moe = intrinsic_margin_of_error \ No newline at end of file diff --git a/_assets/scripts/debris/spread/qi2.jl b/_assets/scripts/debris/spread/qi2.jl deleted file mode 100644 index 72e8ab5..0000000 --- a/_assets/scripts/debris/spread/qi2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Quinnipiac University" -N = 1487 -B = 45 -T = 48 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/qi3.jl b/_assets/scripts/debris/spread/qi3.jl deleted file mode 100644 index 331d891..0000000 --- a/_assets/scripts/debris/spread/qi3.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Quinnipiac University" -N = 1487 -B = 36 -T = 41 -TYPE_POLL = "3-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/rota b/_assets/scripts/debris/spread/rota deleted file mode 100644 index be82427..0000000 --- a/_assets/scripts/debris/spread/rota +++ /dev/null @@ -1,20 +0,0 @@ -include("bi2.jl" -include("bi3.jl" -include("bl2.jl" -include("bl3.jl" -include("cn2.jl" -include("cn3.jl" -include("ec2.jl" -include("ec3.jl" -include("hi2.jl" -include("hi3.jl" -include("ma3.jl" -include("qi2.jl" -include("qi3.jl" -include("sp2.jl" -include("sp3.jl" -include("su2.jl" -include("su3.jl" -include("ws2.jl" -include("ws3l.jl" -include("ws3s.jl" \ No newline at end of file diff --git a/_assets/scripts/debris/spread/sp2.jl b/_assets/scripts/debris/spread/sp2.jl deleted file mode 100644 index 49e0464..0000000 --- a/_assets/scripts/debris/spread/sp2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Spry" -N = 709 -B = 44 -T = 48 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/sp3.jl b/_assets/scripts/debris/spread/sp3.jl deleted file mode 100644 index 936d9ac..0000000 --- a/_assets/scripts/debris/spread/sp3.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "Spry" -TYPE_POLL = "3-way" -N = 709 -B = 40 -T = 43 -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/spread.jl b/_assets/scripts/debris/spread/spread.jl deleted file mode 100644 index f2d5163..0000000 --- a/_assets/scripts/debris/spread/spread.jl +++ /dev/null @@ -1,82 +0,0 @@ -using Plots -using Dates - -const FLAGRED = "#B22234" -const FLAGBLUE = "#3C3B6E" -const PURPLE = "#772F51" -const PLUG = 0.012 - -include("moe.jl") - -gr() - -function spread(Harris::Int64,Trump::Int64,N::Int64) - biden_lo = Harris/100 - (moe(N) + PLUG) - biden_hi = Harris/100 + (moe(N) + PLUG) - biden_pk = [biden_lo,Harris/100,biden_hi] .* 100 - biden_bk = Int.(round.(biden_pk,digits = 0)) - trump_lo = Trump/100 - (moe(N) + PLUG) - trump_hi = Trump/100 + (moe(N) + PLUG) - trump_pk = [trump_lo,Trump/100,trump_hi] .* 100 - trump_bk = Int.(round.(trump_pk,digits = 0)) - return(biden_bk,trump_bk) -end - -function create_ribbon_chart(result, STATE, TYPE_POLL, POLLSTER; filename=nothing) - biden_range = result[1] - trump_range = result[2] - - # Calculate the overlap range - overlap_start = max(biden_range[1], trump_range[1]) - overlap_end = min(biden_range[end], trump_range[end]) - overlap_range = [overlap_start, overlap_end] - - # Calculate the overlap amount - overlap_amount = overlap_range[end] - overlap_range[1] - - # Create the ribbon chart - p = plot(size=(800, 300), legend=false, grid=false, yaxis=false, bottom_margin=10Plots.mm, top_margin=15Plots.mm) - - # Plot Harris's and Trump's ranges - plot!([biden_range[1], biden_range[end]], [1.2, 1.2], linewidth=10, color=FLAGBLUE) - plot!([trump_range[1], trump_range[end]], [0.2, 0.2], linewidth=10, color=FLAGRED) - - # Plot the overlap range - plot!([overlap_range[1], overlap_range[end]], [0.7, 0.7], linewidth=10, color=PURPLE) - - # Add candidate names and overlap amount annotation - annotate!((biden_range[1] + biden_range[end]) / 2, 1.2, text("BIDEN", :center, 12, :white)) - annotate!((trump_range[1] + trump_range[end]) / 2, 0.2, text("TRUMP", :center, 12, :white)) - annotate!((overlap_range[1] + overlap_range[end]) / 2, 0.7, text("$(overlap_amount) pts", :center, 12, :white)) - - # Set tick positions and labels - tick_values = sort(unique(vcat(biden_range, trump_range))) - xticks!(tick_values, string.(tick_values)) - - # Add title - title!("$STATE, $TYPE_POLL by $POLLSTER") - - # Adjust the y-axis limits - ylims!((-0.5, 2.0)) - - # Save the plot to a file if a filename is provided - if filename !== nothing - savefig(p, filename) - end - - return p -end - -""" -# Example usage - -38,41,600 -40,44,600 - -result = spread(43,47,1000) -STATE = "North Carolina" -TYPE_POLL = "2-way" -POLLSTER = "Susquehanna Polling" -create_ribbon_chart(result, STATE, TYPE_POLL, POLLSTER) -""" - diff --git a/_assets/scripts/debris/spread/su2.jl b/_assets/scripts/debris/spread/su2.jl deleted file mode 100644 index 9429b12..0000000 --- a/_assets/scripts/debris/spread/su2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = Suquehanna -N = -B = -T = -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/su3.jl b/_assets/scripts/debris/spread/su3.jl deleted file mode 100644 index be15ae2..0000000 --- a/_assets/scripts/debris/spread/su3.jl +++ /dev/null @@ -1,7 +0,0 @@ -POLLSTER = Suquehanna -N = -B = -T = -TYPE_POLL = "3-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/ws2.jl b/_assets/scripts/debris/spread/ws2.jl deleted file mode 100644 index a1b189c..0000000 --- a/_assets/scripts/debris/spread/ws2.jl +++ /dev/null @@ -1,8 +0,0 @@ -include("spread.jl") -POLLSTER = "WSJ" -N = 600 -B = 45 -T = 48 -TYPE_POLL = "2-way" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/spread/ws3l.jl b/_assets/scripts/debris/spread/ws3l.jl deleted file mode 100644 index 15d31e3..0000000 --- a/_assets/scripts/debris/spread/ws3l.jl +++ /dev/null @@ -1,9 +0,0 @@ -include("spread.jl") -POLLSTER = "WSJ" -N = 600 -B = 40 -T = 48 -TYPE_POLL = "3-way (long)" -result = spread(B,T,N) -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) - diff --git a/_assets/scripts/debris/spread/ws3s.jl b/_assets/scripts/debris/spread/ws3s.jl deleted file mode 100644 index e19036b..0000000 --- a/_assets/scripts/debris/spread/ws3s.jl +++ /dev/null @@ -1,7 +0,0 @@ -include("spread.jl") -POLLSTER = "WSJ" -N = 600 -B = 37 -T = 39 -TYPE_POLL = "3-way (short)" -create_ribbon_chart(result, ST, TYPE_POLL, POLLSTER) diff --git a/_assets/scripts/debris/sql.jl b/_assets/scripts/debris/sql.jl deleted file mode 100644 index 41a98dd..0000000 --- a/_assets/scripts/debris/sql.jl +++ /dev/null @@ -1,92 +0,0 @@ -using Dates -using DataFrames -using HTTP -using MySQL - -""" -CREATE TABLE IF NOT EXISTS polls ( - id INT AUTO_INCREMENT PRIMARY KEY, - state VARCHAR(255) COMMENT 'Name of state', - pollster VARCHAR(255) COMMENT 'Name of the pollster', - typepoll VARCHAR(255) COMMENT 'Poll type', - pub_date DATE COMMENT 'Date of the poll', - start_date DATE COMMENT 'Start date of polling', - end_date DATE COMMENT 'End date of polling', - url VARCHAR(255) COMMENT 'URL of the poll', - n INTEGER COMMENT 'Sample size (in respondents)', - biden FLOAT COMMENT 'Harris support', - trump FLOAT COMMENT 'Trump support', - third FLOAT COMMENT 'Third-party support', - sserept FLOAT COMMENT 'Reported sample standard error', - design_err FLOAT COMMENT 'Design effect', - other_err FLOAT COMMENT 'Unspecified error', - moe FLOAT COMMENT 'Margin of error', - ssecalc FLOAT COMMENT 'Calculated [sub]sample standard error', - deadj FLOAT COMMENT 'Design effect adj [sub]sample st error', - moeadj FLOAT COMMENT 'Total adjusted margin of error', - leadr VARCHAR(255) COMMENT 'Poll leader (Harris,Trump,Third,None)' - ); -""" -# Database connection details -const HOST = "localhost" -const USER = "swing" -const PASSWORD = "swing" -const DATABASE = "swing" -const TABLE = "polls" - -# Connect to the MariaDB database -conn = DBInterface.connect(MySQL.Connection, HOST, USER, PASSWORD, db=DATABASE) - -# Define the date range -start_date = Date("2024-01-01") -end_date = Date("2024-12-31") -pub_date = Date("2024-04-04") - -# Read data from the database within the date range into a DataFrame -query = """ - SELECT * - FROM $TABLE - WHERE pub_date = "2024-04-04" -""" - - -# Execute the query and fetch the results into a DataFrame -df = DataFrame(DBInterface.execute(conn, query)) - -""" -# Perform calculations in Julia -df.sse = sqrt.(df.n) # Calculate simple random sampling error -df.total_support = df.biden .+ df.trump .+ df.third # Calculate total support - - -update_query = """ - UPDATE data_entries - SET poll = ?, url = ?, n = ?, biden = ?, trump = ?, third = ?, - type = ?, sserept = ?, de = ?, other = ?, tot = ?, - ssecalc = ?, deadj = ?, totadj = ?, leadr = ? - WHERE date = ? - """ -stmt = DBInterface.prepare(conn, update_query) -DBInterface.execute(stmt, [ - row.poll, row.url, row.n, row.biden, row.trump, row.third, - row.type, row.sserept, row.de, row.other, row.tot, - row.ssecalc, row.deadj, row.totadj, row.leadr, row.date -]) -# Write the updated DataFrame back to the database -for row in eachrow(df) - update_query = """ - UPDATE data_entries - SET poll = ?, url = ?, n = ?, biden = ?, trump = ?, third = ?, - type = ?, sserept = ?, de = ?, other = ?, tot = ?, - ssecalc = ?, deadj = ?, totadj = ?, leadr = ? - WHERE date = ? - """ - MySQL.execute(conn, update_query, [ - row.poll, row.url, row.n, row.biden, row.trump, row.third, - row.type, row.sserept, row.de, row.other, row.tot, - row.ssecalc, row.deadj, row.totadj, row.leadr, row.date - ]) -end -""" -# Close the database connection -MySQL.disconnect(conn) \ No newline at end of file diff --git a/_assets/scripts/debris/state_level.jl b/_assets/scripts/debris/state_level.jl deleted file mode 100644 index 7a0b71d..0000000 --- a/_assets/scripts/debris/state_level.jl +++ /dev/null @@ -1,29 +0,0 @@ -include("bayes_head.jl") - -function filter_empty_entries(dict::Dict{Pollster, Vector{Poll}}) - return Dict(poll=> polls for (poll, polls) in dict if !isempty(polls)) -end - -using BSON: @save, @load -@load "../objs/may_polls.bson" months - -MO = may -ST = WI - -current_mon = filter_empty_entries(months[MO][ST]) - -include("bayes_main.jl") - -prior_probs[ST] -# Summary statistics -summarystats(current_samples) - -# Trace plot -plot() - -# Autocorrelation -autocor(current_samples) - -# Effective sample size -ess(current_samples) - diff --git a/_assets/scripts/debris/statetabs.jl b/_assets/scripts/debris/statetabs.jl deleted file mode 100644 index d15983f..0000000 --- a/_assets/scripts/debris/statetabs.jl +++ /dev/null @@ -1,38 +0,0 @@ -using CSV -using DataFrames -using PrettyTables - - -# Include files -include("constants.jl") -include("utils.jl") - -# see CreateOutcomes.jl for production of outcome.csv -# objs = "../objs/" -# objs = "/Users/ro/projects/SwingWatch/_src/objs/" -outcome = CSV.read("/Users/ro/projects/SwingWatch/_src/objs/outcome.csv"DataFrame) - -header = ["Scenario", "Electoral Votes", "Harris Total", "Trump Total", "Result"] - -# pretty_table(outcome; backend = Val(:html), header = header, standalone = false) - -pa_loss = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== -"Trump"), :] -pa_ties = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== "Tie"), :] -pa_wins = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== "Harris"), :] - -println("### Harris wins") - - -# see intake.jl for production of 2020vote.csv -base = CSV.read("/Users/ro/projects/SwingWatch/_src/objs/2020vote.csv", DataFrame) -base.vote = base.biden_col .+ base.trump_col -base.pop = base.biden_pop .+ base.trump_pop -base.pct = base.biden_pop ./ base.pop -base = base[:,[1,4,5,6,7,8,9]] -new_names = ["st","biden","trump","margin","vote","pop","pct"] -rename!(base, Symbol.(new_names)) - -pa2020 = base[(occursin.("PA", base.st)), :] - -outcome[(occursin.("Trump", outcome.result)) diff --git a/_assets/scripts/debris/stubby b/_assets/scripts/debris/stubby deleted file mode 100644 index 7362d77..0000000 --- a/_assets/scripts/debris/stubby +++ /dev/null @@ -1,94 +0,0 @@ -master_polls.data[bl2][mar].data[AZ] = [ - PollData(42,49,788) -] -master_polls.data[bi2][mar].data[PA] = [ - PollData(40,46,1305) -] -master_polls.data[bi2][mar].data[MI] = [ - PollData(42,45,1218) -] -master_polls.data[bl2][mar].data[PA] = [ - PollData(45,45,807) -] -master_polls.data[bl2][mar].data[GA] = [ - PollData(42,49,788) -] -master_polls.data[bl2][mar].data[NC] = [ - PollData(43,49,699) -] -master_polls.data[bl2][mar].data[MI] = [ - PollData(44,46,447) -] -master_polls.data[bl2][mar].data[AZ] = [ - PollData(42,49,788)x`x -] -master_polls.data[bl2][mar].data[WI] = [ - PollData(46,45,697) -] -master_polls.data[bl2][mar].data[NV] = [ - PollData(43,49,699) -] -master_polls.data[cb2][mar].data[GA] = [ - PollData(48,51,1133) -] -master_polls.data[cn2][mar].data[PA] = [ - PollData(46,46,1132) -] -master_polls.data[cn2][mar].data[MI] = [ - PollData(42,50,1097) -] -master_polls.data[ec2][mar].data[PA] = [ - PollData(43,45,1000) -] -master_polls.data[ec2][mar].data[GA] = [ - PollData(42,46,1000) -] -master_polls.data[ec2][mar].data[MI] = [ - PollData(44,45,1000) -] -master_polls.data[fm2][mar].data[PA] = [ - PollData(48,38,431) -] -master_polls.data[fo2][mar].data[PA] = [ - PollData(45,49,1121) -] -master_polls.data[hi2][mar].data[NC] = [ - PollData(38,44,1016) -] -master_polls.data[ma2][mar].data[NC] = [ - PollData(48,51,1295) -] -master_polls.data[mi2][mar].data[NC] = [ - PollData(44,47,626) -] -master_polls.data[qi2][mar].data[MI] = [ - PollData(45,48,1487) -] -master_polls.data[sp2][mar].data[MI] = [ - PollData(44,48,709) -] - -master_polls.data[wa2][mar].data[PA] = [ - PollData(45,50,736) -] -master_polls.data[ws2][mar].data[PA] = [ - PollData(44,47,600) -] -master_polls.data[ws2][mar].data[GA] = [ - PollData(43,44,600) -] -master_polls.data[ws2][mar].data[NC] = [ - PollData(43,49,600) -] -master_polls.data[ws2][mar].data[MI] = [ - PollData(45,48,600) -] -master_polls.data[ws2][mar].data[AZ] = [ - PollData(44,47,600) -] -master_polls.data[ws2][mar].data[WI] = [ - PollData(46,46,600) -] -master_polls.data[ws2][mar].data[NV] = [ - PollData(44,48,600) -] diff --git a/_assets/scripts/debris/tabsstates.jl b/_assets/scripts/debris/tabsstates.jl deleted file mode 100644 index b85c027..0000000 --- a/_assets/scripts/debris/tabsstates.jl +++ /dev/null @@ -1,72 +0,0 @@ -using CSV -using DataFrames -using PrettyTables - - -header = ["Scenario", "Electoral Votes", "Biden Total", "Trump Total", "Result"] - -# see CreateOutcomes.jl for production of outcome.csv -csv_path = "/Users/ro/projects/SwingWatch/_assets/objs/outcome.csv" - - -outcome = CSV.read(csv_path, DataFrame) - -""" - replace_and_with_comma!(df::DataFrame, col_name::Symbol) - -Replace occurrences of " and" with "," in a specific column of a DataFrame. - -# Arguments -- `df::DataFrame`: The DataFrame in which the replacement should be performed. -- `col_name::Symbol`: The name of the column (as a Symbol) in which the replacement should be done. - -# Notes -- This function modifies the input DataFrame `df` in-place. -- It uses the `transform!` function from the DataFrames.jl package to apply a row-wise transformation to the specified `col_name` column. -- The transformation function `ByRow(x -> replace(x, " and" => ","))` replaces occurrences of " and" with "," in each row of the `col_name` column. -- This function is useful for cleaning text data, especially when dealing with comma-separated lists that may contain the word "and". - -# Examples -```julia -# Create a sample DataFrame -data = [ - "Apple and Banana", - "Orange and Kiwi", - "Grape", - "Pear and Mango" -] -df = DataFrame(fruit=data) - -# Replace " and" with "," in the "fruit" column -replace_and_with_comma!(df, :fruit) - -# The "fruit" column of `df` now contains: -# fruit -# 1 "Apple,Banana" -# 2 "Orange,Kiwi" -# 3 "Grape" -# 4 "Pear,Mango" -""" -# Function to replace " and" with "," in a specific column of a DataFrame -function replace_and_with_comma!(df::DataFrame, col_name::Symbol) - transform!(df, col_name => ByRow(x -> replace(x, " and" => ",")) => col_name) -end - -# Example usage: -# Assume outcome is your DataFrame and combo is the column you want to modify -replace_and_with_comma!(outcome, :combo) - -#pretty_table(outcome; backend = Val(:html), header = header, standalone = false) - -pa_loss = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== - "Trump"), :] -pa_ties = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== "Tie"), :] -pa_wins = outcome[(occursin.("PA", outcome.combo)) .& (outcome.result .== "Biden"), :] -pa_miss = outcome[(.!occursin.("PA", outcome.combo)) .& (outcome.result .== "Biden"), :] - - -pretty_table(pa_miss; backend = Val(:html), header = header, standalone = false) - -nc_miss = outcome[(.!occursin.("NC", outcome.combo)) .& (outcome.result .== "Biden"), :] -pa_miss = nc_miss[(.!occursin.("PA", nc_miss.combo)), :] -pretty_table(pa_miss; backend = Val(:html), header = header, standalone = false) \ No newline at end of file diff --git a/_assets/scripts/debris/the_maps.jl b/_assets/scripts/debris/the_maps.jl deleted file mode 100644 index 89866aa..0000000 --- a/_assets/scripts/debris/the_maps.jl +++ /dev/null @@ -1,87 +0,0 @@ -using PlotlyJS - -""" - electoral_map(data, color) - -Create a choropleth map of the United States, colored by the provided data and color scheme, with state labels and a title. - -# Arguments -- `data::Vector{<:Real}`: A vector of numeric values representing the data to be displayed on the map, with one value for each state. -- `color::AbstractString`: A color string (e.g., "red", "#FF0000") representing the color to be used for the map. - -# Returns -- `PlotlyJS.SyncPlot`: The Plotly.js figure object representing the electoral map. - -# Notes -- This function uses the Plotly.js library to create an interactive choropleth map of the United States. -- The `data` vector must have one value for each state, and the values will be used to color the states based on the provided `color` scheme. -- The map includes state labels with the corresponding data values. -- The map has a title "The 93 Swing State Electoral Votes". -- The map is saved as a PNG image file at the path "/Users/ro/projects/SwingWatch/_assets/img/maps/electoral_map.png". -- This function assumes the existence of a constant `STATES` containing the two-letter abbreviations for all U.S. states. - -# Example -```julia -# Assuming `STATES` is a vector of two-letter state abbreviations -data = rand(length(STATES)) # Generates random data for each state -electoral_map(data, "blue") # Create a blue electoral map with the random data -""" -function electoral_map(data, color) - # Create the data for the choropleth map - choropleth_trace = PlotlyJS.choropleth( - locationmode="USA-states", - locations=STATES, - z=data, - colorscale=[[0, color], [1, color]], - showscale=false, - marker=attr(line=attr(color="white", width=2)), - hoverinfo="location+text" - ) - - # Create the data for the state labels - label_trace = PlotlyJS.scattergeo( - locationmode="USA-states", - locations=STATES, - text=data, - textfont=attr(size=12, color="white"), - mode="text", - showlegend=false, - hoverinfo="none" - ) - - # Create the layout for the map - layout = PlotlyJS.Layout( - title="The 93 Swing State Electoral Votes", - geo=attr( - scope="usa", - projection=attr(type="albers usa"), - showlakes=true, - lakecolor="rgb(255, 255, 255)" - ) - ) - - # Create the figure with both traces - fig = PlotlyJS.plot([choropleth_trace, label_trace], layout) - - # Save the plot as an image file - PlotlyJS.savefig(fig, "/Users/ro/projects/SwingWatch/_assets/img/maps/electoral_map.png") -end - -const STATES = ["NV", "MI", "WI", "NC", "AZ", "PA", "GA"] -const LIGHT_PURPLE = "rgba(200, 150, 255, 0.7)" - -votes = Dict( - "NV" => 6, - "MI" => 15, - "WI" => 10, - "NC" => 16, - "AZ" => 11, - "PA" => 19, - "GA" => 16 -) - -data = [votes[state] for state in STATES] -const PURPLE = "#772F51" - -electoral_map(data, PURPLE) - diff --git a/_assets/scripts/debris/utils.jl b/_assets/scripts/debris/utils.jl deleted file mode 100644 index ec20858..0000000 --- a/_assets/scripts/debris/utils.jl +++ /dev/null @@ -1,65 +0,0 @@ -function hfun_bar(vname) - val = Meta.parse(vname[1]) - return round(sqrt(val), digits=2) -end - -function hfun_m1fill(vname) - var = vname[1] - return pagevar("index", var) -end - -function lx_baz(com, _) - # keep this first line - brace_content = Franklin.content(com.braces[1]) # input string - # do whatever you want here - return uppercase(brace_content) -end - -function hfun_custom_taglist()::String - # ----------------------------------------- - # Part1: Retrieve all pages associated with - # the tag & sort them - # ----------------------------------------- - # retrieve the tag string - tag = locvar(:fd_tag) - # recover the relative paths to all pages that have that - # tag, these are paths like /blog/page1 - rpaths = globvar("fd_tag_pages")[tag] - # you might want to sort these pages by chronological order - # you could also only show the most recent 5 etc... - sorter(p) = begin - # retrieve the "date" field of the page if defined, otherwise - # use the date of creation of the file - pvd = pagevar(p, :date) - if isnothing(pvd) - return Date(Dates.unix2datetime(stat(p * ".md").ctime)) - end - return pvd - end - sort!(rpaths, by=sorter, rev=true) - - # -------------------------------- - # Part2: Write the HTML to plug in - # -------------------------------- - # instantiate a buffer in which we will write the HTML - # to plug in the tag page - c = IOBuffer() - write(c, "...1...") - # go over all paths - for rpath in rpaths - # recover the url corresponding to the rpath - url = get_url(rpath) - # recover the title of the page if there is one defined, - # if there isn't, fallback on the path to the page - title = pagevar(rpath, "title") - if isnothing(title) - title = "/$rpath/" - end - # write some appropriate HTML - write(c, "...2...") - end - # finish the HTML - write(c, "...3...") - # return the HTML string - return String(take!(c)) -end diff --git a/_assets/scripts/debris/vote20223.jl b/_assets/scripts/debris/vote20223.jl deleted file mode 100644 index 7d72968..0000000 --- a/_assets/scripts/debris/vote20223.jl +++ /dev/null @@ -1,56 +0,0 @@ -#------------------------------------------------------------------ -# revise to add north carolina -#------------------------------------------------------------------ - -using CSV -using DataFrames -using Format -using PrettyTables -using Printf - -mutable struct MetaFrames - meta::Dict{Symbol, Any} - data::DataFrame -end - -# Example usage -# df = DataFrame(name=["John", "Jane"], age=[28, 34]) -# meta_info = Dict(:source => "Survey Data", :year => 2021) -# df_meta = MetaFrames(meta_info, df) - -turnout = CSV.read("../data/vote2022.csv",DataFrame) -meta_info = Dict( - :source => "Census Bureau, Current Population Survey, November 2022", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022", - :url => "https://www.census.gov/data/tables/time-series/demo/voting-and-registration/p20-586.html", - :title => "Table 4c. Reported Voting and Registration of the Total Voting-Age Population, by Age, for States: November 2022") -turnout[2:6,1] .= "AZ" -turnout[8:12,1] .= "GA" -turnout[14:18,1] .= "MI" -turnout[20:24,1] .= "NV" -turnout[26:30,1] .= "PA" -turnout[32:36,1] .= "WI" - -turnout[:,3:6] = turnout[:,3:6] .* Int64[1e3] -turnout.ncpop = turnout.totpop .- turnout.cpop -turnout.ncpct = turnout.ncpop ./ turnout.totpop -turnout = turnout[1:36,:] -state_turnout = turnout[turnout.cohort .== "Total", :] -turnout = turnout[turnout.cohort .!= "Total", :] -vote2022 = MetaFrames(meta_info,turnout) - -state_turnout.st = convert.(String, state_turnout.st) -state_turnout.totpop = convert.(Int64, state_turnout.totpop) -state_turnout.cpop = convert.(Int64, state_turnout.cpop) -state_turnout.ncpop = convert.(Int64, state_turnout.ncpop) -state_turnout.ncpct = convert.(Float64, state_turnout.ncpct) -state_turnout.ncpct = map(x -> Printf.@sprintf("%.2f", x), state_turnout.ncpct) -state_turnout.totpop = Format.format.(state_turnout.totpop, commas=true) -state_turnout.cpop = Format.format.(state_turnout.cpop, commas=true) -state_turnout.ncpop = Format.format.(state_turnout.ncpop, commas=true) -header = ("State","Population","Non-citizen","Percentage") -pretty_table(state_turnout; backend = Val(:html), header = header) - - - - diff --git a/_assets/scripts/dict.jl b/_assets/scripts/dict.jl index bc6e14e..af3064d 100644 --- a/_assets/scripts/dict.jl +++ b/_assets/scripts/dict.jl @@ -1,10 +1,4 @@ Month_names = Dict( - "mar" => "March", - "apr" => "April", - "may" => "May", - "jun" => "June", - "jul" => "July", - "jul2" => "July-post", "aug1" => "early August", "aug2" => "late August", "sep1" => "early September", diff --git a/_assets/scripts/election_graph.png b/_assets/scripts/election_graph.png deleted file mode 100644 index 8d44134..0000000 Binary files a/_assets/scripts/election_graph.png and /dev/null differ diff --git a/_assets/scripts/func.jl b/_assets/scripts/func.jl index dcb8a39..d98b842 100644 --- a/_assets/scripts/func.jl +++ b/_assets/scripts/func.jl @@ -1,50 +1,87 @@ +""" + draw_density() + +Generates and returns a density plot figure visualizing the posterior distribution of the likelihood of Harris winning in a specific state, based on current polling data. + +The plot includes: +- **KDE Line Plot**: The kernel density estimate (KDE) of the posterior draws, plotted as a solid line. +- **Credible Interval Shading**: A shaded area under the KDE curve representing the credible interval of the posterior distribution. +- **Actual Margin Line**: A vertical dashed line indicating the actual margin from the 2020 election. +- **Axis Labels and Title**: Customizable labels for the x-axis and y-axis, and a title that includes the state and polling date. +- **Legend**: A legend explaining the plotted elements. +- **Axis Limits**: Adjusted x-axis limits based on `p_vec` and y-axis limits starting from zero. + +**Dependencies**: +- `kde_result`: An object containing `x` and `density` arrays from a KDE computation. +- `posterior_interval`: A tuple or array containing the lower and upper bounds of the credible interval. +- `margin`: A numerical value representing the actual margin from the 2020 election. +- `p_vec`: An array of possible probability values used to set x-axis limits. +- `st`: A string representing the state being analyzed. +- `Mon`: An integer representing the current month index. +- `Month_names`: An array of month names. +- `LORANGE`: A color constant for the credible interval shading. +- `FLAGBLUE`: A color constant for the actual margin line. + +**Returns**: +- `fig` (`Makie.Figure`): A Makie Figure object containing the constructed density plot. + +**Note**: +This function relies on global variables defined outside its scope. Ensure all dependencies are properly defined before calling this function. +""" function draw_density() - # Create a new figure with specified resolution - fig = Figure(size = (600, 400)) - - # Add an axis to the figure - ax = Axis(fig[1, 1], xlabel = "Likelihood of Harris win", ylabel = "Number of draws", title = "Model: Harris results in $st with polling through " * Month_names[Mon]) - - # Plot the full density curve + fig = Figure(size = (600, 400)) + ax = Axis(fig[1, 1], xlabel = "Likelihood of Harris win", ylabel = "Number of draws", + title = "Model: Harris results in $st with polling through " * Month_names[Mon]) lines!(ax, kde_result.x, kde_result.density, color = "#a3b35c", linewidth = 3, label = "Draws") - # Find the indices corresponding to the posterior interval - indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) - - # Extract the x and y values within the posterior interval + indices = findall((posterior_interval[1] .<= kde_result.x) .& (kde_result.x .<= posterior_interval[2])) x_region = kde_result.x[indices] y_region = kde_result.density[indices] - - # Fill the specific area under the curve band!(ax, x_region, fill(0, length(x_region)), y_region, color = (LORANGE), label = "Credible Interval") - - # Find the y-value corresponding to the specified x-value - y_value = kde_result.density[argmin(abs.(kde_result.x .- margin))] - - # Add a vertical line at the specified x-value from 0 to the y-value - vlines!(ax, [margin], [0, y_value], color = FLAGBLUE, linestyle = :dash, linewidth = 4, label = "2020 Actual") - - # Add a legend to the plot + # Draw a vertical line at x = 0.5 with label "Even odds" + vlines!(ax, [0.5], color = :red, linestyle = :dash, linewidth = 2, label = "Even odds") axislegend(ax) - - # Adjust the plot limits to fit the density line Makie.xlims!(ax, extrema(p_vec)) Makie.ylims!(ax, 0, nothing) - - # Display the figure fig end +""" + estimate_high_probability_outcomes(kde, threshold=0.5, num_samples=10000) + +Estimates the proportion of samples from a given kernel density estimate (KDE) that are greater than a specified threshold. + +**Parameters**: +- `kde`: A KDE object from which samples can be drawn using the `rand` function. +- `threshold` (`Float64`, default = 0.5): The threshold value above which samples are considered high-probability outcomes. +- `num_samples` (`Int`, default = 10000): The number of random samples to draw from the KDE for estimation. + +**Returns**: +- `proportion` (`Float64`): The estimated proportion of samples exceeding the threshold. + +**Example**: +```julia +kde = some_kde_function(data) +prob = estimate_high_probability_outcomes(kde, threshold=0.7, num_samples=5000) +println("Proportion of outcomes above 0.7: ", prob) +Notes: + +The function uses Monte Carlo sampling; results may vary slightly with each run due to randomness. +Ensure that kde is a valid KDE object compatible with rand. +""" function estimate_high_probability_outcomes(kde, threshold=0.5, num_samples=10000) - # Sample from the kernel density estimate - samples = rand(kde, num_samples) - - # Count samples above the threshold + samples = rand(kde, num_samples) count_above_threshold = sum(samples .> threshold) - - # Calculate the proportion - proportion = count_above_threshold / num_samples - + proportion = count_above_threshold / num_samples return proportion end +function flip!(df, state) + i = findfirst(df.po .== state) + df[i, :harris], df[i, :trump] = df[i, :trump], df[i, :harris] + return df +end + +function tally() + spread.spread = spread.margin .- spread.pop_harris ./ (spread.pop_harris .+ spread.pop_trump) +end diff --git a/_assets/scripts/impt.jl b/_assets/scripts/impt.jl index 4fb610d..6f883eb 100644 --- a/_assets/scripts/impt.jl +++ b/_assets/scripts/impt.jl @@ -1,8 +1,9 @@ -margins = CSV.read("../objs/margins.csv", DataFrame) -prior_poll = BSON.load("../objs/"*"$st"*"_"*"$prior_month"*"_p_sample.bson") -# prior_poll = BSON.load("../objs/new_prior.bson") +margins = CSV.read("objs/margins.csv", DataFrame) +prior_poll = BSON.load("objs/"*"$st"*"_"*"$prior_month"*"_p_sample.bson") +# when starting with an initial prior +# prior_poll = BSON.load("objs/new_prior.bson") -input_file = "../data/$sT.csv" +input_file = "data/$sT.csv" lines = readlines(input_file) data = @chain lines begin map(line -> begin @@ -26,13 +27,10 @@ df = CSV.read(IOBuffer(data_str), header = HEADER, missingstring = "—") select!(df, Not(:margin)) -# df.Day = parse.(Int,df.Day) -#df.n = parse.(Int,df.n) -df.Day = ifelse.(df.Day .> 18, 2, 1) - +df.Day = ifelse.(df.Day .> 26, 2, 1) df.Date = df.Date .* string.(df.Day) - select!(df, Not(:Day)) +select!(df, Not(:Column8)) df.total_support = df.harris + df.trump df.harris_adjusted = (df.harris ./ df.total_support) .* 100 diff --git a/_assets/scripts/joint.jl b/_assets/scripts/joint.jl index 38eff29..9aeaa48 100644 --- a/_assets/scripts/joint.jl +++ b/_assets/scripts/joint.jl @@ -1,49 +1,66 @@ include("libr.jl") -mon = "oct1" -MON = "oct1" -Mon = "oct1" +mon = "oct2" +MON = "oct2" +Mon = "oct2" st = "AZ" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainAZ = deep[:deep][:p] #------------------------------------------------------------------ st = "GA" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainGA = deep[:deep][:p] #------------------------------------------------------------------ st = "MI" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainMI = deep[:deep][:p] #------------------------------------------------------------------ st = "NC" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainNC = deep[:deep][:p] #------------------------------------------------------------------ st = "NV" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainNV = deep[:deep][:p] #------------------------------------------------------------------ st = "PA" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainPA = deep[:deep][:p] #------------------------------------------------------------------ st = "WI" -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") chainWI = deep[:deep][:p] #------------------------------------------------------------------ -# Assuming you have 7 chains named chain1, chain2, ..., chain7 -samples = [chainAZ, chainGA, chainMI, chainNC, chainNV, chainPA, chainWI] +samples = [chainAZ, chainGA, chainMI, chainNC, chainNV, chainPA, chainWI] state_names = ["AZ","GA","MI","NC","NV","PA", "WI"] -# Calculate individual probabilities - individual_probs = [mean(sample .> 0.5) for sample in samples] - -# 3. Correlation Analysis corr_matrix = cor(hcat(samples...)) - -# 4. Pairwise Joint Probabilities +""" + pairwise_joint_prob(samples1, samples2) + +Calculates the joint probability that both elements in `samples1` and `samples2` exceed a threshold of 0.5 at corresponding positions. + +**Parameters**: +- `samples1`: An array of numerical samples. +- `samples2`: An array of numerical samples of the same length as `samples1`. + +**Returns**: +- `probability` (`Float64`): The proportion of sample pairs where both `samples1[i]` and `samples2[i]` are greater than 0.5. + +**Example**: +```julia +samples1 = rand(10000) +samples2 = rand(10000) +prob = pairwise_joint_prob(samples1, samples2) +println("Joint probability of both samples exceeding 0.5: ", prob) +Notes: + +Both samples1 and samples2 must be arrays of equal length. +The function performs an element-wise comparison and logical AND operation to determine where both samples exceed the threshold. +The threshold is fixed at 0.5; modify the function if a different threshold is needed. +""" function pairwise_joint_prob(samples1, samples2) return mean((samples1 .> 0.5) .& (samples2 .> 0.5)) end @@ -51,39 +68,65 @@ end pairwise_probs = [pairwise_joint_prob(samples[i], samples[j]) for i in 1:7 for j in i+1:7] -# 5. Monte Carlo for All 7 States all_states_prob = mean(all(x -> x > 0.5, hcat(samples...); dims=2)) -# 6. Subset Analysis + +""" + subset_prob(samples, k) + +Calculates the proportion of instances where at least `k` out of the provided sample arrays have values exceeding a threshold of 0.5 at corresponding indices. + +**Parameters**: +- `samples`: A collection (e.g., a list or array) of numerical sample arrays. Each sample array should be of equal length. +- `k` (`Int`): The minimum number of samples that must exceed the threshold at each index. + +**Returns**: +- `probability` (`Float64`): The proportion of indices where at least `k` samples have values greater than 0.5. + +**Example**: +```julia +# Generate sample data +samples1 = rand(10000) +samples2 = rand(10000) +samples3 = rand(10000) + +# Calculate the probability that at least 2 out of 3 samples exceed 0.5 +prob = subset_prob([samples1, samples2, samples3], 2) +println("Probability that at least 2 samples exceed 0.5: ", prob) +Notes: + +All sample arrays in samples must be of equal length. +The function performs an element-wise comparison across all sample arrays. +The threshold is fixed at 0.5. Modify the function if a different threshold is needed. +This function is useful for estimating the probability of at least k successes in multiple trials. +""" function subset_prob(samples, k) return mean(sum(x -> x > 0.5, hcat(samples...); dims=2) .>= k) end subset_probs = [subset_prob(samples, k) for k in 1:7] -# Visualization p1 = Plots.heatmap(corr_matrix, title="State Correlation Heatmap", xticks=(1:7, state_names), yticks=(1:7, state_names)) p2 = Plots.bar(state_names, individual_probs, title="Individual State Probabilities", ylabel="Probability > 0.5") -p3 = Plots.plot(1:7, subset_probs, title="Probability of Harris winning k or more states > 0.5", - xlabel="k", ylabel="Probability", marker=:circle, legend = false) +p3 = Plots.plot(1:7, subset_probs, title="Likelihood of Harris winning k or more states > 0.5", + xlabel="k", ylabel="Likelihood", marker=:circle, legend = false) -#Plots.plot(p1, p2, p3, layout=(3,1), size=(800,1200)) Plots.plot(p3) -# Print results -println("Individual state probabilities:") + +println("Individual state likelihood:") for (state, prob) in zip(state_names, individual_probs) println(" $state: $(round(prob, digits=3))") end -println("\nProbability of all 7 states > 0.5: $(round(all_states_prob, digits=3))") +println("\nLikelihood of all 7 states > 0.5: $(round(all_states_prob, digits=3))") -println("\nSubset probabilities:") +println("\nSubset Likelihood:") for k in 1:7 println(" $k or more states > 0.5: $(round(subset_probs[k], digits=3))") end -savefig(p3, "../img/joint.png") \ No newline at end of file +Plots.savefig(p3, "../img/joint.png") diff --git a/_assets/scripts/libr.jl b/_assets/scripts/libr.jl index 4adb92f..87c7eac 100644 --- a/_assets/scripts/libr.jl +++ b/_assets/scripts/libr.jl @@ -20,4 +20,4 @@ using Printf using Serialization using Statistics using StatsPlots -using Turing \ No newline at end of file +using Turing diff --git a/_assets/scripts/load.jl b/_assets/scripts/load.jl index d47b01d..54b6f0b 100644 --- a/_assets/scripts/load.jl +++ b/_assets/scripts/load.jl @@ -8,4 +8,4 @@ include("impt.jl") # object imports include("main.jl") # modeling include("outp.jl") # output include("insp.jl") # check results -include("save.jl") # save model \ No newline at end of file +include("save.jl") # save model diff --git a/_assets/scripts/main.jl b/_assets/scripts/main.jl index b000ada..d5e17ba 100644 --- a/_assets/scripts/main.jl +++ b/_assets/scripts/main.jl @@ -1,4 +1,4 @@ -margin = first(margins[margins.st .== st, :pct]) +#margin = first(margins[margins.st .== st, :pct]) poll_posterior = prior_poll posterior_mean = mean(poll_posterior[:deep][:p]) posterior_var = var( poll_posterior[:deep][:p]) @@ -11,10 +11,52 @@ prior_beta = (1 - posterior_mean) * (1 - posterior_mean) / posterior_var - 1) prior_dist = Beta(prior_alpha, prior_beta) +""" + @model poll_model(num_votes::Int64, num_wins::Int64, prior_dist::Distribution) + +Defines a probabilistic model for Bayesian inference of a binomial proportion using the Turing.jl library. + +This model estimates the probability `p` of success in a binomial experiment, given observed data and a prior distribution for `p`. + +**Parameters**: + +- `num_votes` (`Int64`): The total number of trials or votes. +- `num_wins` (`Int64`): The number of observed successes or wins. +- `prior_dist` (`Distribution`): The prior distribution for the probability `p`. This should be a univariate distribution over `[0, 1]`, such as `Beta` or `Uniform`. + +**Model Structure**: + +- `p ~ prior_dist`: The probability of success `p` is assigned the specified prior distribution. +- `num_wins ~ Binomial(num_votes, p)`: The observed number of successes `num_wins` is modeled as a binomial random variable with `num_votes` trials and success probability `p`. + +**Usage Example**: + +```julia +using Turing, Distributions + +# Define prior distribution +prior_dist = Beta(2, 2) # Example prior + +# Observed data +num_votes = 100 +num_wins = 60 + +# Define the model +model = poll_model(num_votes, num_wins, prior_dist) + +# Perform inference using NUTS sampler +chain = sample(model, NUTS(), 1000) + +# Summarize the results +describe(chain) +Notes: + +This model is compatible with any sampler from Turing.jl. +Ensure that prior_dist is appropriate for modeling probabilities (i.e., its support is within [0, 1]). +The function uses the @model macro from Turing.jl; make sure Turing is properly imported. +""" @model function poll_model(num_votes::Int64, num_wins::Int64, prior_dist::Distribution) - # Define the prior using the informed prior distribution p ~ prior_dist - # Define the likelihood with additional uncertainty num_wins ~ Binomial(num_votes, p) end model = poll_model(num_votes, num_wins, prior_dist) @@ -41,4 +83,4 @@ p_df[1,:] = out p_samples = chain[:p] p_vec = vec(p_samples) kde_result = kde(p_vec) -posterior_interval = p_intv \ No newline at end of file +posterior_interval = p_intv diff --git a/_assets/scripts/debris/wrong.csv b/_assets/scripts/objs/2020vote.csv similarity index 94% rename from _assets/scripts/debris/wrong.csv rename to _assets/scripts/objs/2020vote.csv index b1b20bb..af085e0 100644 --- a/_assets/scripts/debris/wrong.csv +++ b/_assets/scripts/objs/2020vote.csv @@ -23,7 +23,7 @@ ME1,266376,164045,1,0,102331 ME2,168696,196692,0,1,-27996 MD,1985023,976414,10,0,1008609 MA,2382202,1167202,11,0,1215000 -MI,2804040,2649852,15,0,154188 +MI,2804040,2649852,16,0,154188 MN,1717077,1484065,10,0,233012 MS,539398,756764,0,6,-217366 MO,1253014,1718736,0,10,-465722 @@ -37,12 +37,12 @@ NH,424937,365660,4,0,59277 NJ,2608400,1883313,14,0,725087 NM,501614,401894,5,0,99720 NY,5244886,3251997,29,0,1992889 -NC,2684292,2758775,0,16,-74483 +NC,2684292,2758775,0,15,-74483 ND,115042,235751,0,3,-120709 OH,2679165,3154834,0,18,-475669 OK,503890,1020280,0,7,-516390 OR,1340383,958448,7,0,381935 -PA,3458229,3377674,19,0,80555 +PA,3458229,3377674,20,0,80555 RI,307486,199922,4,0,107564 SC,1091541,1385103,0,9,-293562 SD,150471,261043,0,3,-110572 diff --git a/_assets/scripts/objs/2024_whatif.csv b/_assets/scripts/objs/2024_whatif.csv new file mode 100644 index 0000000..f8850c7 --- /dev/null +++ b/_assets/scripts/objs/2024_whatif.csv @@ -0,0 +1,57 @@ +st,biden_pop,trump_pop,margin,biden_col,trump_col +AK,153778,189951,-36173,0,3 +AL,849624,1441170,-591546,0,9 +AR,423932,760647,-336715,0,6 +AZ,1672143,1661686,10457,11,0 +CA,11110639,6006518,5104121,54,0 +CO,1804352,1364607,439745,10,0 +CT,1080831,714717,366114,7,0 +DC,317323,18586,298737,3,0 +DE,296268,200603,95665,3,0 +FL,5297045,5668731,-371686,0,30 +GA,2473633,2461854,11779,16,0 +HI,366130,196864,169266,4,0 +IA,759061,897672,-138611,0,6 +ID,287021,554119,-267098,0,4 +IL,3471915,2446891,1025024,19,0 +IN,1242498,1729857,-487359,0,11 +KS,570323,771406,-201083,0,6 +KY,772474,1326646,-554172,0,8 +LA,856034,1255776,-399742,0,8 +MA,2382202,1167202,1215000,11,0 +MD,1985023,976414,1008609,10,0 +ME,435072,360737,74335,1,0 +ME1,266376,164045,102331,1,0 +ME2,168696,196692,-27996,0,2 +MI,2804040,2649852,154188,15,0 +MN,1717077,1484065,233012,10,0 +MO,1253014,1718736,-465722,0,10 +MS,539398,756764,-217366,0,6 +MT,244786,343602,-98816,0,4 +NC,2684292,2758775,-74483,0,16 +ND,115042,235751,-120709,0,3 +NE,374583,556846,-182263,0,1 +NE1,132261,180290,-48029,0,1 +NE2,176468,154377,22091,1,0 +NE3,65854,222179,-156325,0,2 +NH,424937,365660,59277,4,0 +NJ,2608400,1883313,725087,14,0 +NM,501614,401894,99720,5,0 +NV,703486,669890,33596,6,0 +NY,5244886,3251997,1992889,28,0 +OH,2679165,3154834,-475669,0,17 +OK,503890,1020280,-516390,0,7 +OR,1340383,958448,381935,8,0 +PA,3458229,3377674,80555,19,0 +RI,307486,199922,107564,4,0 +SC,1091541,1385103,-293562,0,9 +SD,150471,261043,-110572,0,3 +TN,1143711,1852475,-708764,0,11 +TX,5259126,5890347,-631221,0,40 +UT,560282,865140,-304858,0,6 +VA,2413568,1962430,451138,13,0 +VT,242820,112704,130116,3,0 +WA,2369612,1584651,784961,12,0 +WI,1630866,1610184,20682,10,0 +WV,235984,545382,-309398,0,4 +WY,73491,193559,-120068,0,3 diff --git a/_assets/scripts/objs/2024vote.csv b/_assets/scripts/objs/2024vote.csv new file mode 100644 index 0000000..e97147e --- /dev/null +++ b/_assets/scripts/objs/2024vote.csv @@ -0,0 +1,57 @@ +st,biden_pop,trump_pop,margin,biden_col,trump_col,total_pop,pct,slice +AK,153778,189951,-36173,0,3,343729,0.4473815127615069,-0.052618487238493106 +AL,849624,1441170,-591546,0,9,2290794,0.3708862516664528,-0.12911374833354722 +AR,423932,760647,-336715,0,6,1184579,0.3578756672201685,-0.1421243327798315 +AZ,1672143,1661686,10457,11,0,3333829,0.5015683167912931,0.0015683167912931006 +CA,11110639,6006518,5104121,54,0,17117157,0.6490937134011214,0.14909371340112143 +CO,1804352,1364607,439745,10,0,3168959,0.5693831949230015,0.06938319492300149 +CT,1080831,714717,366114,7,0,1795548,0.6019504908807785,0.10195049088077845 +DC,317323,18586,298737,3,0,335909,0.9446695384761944,0.4446695384761944 +DE,296268,200603,95665,3,0,496871,0.5962674416498447,0.09626744164984469 +FL,5297045,5668731,-371686,0,30,10965776,0.48305245337858443,-0.016947546621415566 +GA,2473633,2461854,11779,16,0,4935487,0.5011932966290864,0.0011932966290864044 +HI,366130,196864,169266,4,0,562994,0.6503266464651488,0.15032664646514882 +IA,759061,897672,-138611,0,6,1656733,0.4581673691536295,-0.04183263084637051 +ID,287021,554119,-267098,0,4,841140,0.3412285707492213,-0.1587714292507787 +IL,3471915,2446891,1025024,19,0,5918806,0.5865904373280693,0.08659043732806926 +IN,1242498,1729857,-487359,0,11,2972355,0.4180180362036163,-0.08198196379638367 +KS,570323,771406,-201083,0,6,1341729,0.4250657174436865,-0.07493428255631351 +KY,772474,1326646,-554172,0,8,2099120,0.36799897099737033,-0.13200102900262967 +LA,856034,1255776,-399742,0,8,2111810,0.4053555954370895,-0.09464440456291051 +MA,2382202,1167202,1215000,11,0,3549404,0.6711554954014815,0.17115549540148145 +MD,1985023,976414,1008609,10,0,2961437,0.6702904704709234,0.17029047047092338 +ME,435072,360737,74335,2,0,795809,0.5467040458200397,0.04670404582003973 +ME1,266376,164045,102331,1,0,430421,0.618873149776614,0.118873149776614 +ME2,168696,196692,-27996,0,1,365388,0.4616900390817432,-0.03830996091825678 +MI,2804040,2649852,154188,15,0,5453892,0.5141355934440947,0.014135593444094652 +MN,1717077,1484065,233012,10,0,3201142,0.5363951364856667,0.036395136485666724 +MO,1253014,1718736,-465722,0,10,2971750,0.4216417935559855,-0.07835820644401448 +MS,539398,756764,-217366,0,6,1296162,0.4161501417261114,-0.08384985827388858 +MT,244786,343602,-98816,0,4,588388,0.41602819907951893,-0.08397180092048107 +NC,2684292,2758775,-74483,0,16,5443067,0.49315799346214184,-0.0068420065378581585 +ND,115042,235751,-120709,0,3,350793,0.3279483912164724,-0.1720516087835276 +NE,374583,556846,-182263,0,1,931429,0.40215947753398273,-0.09784052246601727 +NE1,132261,180290,-48029,0,1,312551,0.4231661392860685,-0.0768338607139315 +NE2,176468,154377,22091,1,0,330845,0.5333857244328916,0.03338572443289156 +NE3,65854,222179,-156325,0,2,288033,0.22863352463085826,-0.2713664753691417 +NH,424937,365660,59277,4,0,790597,0.5374887584951625,0.03748875849516253 +NJ,2608400,1883313,725087,14,0,4491713,0.5807138612818762,0.08071386128187619 +NM,501614,401894,99720,5,0,903508,0.5551849015171975,0.05518490151719746 +NV,703486,669890,33596,6,0,1373376,0.512231173400438,0.012231173400438 +NY,5244886,3251997,1992889,28,0,8496883,0.6172717689533915,0.11727176895339153 +OH,2679165,3154834,-475669,0,17,5833999,0.45923302352297285,-0.04076697647702715 +OK,503890,1020280,-516390,0,7,1524170,0.3305996050309349,-0.16940039496906512 +OR,1340383,958448,381935,8,0,2298831,0.5830715698544173,0.08307156985441733 +PA,3458229,3377674,80555,19,0,6835903,0.5058920525934906,0.005892052593490571 +RI,307486,199922,107564,4,0,507408,0.6059935988395926,0.10599359883959258 +SC,1091541,1385103,-293562,0,9,2476644,0.44073391250417904,-0.05926608749582096 +SD,150471,261043,-110572,0,3,411514,0.365652201383185,-0.134347798616815 +TN,1143711,1852475,-708764,0,11,2996186,0.38172229627933646,-0.11827770372066354 +TX,5259126,5890347,-631221,0,40,11149473,0.4716927876322047,-0.02830721236779532 +UT,560282,865140,-304858,0,6,1425422,0.39306394878148365,-0.10693605121851635 +VA,2413568,1962430,451138,13,0,4375998,0.551546869993999,0.051546869993999045 +VT,242820,112704,130116,3,0,355524,0.6829918655280656,0.18299186552806557 +WA,2369612,1584651,784961,12,0,3954263,0.599255031847907,0.09925503184790696 +WI,1630866,1610184,20682,10,0,3241050,0.5031906326653399,0.003190632665339921 +WV,235984,545382,-309398,0,4,781366,0.3020146768607797,-0.1979853231392203 +WY,73491,193559,-120068,0,3,267050,0.27519565624414905,-0.22480434375585095 diff --git a/_assets/scripts/objs/AZ_2020_p_sample.bson b/_assets/scripts/objs/AZ_2020_p_sample.bson new file mode 100644 index 0000000..a6259ac Binary files /dev/null and b/_assets/scripts/objs/AZ_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_apr_p_sample.bson b/_assets/scripts/objs/AZ_apr_p_sample.bson new file mode 100644 index 0000000..c60c96e Binary files /dev/null and b/_assets/scripts/objs/AZ_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_aug1_p_sample.bson b/_assets/scripts/objs/AZ_aug1_p_sample.bson new file mode 100644 index 0000000..2c606ed Binary files /dev/null and b/_assets/scripts/objs/AZ_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_aug2_p_sample.bson b/_assets/scripts/objs/AZ_aug2_p_sample.bson new file mode 100644 index 0000000..d86e13b Binary files /dev/null and b/_assets/scripts/objs/AZ_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_hyp_p_sample.bson b/_assets/scripts/objs/AZ_hyp_p_sample.bson new file mode 100644 index 0000000..9bb092a Binary files /dev/null and b/_assets/scripts/objs/AZ_hyp_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_jul2_p_sample.bson b/_assets/scripts/objs/AZ_jul2_p_sample.bson new file mode 100644 index 0000000..9c8481e Binary files /dev/null and b/_assets/scripts/objs/AZ_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_jul_p_sample.bson b/_assets/scripts/objs/AZ_jul_p_sample.bson new file mode 100644 index 0000000..ef27d89 Binary files /dev/null and b/_assets/scripts/objs/AZ_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_jun_p_sample.bson b/_assets/scripts/objs/AZ_jun_p_sample.bson new file mode 100644 index 0000000..b859596 Binary files /dev/null and b/_assets/scripts/objs/AZ_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_mar_p_sample.bson b/_assets/scripts/objs/AZ_mar_p_sample.bson new file mode 100644 index 0000000..bfe3ce4 Binary files /dev/null and b/_assets/scripts/objs/AZ_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_may_p_sample.bson b/_assets/scripts/objs/AZ_may_p_sample.bson new file mode 100644 index 0000000..d2f62d5 Binary files /dev/null and b/_assets/scripts/objs/AZ_may_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_oct1_p_sample.bson b/_assets/scripts/objs/AZ_oct1_p_sample.bson new file mode 100644 index 0000000..7447ca3 Binary files /dev/null and b/_assets/scripts/objs/AZ_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_oct2_p_sample.bson b/_assets/scripts/objs/AZ_oct2_p_sample.bson new file mode 100644 index 0000000..5460e2f Binary files /dev/null and b/_assets/scripts/objs/AZ_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_sep1_p_sample.bson b/_assets/scripts/objs/AZ_sep1_p_sample.bson new file mode 100644 index 0000000..b4928fc Binary files /dev/null and b/_assets/scripts/objs/AZ_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/AZ_sep2_p_sample.bson b/_assets/scripts/objs/AZ_sep2_p_sample.bson new file mode 100644 index 0000000..c8aad13 Binary files /dev/null and b/_assets/scripts/objs/AZ_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_2020_p_sample.bson b/_assets/scripts/objs/GA_2020_p_sample.bson new file mode 100644 index 0000000..8b555a3 Binary files /dev/null and b/_assets/scripts/objs/GA_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_apr_p_sample.bson b/_assets/scripts/objs/GA_apr_p_sample.bson new file mode 100644 index 0000000..86b0c65 Binary files /dev/null and b/_assets/scripts/objs/GA_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_aug1_p_sample.bson b/_assets/scripts/objs/GA_aug1_p_sample.bson new file mode 100644 index 0000000..c45170b Binary files /dev/null and b/_assets/scripts/objs/GA_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_aug2_p_sample.bson b/_assets/scripts/objs/GA_aug2_p_sample.bson new file mode 100644 index 0000000..3298f9c Binary files /dev/null and b/_assets/scripts/objs/GA_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_jul2_p_sample.bson b/_assets/scripts/objs/GA_jul2_p_sample.bson new file mode 100644 index 0000000..1f6c795 Binary files /dev/null and b/_assets/scripts/objs/GA_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_jul_p_sample.bson b/_assets/scripts/objs/GA_jul_p_sample.bson new file mode 100644 index 0000000..e8b523b Binary files /dev/null and b/_assets/scripts/objs/GA_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_jun_p_sample.bson b/_assets/scripts/objs/GA_jun_p_sample.bson new file mode 100644 index 0000000..70fd2dc Binary files /dev/null and b/_assets/scripts/objs/GA_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_mar_p_sample.bson b/_assets/scripts/objs/GA_mar_p_sample.bson new file mode 100644 index 0000000..9eb1e60 Binary files /dev/null and b/_assets/scripts/objs/GA_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_may_p_sample.bson b/_assets/scripts/objs/GA_may_p_sample.bson new file mode 100644 index 0000000..3435d9d Binary files /dev/null and b/_assets/scripts/objs/GA_may_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_oct1_p_sample.bson b/_assets/scripts/objs/GA_oct1_p_sample.bson new file mode 100644 index 0000000..7f08900 Binary files /dev/null and b/_assets/scripts/objs/GA_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_oct2_p_sample.bson b/_assets/scripts/objs/GA_oct2_p_sample.bson new file mode 100644 index 0000000..e917fa5 Binary files /dev/null and b/_assets/scripts/objs/GA_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_sep1_p_sample.bson b/_assets/scripts/objs/GA_sep1_p_sample.bson new file mode 100644 index 0000000..5d2cafd Binary files /dev/null and b/_assets/scripts/objs/GA_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/GA_sep2_p_sample.bson b/_assets/scripts/objs/GA_sep2_p_sample.bson new file mode 100644 index 0000000..9df3100 Binary files /dev/null and b/_assets/scripts/objs/GA_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_2020_p_sample.bson b/_assets/scripts/objs/MI_2020_p_sample.bson new file mode 100644 index 0000000..8a7d394 Binary files /dev/null and b/_assets/scripts/objs/MI_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_apr_p_sample.bson b/_assets/scripts/objs/MI_apr_p_sample.bson new file mode 100644 index 0000000..f2efc2d Binary files /dev/null and b/_assets/scripts/objs/MI_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_aug1_p_sample.bson b/_assets/scripts/objs/MI_aug1_p_sample.bson new file mode 100644 index 0000000..ee2fb80 Binary files /dev/null and b/_assets/scripts/objs/MI_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_aug2_p_sample.bson b/_assets/scripts/objs/MI_aug2_p_sample.bson new file mode 100644 index 0000000..39c6527 Binary files /dev/null and b/_assets/scripts/objs/MI_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_jul2_p_sample.bson b/_assets/scripts/objs/MI_jul2_p_sample.bson new file mode 100644 index 0000000..cdbf94e Binary files /dev/null and b/_assets/scripts/objs/MI_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_jul_p_sample.bson b/_assets/scripts/objs/MI_jul_p_sample.bson new file mode 100644 index 0000000..2f878b6 Binary files /dev/null and b/_assets/scripts/objs/MI_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_jun_p_sample.bson b/_assets/scripts/objs/MI_jun_p_sample.bson new file mode 100644 index 0000000..7440145 Binary files /dev/null and b/_assets/scripts/objs/MI_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_mar_p_sample.bson b/_assets/scripts/objs/MI_mar_p_sample.bson new file mode 100644 index 0000000..1b6b7eb Binary files /dev/null and b/_assets/scripts/objs/MI_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_may_p_sample.bson b/_assets/scripts/objs/MI_may_p_sample.bson new file mode 100644 index 0000000..3b38f9e Binary files /dev/null and b/_assets/scripts/objs/MI_may_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_oct1_p_sample.bson b/_assets/scripts/objs/MI_oct1_p_sample.bson new file mode 100644 index 0000000..489c660 Binary files /dev/null and b/_assets/scripts/objs/MI_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_oct2_p_sample.bson b/_assets/scripts/objs/MI_oct2_p_sample.bson new file mode 100644 index 0000000..06d05af Binary files /dev/null and b/_assets/scripts/objs/MI_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_sep1_p_sample.bson b/_assets/scripts/objs/MI_sep1_p_sample.bson new file mode 100644 index 0000000..940f12e Binary files /dev/null and b/_assets/scripts/objs/MI_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/MI_sep2_p_sample.bson b/_assets/scripts/objs/MI_sep2_p_sample.bson new file mode 100644 index 0000000..ac6f650 Binary files /dev/null and b/_assets/scripts/objs/MI_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_2020_p_sample.bson b/_assets/scripts/objs/NC_2020_p_sample.bson new file mode 100644 index 0000000..e2abe7a Binary files /dev/null and b/_assets/scripts/objs/NC_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_apr_p_sample.bson b/_assets/scripts/objs/NC_apr_p_sample.bson new file mode 100644 index 0000000..5c0136b Binary files /dev/null and b/_assets/scripts/objs/NC_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_aug1_p_sample.bson b/_assets/scripts/objs/NC_aug1_p_sample.bson new file mode 100644 index 0000000..67ce66f Binary files /dev/null and b/_assets/scripts/objs/NC_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_aug2_p_sample.bson b/_assets/scripts/objs/NC_aug2_p_sample.bson new file mode 100644 index 0000000..c0c5f96 Binary files /dev/null and b/_assets/scripts/objs/NC_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_jul2_p_sample.bson b/_assets/scripts/objs/NC_jul2_p_sample.bson new file mode 100644 index 0000000..c3693bb Binary files /dev/null and b/_assets/scripts/objs/NC_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_jul_p_sample.bson b/_assets/scripts/objs/NC_jul_p_sample.bson new file mode 100644 index 0000000..3363d5d Binary files /dev/null and b/_assets/scripts/objs/NC_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_jun_p_sample.bson b/_assets/scripts/objs/NC_jun_p_sample.bson new file mode 100644 index 0000000..cc7c1a7 Binary files /dev/null and b/_assets/scripts/objs/NC_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_mar_p_sample.bson b/_assets/scripts/objs/NC_mar_p_sample.bson new file mode 100644 index 0000000..b06cc40 Binary files /dev/null and b/_assets/scripts/objs/NC_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_may_p_sample.bson b/_assets/scripts/objs/NC_may_p_sample.bson new file mode 100644 index 0000000..adb6791 Binary files /dev/null and b/_assets/scripts/objs/NC_may_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_oct1_p_sample.bson b/_assets/scripts/objs/NC_oct1_p_sample.bson new file mode 100644 index 0000000..94b7de9 Binary files /dev/null and b/_assets/scripts/objs/NC_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_oct2_p_sample.bson b/_assets/scripts/objs/NC_oct2_p_sample.bson new file mode 100644 index 0000000..ecc5e9d Binary files /dev/null and b/_assets/scripts/objs/NC_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_sep1_p_sample.bson b/_assets/scripts/objs/NC_sep1_p_sample.bson new file mode 100644 index 0000000..dc6b385 Binary files /dev/null and b/_assets/scripts/objs/NC_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/NC_sep2_p_sample.bson b/_assets/scripts/objs/NC_sep2_p_sample.bson new file mode 100644 index 0000000..163091d Binary files /dev/null and b/_assets/scripts/objs/NC_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_2020_p_sample.bson b/_assets/scripts/objs/NV_2020_p_sample.bson new file mode 100644 index 0000000..877b6e5 Binary files /dev/null and b/_assets/scripts/objs/NV_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_apr_p_sample.bson b/_assets/scripts/objs/NV_apr_p_sample.bson new file mode 100644 index 0000000..e1bc114 Binary files /dev/null and b/_assets/scripts/objs/NV_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_aug1_p_sample.bson b/_assets/scripts/objs/NV_aug1_p_sample.bson new file mode 100644 index 0000000..5f4817d Binary files /dev/null and b/_assets/scripts/objs/NV_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_aug2_p_sample.bson b/_assets/scripts/objs/NV_aug2_p_sample.bson new file mode 100644 index 0000000..bc43d83 Binary files /dev/null and b/_assets/scripts/objs/NV_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_jul2_p_sample.bson b/_assets/scripts/objs/NV_jul2_p_sample.bson new file mode 100644 index 0000000..a836583 Binary files /dev/null and b/_assets/scripts/objs/NV_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_jul_p_sample.bson b/_assets/scripts/objs/NV_jul_p_sample.bson new file mode 100644 index 0000000..bd7f116 Binary files /dev/null and b/_assets/scripts/objs/NV_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_jun_p_sample.bson b/_assets/scripts/objs/NV_jun_p_sample.bson new file mode 100644 index 0000000..31fbb99 Binary files /dev/null and b/_assets/scripts/objs/NV_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_mar_p_sample.bson b/_assets/scripts/objs/NV_mar_p_sample.bson new file mode 100644 index 0000000..c588910 Binary files /dev/null and b/_assets/scripts/objs/NV_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_may_p_sample.bson b/_assets/scripts/objs/NV_may_p_sample.bson new file mode 100644 index 0000000..601b0ae Binary files /dev/null and b/_assets/scripts/objs/NV_may_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_oct1_p_sample.bson b/_assets/scripts/objs/NV_oct1_p_sample.bson new file mode 100644 index 0000000..10d7f11 Binary files /dev/null and b/_assets/scripts/objs/NV_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_oct2_p_sample.bson b/_assets/scripts/objs/NV_oct2_p_sample.bson new file mode 100644 index 0000000..27fd58c Binary files /dev/null and b/_assets/scripts/objs/NV_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_sep1_p_sample.bson b/_assets/scripts/objs/NV_sep1_p_sample.bson new file mode 100644 index 0000000..65918c3 Binary files /dev/null and b/_assets/scripts/objs/NV_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/NV_sep2_p_sample.bson b/_assets/scripts/objs/NV_sep2_p_sample.bson new file mode 100644 index 0000000..600548f Binary files /dev/null and b/_assets/scripts/objs/NV_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_2020_p_sample.bson b/_assets/scripts/objs/PA_2020_p_sample.bson new file mode 100644 index 0000000..f2621bf Binary files /dev/null and b/_assets/scripts/objs/PA_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_apr_p_sample.bson b/_assets/scripts/objs/PA_apr_p_sample.bson new file mode 100644 index 0000000..9b5714e Binary files /dev/null and b/_assets/scripts/objs/PA_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_aug1_p_sample.bson b/_assets/scripts/objs/PA_aug1_p_sample.bson new file mode 100644 index 0000000..d905f50 Binary files /dev/null and b/_assets/scripts/objs/PA_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_aug2_p_sample.bson b/_assets/scripts/objs/PA_aug2_p_sample.bson new file mode 100644 index 0000000..06afa5b Binary files /dev/null and b/_assets/scripts/objs/PA_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_jul2_p_sample.bson b/_assets/scripts/objs/PA_jul2_p_sample.bson new file mode 100644 index 0000000..dfcea23 Binary files /dev/null and b/_assets/scripts/objs/PA_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_jul_p_sample.bson b/_assets/scripts/objs/PA_jul_p_sample.bson new file mode 100644 index 0000000..91df1a8 Binary files /dev/null and b/_assets/scripts/objs/PA_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_jun_p_sample.bson b/_assets/scripts/objs/PA_jun_p_sample.bson new file mode 100644 index 0000000..6a5ca58 Binary files /dev/null and b/_assets/scripts/objs/PA_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_mar_p_sample.bson b/_assets/scripts/objs/PA_mar_p_sample.bson new file mode 100644 index 0000000..34eb1de Binary files /dev/null and b/_assets/scripts/objs/PA_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_may_p_sample.bson b/_assets/scripts/objs/PA_may_p_sample.bson new file mode 100644 index 0000000..a85a1c7 Binary files /dev/null and b/_assets/scripts/objs/PA_may_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_oct1_p_sample.bson b/_assets/scripts/objs/PA_oct1_p_sample.bson new file mode 100644 index 0000000..50e097a Binary files /dev/null and b/_assets/scripts/objs/PA_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_oct2_p_sample.bson b/_assets/scripts/objs/PA_oct2_p_sample.bson new file mode 100644 index 0000000..9c6cde0 Binary files /dev/null and b/_assets/scripts/objs/PA_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_sep1_p_sample.bson b/_assets/scripts/objs/PA_sep1_p_sample.bson new file mode 100644 index 0000000..173be66 Binary files /dev/null and b/_assets/scripts/objs/PA_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/PA_sep2_p_sample.bson b/_assets/scripts/objs/PA_sep2_p_sample.bson new file mode 100644 index 0000000..e1915be Binary files /dev/null and b/_assets/scripts/objs/PA_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_2020_p_sample.bson b/_assets/scripts/objs/WI_2020_p_sample.bson new file mode 100644 index 0000000..a47a6bb Binary files /dev/null and b/_assets/scripts/objs/WI_2020_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_apr_p_sample.bson b/_assets/scripts/objs/WI_apr_p_sample.bson new file mode 100644 index 0000000..edcbb81 Binary files /dev/null and b/_assets/scripts/objs/WI_apr_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_aug1_p_sample.bson b/_assets/scripts/objs/WI_aug1_p_sample.bson new file mode 100644 index 0000000..4958ea5 Binary files /dev/null and b/_assets/scripts/objs/WI_aug1_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_aug2_p_sample.bson b/_assets/scripts/objs/WI_aug2_p_sample.bson new file mode 100644 index 0000000..ff56698 Binary files /dev/null and b/_assets/scripts/objs/WI_aug2_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_jul2_p_sample.bson b/_assets/scripts/objs/WI_jul2_p_sample.bson new file mode 100644 index 0000000..c1fa1f7 Binary files /dev/null and b/_assets/scripts/objs/WI_jul2_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_jul_p_sample.bson b/_assets/scripts/objs/WI_jul_p_sample.bson new file mode 100644 index 0000000..5055906 Binary files /dev/null and b/_assets/scripts/objs/WI_jul_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_jun_p_sample.bson b/_assets/scripts/objs/WI_jun_p_sample.bson new file mode 100644 index 0000000..f337110 Binary files /dev/null and b/_assets/scripts/objs/WI_jun_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_mar_p_sample.bson b/_assets/scripts/objs/WI_mar_p_sample.bson new file mode 100644 index 0000000..c892bef Binary files /dev/null and b/_assets/scripts/objs/WI_mar_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_may_p_sample.bson b/_assets/scripts/objs/WI_may_p_sample.bson new file mode 100644 index 0000000..d9bb3fd Binary files /dev/null and b/_assets/scripts/objs/WI_may_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_oct1_p_sample.bson b/_assets/scripts/objs/WI_oct1_p_sample.bson new file mode 100644 index 0000000..26af6ed Binary files /dev/null and b/_assets/scripts/objs/WI_oct1_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_oct2_p_sample.bson b/_assets/scripts/objs/WI_oct2_p_sample.bson new file mode 100644 index 0000000..8b5bbc8 Binary files /dev/null and b/_assets/scripts/objs/WI_oct2_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_sep1_p_sample.bson b/_assets/scripts/objs/WI_sep1_p_sample.bson new file mode 100644 index 0000000..a88c25d Binary files /dev/null and b/_assets/scripts/objs/WI_sep1_p_sample.bson differ diff --git a/_assets/scripts/objs/WI_sep2_p_sample.bson b/_assets/scripts/objs/WI_sep2_p_sample.bson new file mode 100644 index 0000000..3e3be86 Binary files /dev/null and b/_assets/scripts/objs/WI_sep2_p_sample.bson differ diff --git a/_assets/scripts/objs/apr_poll.csv b/_assets/scripts/objs/apr_poll.csv new file mode 100644 index 0000000..966bc0b --- /dev/null +++ b/_assets/scripts/objs/apr_poll.csv @@ -0,0 +1,20 @@ +months[apr][AZ][bl2] = PA(43,49, 801) +months[apr][GA][bl2] = PA(45,47, 802) +months[apr][MI][bi2] = PA(43,51, 708) +months[apr][AZ][ec2] = PA(44,48,1000) +months[apr][GA][ec2] = PA(44,47,1000) +months[apr][MI][ec2] = PA(44,45,1000) +months[apr][NV][ec2] = PA(44,45,1000) +months[apr][NC][ec2] = PA(42,47,1000) +months[apr][PA][ec2] = PA(45,47,1000) +months[apr][WI][ec2] = PA(45,47,1000) +months[apr][PA][bi2] = PA(46,47, 803) +months[apr][WI][bl2] = PA(44,48, 703) +months[apr][GA][fo2] = PA(45,51,1128) +months[apr][MI][mr2] = PA(46,42, 600) +months[apr][MI][fo2] = PA(46,49,1106) +months[apr][MI][cb2] = PA(41,49,1287) +months[apr][NC][bl2] = PA(41,51, 703) +months[apr][NV][bl2] = PA(43,51, 450) +months[apr][PA][bb2] = PA(49,50,1306) +months[apr][WI][fo2] = PA(48,48,1198) diff --git a/_assets/scripts/objs/apr_polls.bson b/_assets/scripts/objs/apr_polls.bson new file mode 100644 index 0000000..3eade1c Binary files /dev/null and b/_assets/scripts/objs/apr_polls.bson differ diff --git a/_assets/scripts/objs/aug1_polls.bson b/_assets/scripts/objs/aug1_polls.bson new file mode 100644 index 0000000..685ca2b Binary files /dev/null and b/_assets/scripts/objs/aug1_polls.bson differ diff --git a/_assets/scripts/objs/aug2_polls.bson b/_assets/scripts/objs/aug2_polls.bson new file mode 100644 index 0000000..a141ea1 Binary files /dev/null and b/_assets/scripts/objs/aug2_polls.bson differ diff --git a/_assets/scripts/objs/aug_polls.bson b/_assets/scripts/objs/aug_polls.bson new file mode 100644 index 0000000..7f2be9f Binary files /dev/null and b/_assets/scripts/objs/aug_polls.bson differ diff --git a/_assets/scripts/objs/college.csv b/_assets/scripts/objs/college.csv new file mode 100644 index 0000000..4316bb1 --- /dev/null +++ b/_assets/scripts/objs/college.csv @@ -0,0 +1,57 @@ +state,po,ev +Alabama,AL,9 +Alaska,AK,3 +Arizona,AZ,11 +Arkansas,AR,6 +California,CA,54 +Colorado,CO,10 +Connecticut,CT,7 +Delaware,DE,3 +DC,DC,3 +Florida,FL,30 +Georgia,GA,16 +Hawaii,HI,4 +Idaho,ID,4 +Illinois,IL,19 +Indiana,IN,11 +Iowa,IA,6 +Kansas,KS,6 +Kentucky,KY,8 +Louisiana,LA,8 +Maine,ME,2 +ME1,ME1,1 +ME2,ME2,1 +Maryland,MD,10 +Massachusetts,MA,11 +Michigan,MI,15 +Minnesota,MN,10 +Mississippi,MS,6 +Missouri,MO,10 +Montana,MT,4 +Nebraska,NE,2 +NE1,NE1,1 +NE2,NE2,1 +NE3,NE3,1 +Nevada,NV,6 +New Hampshire,NH,4 +New Jersey,NJ,14 +New Mexico,NM,5 +New York,NY,28 +North Carolina,NC,16 +North Dakota,ND,3 +Ohio,OH,17 +Oklahoma,OK,7 +Oregon,OR,8 +Pennsylvania,PA,19 +Rhode Island,RI,4 +South Carolina,SC,9 +South Dakota,SD,3 +Tennessee,TN,11 +Texas,TX,40 +Utah,UT,6 +Vermont,VT,3 +Virginia,VA,13 +Washington,WA,12 +West Virginia,WV,4 +Wisconsin,WI,10 +Wyoming,WY,3 \ No newline at end of file diff --git a/_assets/scripts/objs/election.csv b/_assets/scripts/objs/election.csv new file mode 100644 index 0000000..a002ed5 --- /dev/null +++ b/_assets/scripts/objs/election.csv @@ -0,0 +1,57 @@ +state,po,ev,harris,trump,time +Kentucky,KY,8,0,8,2024-11-05 19:00 +Vermont,VT,3,3,0,2024-11-05 19:00 +West Virginia,WV,4,0,4,2024-11-05 19:30 +Virginia,VA,13,13,0,2024-11-05 19:36 +South Carolina,SC,9,0,9,2024-11-05 19:56 +Alabama,AL,9,0,9,2024-11-05 20:00 +Mississippi,MS,6,0,6,2024-11-05 20:00 +Tennessee,TN,11,0,11,2024-11-05 20:00 +Oklahoma,OK,7,0,7,2024-11-05 20:00 +Connecticut,CT,7,7,0,2024-11-05 20:00 +Delaware,DE,3,3,0,2024-11-05 20:00 +Illinois,IL,19,19,0,2024-11-05 20:00 +Maryland,MD,10,10,0,2024-11-05 20:00 +Massachusetts,MA,11,11,0,2024-11-05 20:00 +New Jersey,NJ,14,14,0,2024-11-05 20:00 +Rhode Island,RI,4,4,0,2024-11-05 20:00 +Arkansas,AR,6,0,6,2024-11-05 20:30 +Indiana,IN,11,0,11,2024-11-05 20:52 +North Dakota,ND,3,0,3,2024-11-05 21:00 +South Dakota,SD,3,0,3,2024-11-05 21:00 +Wyoming,WY,3,0,3,2024-11-05 21:00 +Louisiana,LA,8,0,8,2024-11-05 21:00 +New York,NY,28,28,0,2024-11-05 21:00 +New Mexico,NM,5,5,0,2024-11-05 21:00 +Nebraska,NE,2,0,1,2024-11-05 21:00 +NE1,NE1,1,0,1,2024-11-05 21:00 +NE2,NE2,1,1,0,2024-11-05 21:00 +NE3,NE3,1,0,2,2024-11-05 21:00 +DC,DC,3,3,0,2024-11-05 21:27 +Colorado,CO,10,10,0,2024-11-05 21:37 +Kansas,KS,6,0,6,2024-11-05 21:59 +Missouri,MO,10,0,10,2024-11-05 22:31 +New Hampshire,NH,4,4,0,2024-11-05 22:54 +Idaho,ID,4,0,4,2024-11-05 23:00 +California,CA,54,54,0,2024-11-05 23:00 +Oregon,OR,8,8,0,2024-11-05 23:00 +Washington,WA,12,12,0,2024-11-05 23:00 +Utah,UT,6,0,6,2024-11-05 23:08 +Hawaii,HI,4,4,0,2024-11-06 00:06 +Minnesota,MN,10,10,0,2024-11-06 00:13 +Ohio,OH,17,0,17,2024-11-06 00:19 +Montana,MT,4,0,4,2024-11-06 00:20 +Iowa,IA,6,0,6,2024-11-06 00:21 +Florida,FL,30,0,30,2024-11-06 00:35 +Texas,TX,40,0,40,2024-11-06 01:06 +Arizona,AZ,11,11,0,2024-11-06 02:51 +Maine,ME,2,2,0,2024-11-06 03:06 +ME1,ME1,1,1,0,2024-11-06 03:06 +ME2,ME2,1,0,1,2024-11-06 13:24 +Wisconsin,WI,10,10,0,2024-11-06 14:16 +Michigan,MI,15,15,0,2024-11-06 17:58 +Pennsylvania,PA,19,19,0,2024-11-06 11:25 +Nevada,NV,6,6,0,2024-11-06 12:13 +Alaska,AK,3,0,3,2024-11-09 00:00 +Georgia,GA,16,16,0,2024-11-11 00:00 +North Carolina,NC,16,0,16,2024-11-11 00:00 diff --git a/_assets/scripts/objs/election_priors b/_assets/scripts/objs/election_priors new file mode 100644 index 0000000..6378d59 --- /dev/null +++ b/_assets/scripts/objs/election_priors @@ -0,0 +1,8 @@ +st,num_wins,num_votes +AZ,1672143,3333829 +GA,2473633,4935487 +MI,2804040,5453892 +NV,703486,1373376 +NC,2684292,5443067 +PA,3458229,6835903 +WI,1630866,3241050 diff --git a/_assets/scripts/objs/election_priors.csv b/_assets/scripts/objs/election_priors.csv new file mode 100644 index 0000000..6378d59 --- /dev/null +++ b/_assets/scripts/objs/election_priors.csv @@ -0,0 +1,8 @@ +st,num_wins,num_votes +AZ,1672143,3333829 +GA,2473633,4935487 +MI,2804040,5453892 +NV,703486,1373376 +NC,2684292,5443067 +PA,3458229,6835903 +WI,1630866,3241050 diff --git a/_assets/scripts/objs/jul2_polls.bson b/_assets/scripts/objs/jul2_polls.bson new file mode 100644 index 0000000..2bceeda Binary files /dev/null and b/_assets/scripts/objs/jul2_polls.bson differ diff --git a/_assets/scripts/objs/jul_polls.bson b/_assets/scripts/objs/jul_polls.bson new file mode 100644 index 0000000..37025af Binary files /dev/null and b/_assets/scripts/objs/jul_polls.bson differ diff --git a/_assets/scripts/objs/jul_pre_polls.bson b/_assets/scripts/objs/jul_pre_polls.bson new file mode 100644 index 0000000..3e177ba Binary files /dev/null and b/_assets/scripts/objs/jul_pre_polls.bson differ diff --git a/_assets/scripts/objs/jun_polls.bson b/_assets/scripts/objs/jun_polls.bson new file mode 100644 index 0000000..88fb9c2 Binary files /dev/null and b/_assets/scripts/objs/jun_polls.bson differ diff --git a/_assets/scripts/debris/mar_polls.bson b/_assets/scripts/objs/mar_polls.bson similarity index 100% rename from _assets/scripts/debris/mar_polls.bson rename to _assets/scripts/objs/mar_polls.bson diff --git a/_assets/scripts/objs/margins.csv b/_assets/scripts/objs/margins.csv new file mode 100644 index 0000000..94d1b45 --- /dev/null +++ b/_assets/scripts/objs/margins.csv @@ -0,0 +1,8 @@ +po,margin +AZ,50.15683167912931 +PA,50.58920525934906 +NV,51.2231173400438 +WI,50.319063266533995 +MI,51.413559344409464 +GA,50.11932966290864 +NC,49.315799346214185 diff --git a/_assets/scripts/objs/may_polls.bson b/_assets/scripts/objs/may_polls.bson new file mode 100644 index 0000000..71bedd3 Binary files /dev/null and b/_assets/scripts/objs/may_polls.bson differ diff --git a/_assets/scripts/objs/meta_cohort_2020.bson b/_assets/scripts/objs/meta_cohort_2020.bson new file mode 100644 index 0000000..cb90ef8 Binary files /dev/null and b/_assets/scripts/objs/meta_cohort_2020.bson differ diff --git a/_assets/scripts/objs/meta_cohort_2022.bson b/_assets/scripts/objs/meta_cohort_2022.bson new file mode 100644 index 0000000..627a91d Binary files /dev/null and b/_assets/scripts/objs/meta_cohort_2022.bson differ diff --git a/_assets/scripts/objs/meta_new_voters.bson b/_assets/scripts/objs/meta_new_voters.bson new file mode 100644 index 0000000..b5f0c1d Binary files /dev/null and b/_assets/scripts/objs/meta_new_voters.bson differ diff --git a/_assets/scripts/objs/mon_template.bson b/_assets/scripts/objs/mon_template.bson new file mode 100644 index 0000000..2bceeda Binary files /dev/null and b/_assets/scripts/objs/mon_template.bson differ diff --git a/_assets/scripts/debris/new_prior.bson b/_assets/scripts/objs/new_prior.bson similarity index 100% rename from _assets/scripts/debris/new_prior.bson rename to _assets/scripts/objs/new_prior.bson diff --git a/_assets/scripts/objs/outcome.csv b/_assets/scripts/objs/outcome.csv new file mode 100644 index 0000000..bd5fcb3 --- /dev/null +++ b/_assets/scripts/objs/outcome.csv @@ -0,0 +1,128 @@ +combo,votes,harris,trump,result +NV,6,232,306,Trump +WI,10,236,302,Trump +AZ,11,237,301,Trump +MI,15,241,297,Trump +NV and WI,16,242,296,Trump +GA,16,242,296,Trump +NC,16,242,296,Trump +NV and AZ,17,243,295,Trump +PA,19,245,293,Trump +NV and MI,21,247,291,Trump +WI and AZ,21,247,291,Trump +NV and GA,22,248,290,Trump +NV and NC,22,248,290,Trump +NV and PA,25,251,287,Trump +WI and MI,25,251,287,Trump +WI and GA,26,252,286,Trump +WI and NC,26,252,286,Trump +AZ and MI,26,252,286,Trump +AZ and GA,27,253,285,Trump +AZ and NC,27,253,285,Trump +"NV, WI and AZ",27,253,285,Trump +WI and PA,29,255,283,Trump +AZ and PA,30,256,282,Trump +GA and MI,31,257,281,Trump +MI and NC,31,257,281,Trump +"NV, WI and MI",31,257,281,Trump +GA and NC,32,258,280,Trump +"NV, WI and GA",32,258,280,Trump +"NV, WI and NC",32,258,280,Trump +"NV, AZ and MI",32,258,280,Trump +"NV, AZ and GA",33,259,279,Trump +"NV, AZ and NC",33,259,279,Trump +MI and PA,34,260,278,Trump +GA and PA,35,261,277,Trump +PA and NC,35,261,277,Trump +"NV, WI and PA",35,261,277,Trump +"NV, AZ and PA",36,262,276,Trump +"WI, AZ and MI",36,262,276,Trump +"NV, GA and MI",37,263,275,Trump +"NV, MI and NC",37,263,275,Trump +"WI, AZ and GA",37,263,275,Trump +"WI, AZ and NC",37,263,275,Trump +"NV, GA and NC",38,264,274,Trump +"NV, MI and PA",40,266,272,Trump +"WI, AZ and PA",40,266,272,Trump +"NV, GA and PA",41,267,271,Trump +"NV, PA and NC",41,267,271,Trump +"WI, GA and MI",41,267,271,Trump +"WI, MI and NC",41,267,271,Trump +"NV, WI, AZ and MI",42,268,270,Trump +"WI, GA and NC",42,268,270,Trump +"AZ, GA and MI",42,268,270,Trump +"AZ, MI and NC",42,268,270,Trump +"NV, WI, AZ and GA",43,269,269,Tie +"NV, WI, AZ and NC",43,269,269,Tie +"AZ, GA and NC",43,269,269,Tie +"WI, MI and PA",44,270,268,Harris +"WI, GA and PA",45,271,267,Harris +"WI, PA and NC",45,271,267,Harris +"AZ, MI and PA",45,271,267,Harris +"NV, WI, AZ and PA",46,272,266,Harris +"AZ, GA and PA",46,272,266,Harris +"AZ, PA and NC",46,272,266,Harris +"NV, WI, GA and MI",47,273,265,Harris +"NV, WI, MI and NC",47,273,265,Harris +"GA, MI and NC",47,273,265,Harris +"NV, WI, GA and NC",48,274,264,Harris +"NV, AZ, GA and MI",48,274,264,Harris +"NV, AZ, MI and NC",48,274,264,Harris +"NV, AZ, GA and NC",49,275,263,Harris +"NV, WI, MI and PA",50,276,262,Harris +"GA, MI and PA",50,276,262,Harris +"MI, PA and NC",50,276,262,Harris +"NV, WI, GA and PA",51,277,261,Harris +"NV, WI, PA and NC",51,277,261,Harris +"NV, AZ, MI and PA",51,277,261,Harris +"GA, PA and NC",51,277,261,Harris +"NV, AZ, GA and PA",52,278,260,Harris +"NV, AZ, PA and NC",52,278,260,Harris +"WI, AZ, GA and MI",52,278,260,Harris +"WI, AZ, MI and NC",52,278,260,Harris +"NV, GA, MI and NC",53,279,259,Harris +"WI, AZ, GA and NC",53,279,259,Harris +"WI, AZ, MI and PA",55,281,257,Harris +"NV, GA, MI and PA",56,282,256,Harris +"NV, MI, PA and NC",56,282,256,Harris +"WI, AZ, GA and PA",56,282,256,Harris +"WI, AZ, PA and NC",56,282,256,Harris +"NV, GA, PA and NC",57,283,255,Harris +"WI, GA, MI and NC",57,283,255,Harris +"NV, WI, AZ, GA and MI",58,284,254,Harris +"NV, WI, AZ, MI and NC",58,284,254,Harris +"AZ, GA, MI and NC",58,284,254,Harris +"NV, WI, AZ, GA and NC",59,285,253,Harris +"WI, GA, MI and PA",60,286,252,Harris +"WI, MI, PA and NC",60,286,252,Harris +"NV, WI, AZ, MI and PA",61,287,251,Harris +"WI, GA, PA and NC",61,287,251,Harris +"AZ, GA, MI and PA",61,287,251,Harris +"AZ, MI, PA and NC",61,287,251,Harris +"NV, WI, AZ, GA and PA",62,288,250,Harris +"NV, WI, AZ, PA and NC",62,288,250,Harris +"AZ, GA, PA and NC",62,288,250,Harris +"NV, WI, GA, MI and NC",63,289,249,Harris +"NV, AZ, GA, MI and NC",64,290,248,Harris +"NV, WI, GA, MI and PA",66,292,246,Harris +"NV, WI, MI, PA and NC",66,292,246,Harris +"GA, MI, PA and NC",66,292,246,Harris +"NV, WI, GA, PA and NC",67,293,245,Harris +"NV, AZ, GA, MI and PA",67,293,245,Harris +"NV, AZ, MI, PA and NC",67,293,245,Harris +"NV, AZ, GA, PA and NC",68,294,244,Harris +"WI, AZ, GA, MI and NC",68,294,244,Harris +"WI, AZ, GA, MI and PA",71,297,241,Harris +"WI, AZ, MI, PA and NC",71,297,241,Harris +"NV, GA, MI, PA and NC",72,298,240,Harris +"WI, AZ, GA, PA and NC",72,298,240,Harris +"NV, WI, AZ, GA, MI and NC",74,300,238,Harris +"WI, GA, MI, PA and NC",76,302,236,Harris +"AZ, GA, MI, PA and NC",77,303,235,Harris +"NV, WI, AZ, GA, MI and PA",77,303,235,Harris +"NV, WI, AZ, MI, PA and NC",77,303,235,Harris +"NV, WI, AZ, GA, PA and NC",78,304,234,Harris +"NV, WI, GA, MI, PA and NC",82,308,230,Harris +"NV, AZ, GA, MI, PA and NC",83,309,229,Harris +"WI, AZ, GA, MI, PA and NC",87,313,225,Harris +"NV, WI, AZ, GA, MI, PA and NC",93,319,219,Harris diff --git a/_assets/scripts/objs/racecard.csv b/_assets/scripts/objs/racecard.csv new file mode 100644 index 0000000..80c2976 --- /dev/null +++ b/_assets/scripts/objs/racecard.csv @@ -0,0 +1,57 @@ +state,po,ev,harris,trump,time,margin,pop_harris,pop_trump,pop_total +Kentucky,KY,8,0,8,2024-11-05 19:00,-0.13200102900262967,0.0,0.0,0.0 +Vermont,VT,3,3,0,2024-11-05 19:00,0.18299186552806557,0.0,0.0,0.0 +West Virginia,WV,4,0,4,2024-11-05 19:30,-0.1979853231392203,0.0,0.0,0.0 +Virginia,VA,13,13,0,2024-11-05 19:36,0.051546869993999045,0.0,0.0,0.0 +South Carolina,SC,9,0,9,2024-11-05 19:56,-0.05926608749582096,0.0,0.0,0.0 +Alabama,AL,9,0,9,2024-11-05 20:00,-0.12911374833354722,0.0,0.0,0.0 +Connecticut,CT,7,7,0,2024-11-05 20:00,0.10195049088077845,0.0,0.0,0.0 +Delaware,DE,3,3,0,2024-11-05 20:00,0.09626744164984469,0.0,0.0,0.0 +Illinois,IL,19,19,0,2024-11-05 20:00,0.08659043732806926,0.0,0.0,0.0 +Massachusetts,MA,11,11,0,2024-11-05 20:00,0.17115549540148145,0.0,0.0,0.0 +Maryland,MD,10,10,0,2024-11-05 20:00,0.17029047047092338,0.0,0.0,0.0 +Mississippi,MS,6,0,6,2024-11-05 20:00,-0.08384985827388858,0.0,0.0,0.0 +New Jersey,NJ,14,14,0,2024-11-05 20:00,0.08071386128187619,0.0,0.0,0.0 +Oklahoma,OK,7,0,7,2024-11-05 20:00,-0.16940039496906512,0.0,0.0,0.0 +Rhode Island,RI,4,4,0,2024-11-05 20:00,0.10599359883959258,0.0,0.0,0.0 +Tennessee,TN,11,0,11,2024-11-05 20:00,-0.11827770372066354,0.0,0.0,0.0 +Arkansas,AR,6,0,6,2024-11-05 20:30,-0.1421243327798315,0.0,0.0,0.0 +Indiana,IN,11,0,11,2024-11-05 20:52,-0.08198196379638367,0.0,0.0,0.0 +Louisiana,LA,8,0,8,2024-11-05 21:00,-0.09464440456291051,0.0,0.0,0.0 +North Dakota,ND,3,0,3,2024-11-05 21:00,-0.1720516087835276,0.0,0.0,0.0 +Nebraska,NE,2,0,1,2024-11-05 21:00,-0.09784052246601727,0.0,0.0,0.0 +NE1,NE1,1,0,1,2024-11-05 21:00,-0.0768338607139315,0.0,0.0,0.0 +NE2,NE2,1,1,0,2024-11-05 21:00,0.03338572443289156,0.0,0.0,0.0 +NE3,NE3,1,0,2,2024-11-05 21:00,-0.2713664753691417,0.0,0.0,0.0 +New Mexico,NM,5,5,0,2024-11-05 21:00,0.05518490151719746,0.0,0.0,0.0 +New York,NY,28,28,0,2024-11-05 21:00,0.11727176895339153,0.0,0.0,0.0 +South Dakota,SD,3,0,3,2024-11-05 21:00,-0.134347798616815,0.0,0.0,0.0 +Wyoming,WY,3,0,3,2024-11-05 21:00,-0.22480434375585095,0.0,0.0,0.0 +DC,DC,3,3,0,2024-11-05 21:27,0.4446695384761944,0.0,0.0,0.0 +Colorado,CO,10,10,0,2024-11-05 21:37,0.06938319492300149,0.0,0.0,0.0 +Kansas,KS,6,0,6,2024-11-05 21:59,-0.07493428255631351,0.0,0.0,0.0 +Missouri,MO,10,0,10,2024-11-05 22:31,-0.07835820644401448,0.0,0.0,0.0 +New Hampshire,NH,4,4,0,2024-11-05 22:54,0.03748875849516253,0.0,0.0,0.0 +California,CA,54,54,0,2024-11-05 23:00,0.14909371340112143,0.0,0.0,0.0 +Idaho,ID,4,0,4,2024-11-05 23:00,-0.1587714292507787,0.0,0.0,0.0 +Oregon,OR,8,8,0,2024-11-05 23:00,0.08307156985441733,0.0,0.0,0.0 +Washington,WA,12,12,0,2024-11-05 23:00,0.09925503184790696,0.0,0.0,0.0 +Utah,UT,6,0,6,2024-11-05 23:08,-0.10693605121851635,0.0,0.0,0.0 +Hawaii,HI,4,4,0,2024-11-06 00:06,0.15032664646514882,0.0,0.0,0.0 +Minnesota,MN,10,10,0,2024-11-06 00:13,0.036395136485666724,0.0,0.0,0.0 +Ohio,OH,17,0,17,2024-11-06 00:19,-0.04076697647702715,0.0,0.0,0.0 +Montana,MT,4,0,4,2024-11-06 00:20,-0.08397180092048107,0.0,0.0,0.0 +Iowa,IA,6,0,6,2024-11-06 00:21,-0.04183263084637051,0.0,0.0,0.0 +Florida,FL,30,0,30,2024-11-06 00:35,-0.016947546621415566,0.0,0.0,0.0 +Texas,TX,40,0,40,2024-11-06 01:06,-0.02830721236779532,0.0,0.0,0.0 +Arizona,AZ,11,11,0,2024-11-06 02:51,0.0015683167912931006,0.0,0.0,0.0 +Maine,ME,2,2,0,2024-11-06 03:06,0.04670404582003973,0.0,0.0,0.0 +ME1,ME1,1,1,0,2024-11-06 03:06,0.118873149776614,0.0,0.0,0.0 +Pennsylvania,PA,19,19,0,2024-11-06 11:25,0.005892052593490571,0.0,0.0,0.0 +Nevada,NV,6,6,0,2024-11-06 12:13,0.012231173400438,0.0,0.0,0.0 +ME2,ME2,1,0,1,2024-11-06 13:24,-0.03830996091825678,0.0,0.0,0.0 +Wisconsin,WI,10,10,0,2024-11-06 14:16,0.003190632665339921,0.0,0.0,0.0 +Michigan,MI,15,15,0,2024-11-06 17:58,0.014135593444094652,0.0,0.0,0.0 +Alaska,AK,3,0,3,2024-11-09 00:00,-0.052618487238493106,0.0,0.0,0.0 +Georgia,GA,16,16,0,2024-11-11 00:00,0.0011932966290864044,0.0,0.0,0.0 +North Carolina,NC,16,0,16,2024-11-11 00:00,-0.0068420065378581585,0.0,0.0,0.0 diff --git a/_assets/scripts/objs/shorty.csv b/_assets/scripts/objs/shorty.csv new file mode 100644 index 0000000..eabfc71 --- /dev/null +++ b/_assets/scripts/objs/shorty.csv @@ -0,0 +1,8 @@ +state,po,ev,harris,trump,time,margin,pop_harris,pop_trump,pop_total +Arizona,AZ,11,11,0,2024-11-06 02:51,0.0015683167912931006,0.0,0.0,0.0 +Pennsylvania,PA,19,19,0,2024-11-06 11:25,0.005892052593490571,0.0,0.0,0.0 +Nevada,NV,6,6,0,2024-11-06 12:13,0.012231173400438,0.0,0.0,0.0 +Wisconsin,WI,10,10,0,2024-11-06 14:16,0.003190632665339921,0.0,0.0,0.0 +Michigan,MI,15,15,0,2024-11-06 17:58,0.014135593444094652,0.0,0.0,0.0 +Georgia,GA,16,16,0,2024-11-11 00:00,0.0011932966290864044,0.0,0.0,0.0 +North Carolina,NC,16,0,16,2024-11-11 00:00,-0.0068420065378581585,0.0,0.0,0.0 diff --git a/_assets/scripts/objs/spread.csv b/_assets/scripts/objs/spread.csv new file mode 100644 index 0000000..599253a --- /dev/null +++ b/_assets/scripts/objs/spread.csv @@ -0,0 +1,57 @@ +po,margin,pop_harris,pop_trump,pop,spread +KY,-0.13200102900262967,0.0,0.0,0.0,NaN +VT,0.18299186552806557,0.0,0.0,0.0,NaN +WV,-0.1979853231392203,0.0,0.0,0.0,NaN +VA,0.051546869993999045,0.0,0.0,0.0,NaN +SC,-0.05926608749582096,0.0,0.0,0.0,NaN +AL,-0.12911374833354722,0.0,0.0,0.0,NaN +CT,0.10195049088077845,0.0,0.0,0.0,NaN +DE,0.09626744164984469,0.0,0.0,0.0,NaN +IL,0.08659043732806926,0.0,0.0,0.0,NaN +MA,0.17115549540148145,0.0,0.0,0.0,NaN +MD,0.17029047047092338,0.0,0.0,0.0,NaN +MS,-0.08384985827388858,0.0,0.0,0.0,NaN +NJ,0.08071386128187619,0.0,0.0,0.0,NaN +OK,-0.16940039496906512,0.0,0.0,0.0,NaN +RI,0.10599359883959258,0.0,0.0,0.0,NaN +TN,-0.11827770372066354,0.0,0.0,0.0,NaN +AR,-0.1421243327798315,0.0,0.0,0.0,NaN +IN,-0.08198196379638367,0.0,0.0,0.0,NaN +LA,-0.09464440456291051,0.0,0.0,0.0,NaN +ND,-0.1720516087835276,0.0,0.0,0.0,NaN +NE,-0.09784052246601727,0.0,0.0,0.0,NaN +NE1,-0.0768338607139315,0.0,0.0,0.0,NaN +NE2,0.03338572443289156,0.0,0.0,0.0,NaN +NE3,-0.2713664753691417,0.0,0.0,0.0,NaN +NM,0.05518490151719746,0.0,0.0,0.0,NaN +NY,0.11727176895339153,0.0,0.0,0.0,NaN +SD,-0.134347798616815,0.0,0.0,0.0,NaN +WY,-0.22480434375585095,0.0,0.0,0.0,NaN +DC,0.4446695384761944,0.0,0.0,0.0,NaN +CO,0.06938319492300149,0.0,0.0,0.0,NaN +KS,-0.07493428255631351,0.0,0.0,0.0,NaN +MO,-0.07835820644401448,0.0,0.0,0.0,NaN +NH,0.03748875849516253,0.0,0.0,0.0,NaN +CA,0.14909371340112143,0.0,0.0,0.0,NaN +ID,-0.1587714292507787,0.0,0.0,0.0,NaN +OR,0.08307156985441733,0.0,0.0,0.0,NaN +WA,0.09925503184790696,0.0,0.0,0.0,NaN +UT,-0.10693605121851635,0.0,0.0,0.0,NaN +HI,0.15032664646514882,0.0,0.0,0.0,NaN +MN,0.036395136485666724,0.0,0.0,0.0,NaN +OH,-0.04076697647702715,0.0,0.0,0.0,NaN +MT,-0.08397180092048107,0.0,0.0,0.0,NaN +IA,-0.04183263084637051,0.0,0.0,0.0,NaN +FL,-0.016947546621415566,0.0,0.0,0.0,NaN +TX,-0.02830721236779532,0.0,0.0,0.0,NaN +AZ,0.0015683167912931006,0.0,0.0,0.0,NaN +ME,0.04670404582003973,0.0,0.0,0.0,NaN +ME1,0.118873149776614,0.0,0.0,0.0,NaN +PA,0.005892052593490571,0.0,0.0,0.0,NaN +NV,0.012231173400438,0.0,0.0,0.0,NaN +ME2,-0.03830996091825678,0.0,0.0,0.0,NaN +WI,0.003190632665339921,0.0,0.0,0.0,NaN +MI,0.014135593444094652,0.0,0.0,0.0,NaN +AK,-0.052618487238493106,0.0,0.0,0.0,NaN +GA,0.0011932966290864044,0.0,0.0,0.0,NaN +NC,-0.0068420065378581585,0.0,0.0,0.0,NaN diff --git a/_assets/scripts/objs/swing_all_totals.csv b/_assets/scripts/objs/swing_all_totals.csv new file mode 100644 index 0000000..b2cd873 --- /dev/null +++ b/_assets/scripts/objs/swing_all_totals.csv @@ -0,0 +1,8 @@ +state,total +AZ,3387326 +GA,4999960 +MI,5539302 +NV,1405376 +NC,5524804 +PA,6936976 +WI,3298041 diff --git a/_assets/scripts/objs/swing_margins.csv b/_assets/scripts/objs/swing_margins.csv new file mode 100644 index 0000000..b91446b --- /dev/null +++ b/_assets/scripts/objs/swing_margins.csv @@ -0,0 +1,8 @@ +st,num_wins,num_votes,pct +AZ,1672143,3333829,0.5016 +GA,2473633,4935487,0.5012 +MI,2804040,5453892,0.5141 +NV,703486,1373376,0.5122 +NC,2684292,5443067,0.4932 +PA,3458229,6835903,0.5059 +WI,1630866,3241050,0.5032 diff --git a/_assets/scripts/objs/tally.bson b/_assets/scripts/objs/tally.bson new file mode 100644 index 0000000..e69de29 diff --git a/_assets/scripts/objs/vote2022.bson b/_assets/scripts/objs/vote2022.bson new file mode 100644 index 0000000..73085ec Binary files /dev/null and b/_assets/scripts/objs/vote2022.bson differ diff --git a/_assets/scripts/outp.jl b/_assets/scripts/outp.jl index fe67b5b..0b8176c 100644 --- a/_assets/scripts/outp.jl +++ b/_assets/scripts/outp.jl @@ -1,9 +1,4 @@ -fig = draw_density() +fig = draw_density() pretty_table(p_df,backend=Val(:html),show_subheader = false) -# Assume 'kde' is your pre-computed kernel density estimate -# kde = kde(your_mcmc_samples) - -# Estimate the proportion of outcomes with probability > 0.5 estimated_proportion = estimate_high_probability_outcomes(chain[:p]) - -println("The model shows Harris leading, with $(estimated_proportion * 100)% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through October 25. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with $(estimated_proportion * 100)% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through October 31. This is a summary of the model, not a prediction of the election outcome.") diff --git a/_assets/scripts/paths.jl b/_assets/scripts/paths.jl index e0340b4..d137b36 100644 --- a/_assets/scripts/paths.jl +++ b/_assets/scripts/paths.jl @@ -1,14 +1,51 @@ using Combinatorics - states = ["Pennsylvania", "Georgia", "North Carolina", "Michigan", "Arizona", "Wisconsin", "Nevada"] -votes = [19, 16, 16, 15, 11, 10, 6] +votes = [19, 16, 16, 15, 11, 10, 6] +""" + find_state_combinations(n, states=states, votes=votes, target=44) + +Finds all combinations of `n` states where the total number of votes meets or exceeds a specified `target`. + +**Parameters**: + +- `n` (`Int`): The number of states to include in each combination. +- `states` (`Array{String}`): An array of state names. +- `votes` (`Array{Int}`): An array of vote counts corresponding to each state. +- `target` (`Int`, default = 44): The minimum total votes required for a combination to be included. + +**Returns**: + +- `result_combos` (`Array`): A sorted array of tuples, each containing: + - `state_combo` (`Array{String}`): The names of the states in the combination. + - `vote_sum` (`Int`): The total votes for that combination. + +The results are sorted in descending order based on the total votes (`vote_sum`). + +**Example**: -# Function to find combinations of some number n of -# states with sum ≥ target votes -function find_state_combinations(n, states=states, votes=votes, target=44) +```julia +using Combinatorics + +states = ["State1", "State2", "State3", "State4"] +votes = [10, 20, 15, 5] +n = 2 +target = 25 + +combinations = find_state_combinations(n, states=states, votes=votes, target=target) +println(combinations) +# Output: +# [(["State2", "State3"], 35)] +Notes: + +All possible combinations of n states are considered. +Ensure that states and votes are arrays of the same length. +This function requires the Combinatorics package. Make sure to include using Combinatorics before calling the function. +""" + +function find_state_combinations(n=n, states=states, votes=votes, target=target) result_combos = [] # Get all possible combinations of n indices - for combo in combinations(1:length(states), 3) + for combo in combinations(1:length(states), n) vote_sum = sum(votes[i] for i in combo) if vote_sum >= target state_combo = states[collect(combo)] @@ -18,10 +55,10 @@ function find_state_combinations(n, states=states, votes=votes, target=44) return sort(result_combos, by=x->x[2], rev=true) end -# Find and display combinations with 44 or more votes -state_combos = find_state_combinations(3) - -println("Combinations of three states with 44 or more electoral votes:") +target = 44 +n = 5 +state_combos = find_state_combinations() +println("Combinations of three states with $target or more electoral votes:") for (states, total) in state_combos println("$(join(states, ", ")) = $total electoral votes") -end \ No newline at end of file +end diff --git a/_assets/scripts/paths.jl.m b/_assets/scripts/paths.jl.m deleted file mode 100644 index 51964c4..0000000 --- a/_assets/scripts/paths.jl.m +++ /dev/null @@ -1,79 +0,0 @@ -using DataFrames -using PrettyTables - -# Initial setup -const blue_initial = 226 -const states = ["PA", "GA", "NC", "MI", "AZ", "WI", "NV"] -const votes = [19, 16, 16, 15, 11, 10, 6] - -struct VoteState - blue::Int - path::Vector{String} - VoteState(blue::Int, path::Vector{String} = String[]) = new(blue, path) -end - -import Base: ==, hash -==(a::VoteState, b::VoteState) = a.blue == b.blue && a.path == b.path -hash(a::VoteState, h::UInt) = hash(a.blue, hash(a.path, h)) - -function generate_winning_paths() - initial_state = VoteState(blue_initial) - state_to_index = Dict{VoteState, Int}() - state_to_index[initial_state] = 1 - - winning_states = Set{VoteState}() - - function explore_state(current_state, remaining_states, remaining_votes) - if current_state.blue ≥ 270 - push!(winning_states, current_state) - return - end - - if current_state.blue + sum(remaining_votes) < 270 - return - end - - for (i, (state, votes)) in enumerate(zip(remaining_states, remaining_votes)) - new_path = copy(current_state.path) - push!(new_path, state) - new_state = VoteState(current_state.blue + votes, new_path) - - if !haskey(state_to_index, new_state) - state_to_index[new_state] = length(state_to_index) + 1 - end - - if new_state.blue ≥ 270 - push!(winning_states, new_state) - else - next_remaining_states = [remaining_states[1:i-1]..., remaining_states[i+1:end]...] - next_remaining_votes = [remaining_votes[1:i-1]..., remaining_votes[i+1:end]...] - explore_state(new_state, next_remaining_states, next_remaining_votes) - end - end - end - - explore_state(initial_state, states, votes) - return winning_states -end - -# Generate the paths -winning_states = generate_winning_paths() - -# Create DataFrame -paths_df = DataFrame( - Path = [join(state.path, " → ") for state in sort(collect(winning_states), by=s->length(s.path))], - FinalVotes = [state.blue for state in sort(collect(winning_states), by=s->length(s.path))] -) - -# Sort by number of states in path (shorter paths first) and then by final votes -paths_df.NumStates = length.(split.(paths_df.Path, " → ")) -sort!(paths_df, [:NumStates, :FinalVotes]) -select!(paths_df, Not(:NumStates)) # Remove the helper column - -# Display first few rows -println("\nFirst few winning paths:") -first(paths_df, 10) - -pretty_table(paths_df,backend=Val(:html),show_subheader = false) - -df = sort!(paths_df,[:Path,:FinalVotes]) \ No newline at end of file diff --git a/_assets/scripts/poll.jl b/_assets/scripts/poll.jl index 4b35709..7394ce3 100644 --- a/_assets/scripts/poll.jl +++ b/_assets/scripts/poll.jl @@ -10,7 +10,7 @@ include("load.jl") # libraries, etc. #------------------------------------------------------------------ st = "MI" sT = "mi" -HEADER = ["pollster", "Date", "Day", "n", "margin", "trump", "harris"] +HEADER = ["pollster", "Date", "Day", "n", "margin", "harris", "trump"] include("load.jl") # libraries, etc. #------------------------------------------------------------------ st = "NC" @@ -30,6 +30,6 @@ include("load.jl") # libraries, etc. #------------------------------------------------------------------ st = "WI" sT = "wi" -HEADER = ["pollster", "Date", "Day", "n", "margin", "trump", "harris"] +HEADER = ["pollster", "Date", "Day", "n", "margin", "harris", "trump"] include("load.jl") # libraries, etc. -#------------------------------------------------------------------ \ No newline at end of file +#------------------------------------------------------------------ diff --git a/_assets/scripts/save.jl b/_assets/scripts/save.jl index 2adca10..54c81a8 100644 --- a/_assets/scripts/save.jl +++ b/_assets/scripts/save.jl @@ -1,3 +1,3 @@ save(("../img/models/"*"$st"*"_"*"$mon"*".png"), fig) deep = deepcopy(chain) -@save ("../objs/"*"$st"*"_"*"$mon"*"_p_sample.bson") deep +@save ("objs/"*"$st"*"_"*"$mon"*"_p_sample.bson") deep diff --git a/_assets/scripts/stats.jl b/_assets/scripts/stats.jl new file mode 100644 index 0000000..01944ab --- /dev/null +++ b/_assets/scripts/stats.jl @@ -0,0 +1,235 @@ +using CSV +using DataFrames +using Statistics +using HypothesisTests +using StatsBase + +df = CSV.read("objs/margins.csv",DataFrame) +function analyze_early_reporting(df::DataFrame; early_threshold::Int=10) + """ + Comprehensive statistical analysis of differences between early and late reporting states. + + Parameters: + - df: DataFrame with columns ev (electoral votes), margin (vote margin), harris (electoral outcome) + - early_threshold: Number of states to consider as "early reporting" + + Returns: + - Dictionary with analysis results + """ + + # Sort by harris to get early reporting states + early_states = sort(df, :harris)[1:early_threshold, :] + late_states = sort(df, :harris)[early_threshold+1:end, :] + + # Convert margins to Float64 vectors + early_margins = Float64.(early_states.margin) + late_margins = Float64.(late_states.margin) + + # Weighted calculations + function weighted_mean(margins, weights) + return sum(Float64.(margins) .* Float64.(weights)) / sum(weights) + end + + early_weighted_margin = weighted_mean(early_states.margin, early_states.ev) + late_weighted_margin = weighted_mean(late_states.margin, late_states.ev) + overall_weighted_margin = weighted_mean(df.margin, df.ev) + + # Additional Statistical Tests + + # 1. Parametric t-test + t_test = UnequalVarianceTTest(early_margins, late_margins) + + # 2. Non-parametric Mann-Whitney U test + mw_test = MannWhitneyUTest(early_margins, late_margins) + + # 3. Kolmogorov-Smirnov test for distribution differences + ks_test = ApproximateTwoSampleKSTest(early_margins, late_margins) + + # 4. Effect sizes + # Cohen's d + pooled_std = sqrt((var(early_margins) + var(late_margins)) / 2) + cohens_d = (mean(early_margins) - mean(late_margins)) / pooled_std + + # Point-biserial correlation + all_margins = vcat(early_margins, late_margins) + group_indicator = vcat(zeros(length(early_margins)), ones(length(late_margins))) + r_pb = cor(all_margins, group_indicator) + + # 5. Descriptive statistics + early_stats = Dict( + "mean" => mean(early_margins), + "median" => median(early_margins), + "std" => std(early_margins), + "iqr" => diff(quantile(early_margins, [0.25, 0.75]))[1], + "skewness" => skewness(early_margins) + ) + + late_stats = Dict( + "mean" => mean(late_margins), + "median" => median(late_margins), + "std" => std(late_margins), + "iqr" => diff(quantile(late_margins, [0.25, 0.75]))[1], + "skewness" => skewness(late_margins) + ) + + return Dict( + # Original metrics + "early_weighted_margin" => early_weighted_margin, + "late_weighted_margin" => late_weighted_margin, + "overall_weighted_margin" => overall_weighted_margin, + "margin_difference" => early_weighted_margin - late_weighted_margin, + "early_ev_total" => sum(early_states.ev), + "late_ev_total" => sum(late_states.ev), + "early_states_count" => length(early_margins), + "late_states_count" => length(late_margins), + + # Statistical tests + "t_test_pvalue" => pvalue(t_test), + "mw_test_pvalue" => pvalue(mw_test), + "ks_test_pvalue" => pvalue(ks_test), + + # Effect sizes + "cohens_d" => cohens_d, + "point_biserial_r" => r_pb, + + # Descriptive statistics + "early_stats" => early_stats, + "late_stats" => late_stats + ) +end + +""" +Let me provide a comprehensive interpretation of these statistical results: + +1. **Distribution Differences** (KS Test): +- The Kolmogorov-Smirnov test p-value (0.0021) is highly significant +- This tells us the early and late reporting states have fundamentally different distribution patterns of margins +- This strengthens our confidence that the differences we see aren't just random variation + +2. **Statistical Significance** (Multiple Tests): +- T-test p-value: 0.00088 +- Mann-Whitney U test p-value: 0.0050 +- All three tests (including KS) are significant at p < 0.01 +- The agreement across both parametric (t-test) and non-parametric (Mann-Whitney) tests strongly suggests these differences are real, not artifacts of the analysis method + +3. **Effect Sizes** (Multiple Measures): +- Cohen's d: -0.96 (large negative effect) +- Point-biserial correlation: 0.31 (moderate positive correlation) +- These indicate not just statistically significant but practically meaningful differences + +4. **Descriptive Statistics** (Early vs Late): +Early States: +- More negative mean/median (-0.042 median) +- Higher skewness (1.018), indicating right-tailed distribution +- Larger IQR (0.154), suggesting more variability + +Late States: +- More positive median (0.081) +- Lower skewness (0.229), indicating more symmetrical distribution +- Smaller IQR (0.098), suggesting more consistency + +5. **Electoral Impact**: +- Early states: 326 EVs across 45 states (-2.70% weighted margin) +- Late states: 212 EVs across 11 states (+8.59% weighted margin) +- Overall weighted margin: +1.75% +- The -11.29% margin difference between early/late states is substantial + +Key Takeaways: +1. The differences are robust (confirmed by multiple statistical tests) +2. Early reporting states: + - Show more variable results + - Tend to lean negative + - Have a more skewed distribution +3. Late reporting states: + - Show more consistent results + - Tend to lean positive + - Have a more normal distribution +4. The difference is both statistically significant and practically large +5. This pattern could significantly impact election night interpretations, as early results might not be representative of the final outcome + +""" + +using DataFrames +using Statistics +using HypothesisTests +using StatsBase + +function analyze_margin_groups(df::DataFrame) + """ + Analyze states grouped by margin size categories and their reporting patterns. + + Parameters: + - df: DataFrame with columns ev (electoral votes), margin (vote margin), harris (electoral outcome) + + Returns: + - Dictionary with analysis results by margin group + """ + + # Create margin size categories + function get_margin_category(margin) + abs_margin = abs(margin) + if abs_margin < 0.02 # Within 2% + return "Very Close" + elseif abs_margin < 0.05 # Within 5% + return "Close" + elseif abs_margin < 0.10 # Within 10% + return "Moderate" + else + return "Decisive" + end + end + + # Add category columns + df_analysis = DataFrame(df) + df_analysis.margin_category = get_margin_category.(df_analysis.margin) + df_analysis.is_early = df_analysis.harris .<= 10 + + # Group analysis + groups = groupby(df_analysis, :margin_category) + + results = Dict() + + for (category, group) in pairs(groups) + early_group = filter(:is_early => x -> x, group) + late_group = filter(:is_early => x -> !x, group) + + group_stats = Dict( + "total_states" => nrow(group), + "total_ev" => sum(group.ev), + "mean_margin" => mean(group.margin), + "early_states" => nrow(early_group), + "early_ev" => sum(early_group.ev), + "early_mean_margin" => nrow(early_group) > 0 ? mean(early_group.margin) : NaN, + "late_states" => nrow(late_group), + "late_ev" => sum(late_group.ev), + "late_mean_margin" => nrow(late_group) > 0 ? mean(late_group.margin) : NaN, + "margin_range" => (minimum(group.margin), maximum(group.margin)) + ) + + # Add timing analysis + if nrow(early_group) > 0 && nrow(late_group) > 0 + group_stats["timing_difference"] = mean(early_group.margin) - mean(late_group.margin) + group_stats["early_vs_late_pvalue"] = pvalue(UnequalVarianceTTest( + Float64.(early_group.margin), + Float64.(late_group.margin) + )) + end + + results[category] = group_stats + end + + # Add overall summary + results["overall"] = Dict( + "total_states" => nrow(df), + "total_ev" => sum(df.ev), + "category_counts" => Dict( + category => count(==(category), df_analysis.margin_category) + for category in unique(df_analysis.margin_category) + ) + ) + + return results +end + +margin_results = analyze_margin_groups(df) + diff --git a/_assets/scripts/tally.jl b/_assets/scripts/tally.jl new file mode 100644 index 0000000..7d409a1 --- /dev/null +++ b/_assets/scripts/tally.jl @@ -0,0 +1,27 @@ +using CSV +using DataFrames +using Plots +using Statistics +using TimeZones + +df = CSV.read("objs/racecard.csv",DataFrame) +out = CSV.read("objs/outcome.csv",DataFrame) +tz = TimeZone("America/New_York") +df.time = replace.(df.time, " " => "T") +df.time = ZonedDateTime.(df.time, tz) + +now(tz) + +function flip!(df, state) + i = findfirst(df.po .== state) + df[i, :harris], df[i, :trump] = df[i, :trump], df[i, :harris] + return df +end + +function tally() + df.spread = df.margin .- df.pop_harris ./ (df.pop_harris .+ df.pop_trump) +end + +filter(row -> !any(loser -> occursin(loser, row.combo), losers), outq) + +filter(row -> any(picks -> occursin(picks, row.po), picks), dfq) diff --git a/_assets/scripts/watch_party.jl b/_assets/scripts/watch_party.jl index c1cbc1a..024e47f 100644 --- a/_assets/scripts/watch_party.jl +++ b/_assets/scripts/watch_party.jl @@ -18,13 +18,13 @@ function round_up_30min(dt::DateTime) end end #------------------------------------------------------------------ -df = CSV.read("../data/call_order.csv", DataFrame) -college = CSV.read("../objs/college.csv", DataFrame) -oldvote = CSV.read("../objs/2024vote.csv", DataFrame) -oldvote = oldvote[:,[1,5,6]] +df = CSV.read("data/call_order.csv", DataFrame) +college = CSV.read("objs/college.csv", DataFrame) +oldvote = CSV.read("objs/2024vote.csv", DataFrame) +oldvote = oldvote[:,[1,5,6]] rename!(oldvote, [:po,:harris,:trump]) -df.time = map(x -> DateTime(x, "yyyy-mm-dd HH:MM"), df.time) +df.time = map(x -> DateTime(x, "yyyy-mm-dd HH:MM"), df.time) # df.est = map(x -> DateTime(x, "yyyy-mm-dd HH:MM"), df.time) # df.cst = map(x -> DateTime(x, "yyyy-mm-dd HH:MM") - Hour(1), df.time) @@ -38,8 +38,8 @@ df.time = map(x -> DateTime(x, "yyyy-mm-dd HH:MM"), df.time) df = leftjoin(df,college,on = :state) df = leftjoin(df,oldvote,on = :po) -df.time = round_up_30min.(df.time) -df.idx = 1:56 +df.time = round_up_30min.(df.time) +df.idx = 1:56 [df.harris[df.idx .== i] .= 0 for i in pos] swings = ["PA","GA","NC","MI","AZ","WI","NV"] filtered_df = df[in.(df.po, Ref(swings)), :] diff --git a/_assets/scripts/debris/whatif.jl b/_assets/scripts/whatif.jl similarity index 100% rename from _assets/scripts/debris/whatif.jl rename to _assets/scripts/whatif.jl diff --git a/_assets/scripts/wrap.jl b/_assets/scripts/wrap.jl index e28722c..55ac156 100644 --- a/_assets/scripts/wrap.jl +++ b/_assets/scripts/wrap.jl @@ -1,56 +1,56 @@ st = "AZ" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ st = "GA" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ st = "MI" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ st = "NV" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ st = "NC" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ st = "PA" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ st = "WI" period = values(Month_names[Mon]) -deep = BSON.load("../objs/$st" * "_" *"$mon" * "_p_sample.bson") +deep = BSON.load("objs/$st" * "_" *"$mon" * "_p_sample.bson") results = deep[:deep][:p] estimated_proportion = estimate_high_probability_outcomes(results) -println("The model shows Harris leading, with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a strong position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") +println("The model shows Harris [leading], with **$(round(estimated_proportion * 100))**% of simulated outcomes showing her gaining more than 50% of the two-candidate vote. This suggests a [strong] position for Harris, but it's important to note that this is a statistical projection based the data from August through $period. This is a summary of the model, not a prediction of the election outcome.") #------------------------------------------------------------------ diff --git a/_assets/scripts/xf b/_assets/scripts/xf deleted file mode 100644 index 1f6b881..0000000 Binary files a/_assets/scripts/xf and /dev/null differ