
Well, election season is in full swing – I tell you, just in case you haven’t noticed from the obnoxiously aggressive TV ads and all of the yard signs. Having the right to vote is a wonderful opportunity that many fellow world citizens don’t have. I have often wonder, however, how influential my singular vote can be. In this article, I’m going to attempt to address this question using one of my favorite tools – simulation!
I enjoy using simulation to solve problems – I wrote a series on simulation earlier this year – check it out if that seems interesting.
In this article, we’ll cover these topics:
- Setting up the simulation
- Simulating your vote swinging your state election
- Simulating your state swinging the overall election
- Estimating the overall probability that your vote decides the president
- Why (I think) you should still vote
Setting up the simulation approach
Before we get into the simulation, we need to get everything set up. There are multiple elements for us to consider, so we’ll go through them here.
What needs to happen for your vote to swing an election?
Two things need to happen for your vote to decide the presidential election – (1) your vote needs to be the deciding vote for your candidate in your state and (2) your state needs to provide your candidate with enough electoral votes to win the presidency. We will simulate these two separately and then combine them at the end.
What inputs do we need for the simulation?
We need multiple inputs and estimations for those inputs for our simulation:

Code setup
The code setup will have two classes that interact with each other. The first class will need an instance for each state. It will store methods and attributes related to individual state Elections – this class will be called ‘state.’ The second class will take multiple state instances as attributes and will have other attributes and methods that are needed to simulate state and national election – this class will be called ‘simulate_elections.’
Simulation outputs
The Simulation will run state and/or national elections multiple times. The primary output will be the number of times that your vote swung the election (state or national, whichever one we are simulating at the time) out of the total number of simulations. We can interpret this as an estimate of the probability that your vote swings the national election.
Okay, with the simulation plan mapped out, let’s get going on the code and then run some simulations!
Simulating your vote swinging a state
For the presidential election, most states have a "winner take all" popular vote for the president. This just means whoever gets the majority of the votes in the state wins the whole state. Maine and Nebraska are the exceptions, but for this article, we are going to just assume they act like the other states. They have a relatively small number of electoral votes – as long as we are not simulating the probability of a Maine or Nebraska resident swinging the election our estimates shouldn’t be too far off (sorry Mainer and Nebraskan readers!).
Condition for your vote to swing the state
So, with the "winner take all" assumption, what has to happen for your vote to swing a state? It’s actually pretty simple: your state needs to be in a perfect tie without your vote. Then, your vote comes in and breaks the tie for your candidate. Ok, now that we understand what needs to happen, let’s figure out how we can estimate the probability of a perfect tie.
Estimating the probability of a popular vote tie with simulation
We are going to use the binomial probability distribution a lot in our simulation. This is a really cool distribution and I encourage you to check it out if you are not familiar with it. It is out of the scope of this article, so I’m not going to go into any details here.
When simulating, you often have to make at least a few simplifying assumptions. In this section, I’m going to make the assumption that there are only two candidates (Trump and Harris) and votes that don’t go to one of them go to the other. In reality there are other candidates that will secure a couple of votes. For our purposes we are not going to factor them in though.
Right, let’s get started with the simulation! There are multiple components that we need to consider when simulating the probability of your vote deciding your state’s candidate.
We covered a comprehensive list of inputs in the last section. The inputs required for state simulation are a subset of that list and are below:
- The number of registered voters
- Voter turnout
- The probability of a voter voting for a specific candidate (Harris or Trump)
- Which candidate you are voting for
Simulating the number of voters
We first need to simulate the number of registered voters that will actually vote. To do this, we can use the binomial distribution. When simulating the number of voters, we put the number of registered voters as n and the historical voter turnout as the probability of success. This will give us a random number of voters based on the probabilities provided by the binomial distribution.

Let’s do a quick example – I live in the great state of Texas, we have 17.2mm registered voters with a historical voter turnout of 58%. Here is what 10 simulations for number of voters would look like:

Using the binomial distribution sounds kind of complicated; why can’t we just multiply registered voters by the historical voter turnout (for Texas, that would be 17.2mm*0.58)? The main problem with this approach is that for each of our simulated elections, we will have the exact same number of voters. This is a problem because of how we define winning a state. There must be a tie and our vote must break the tie. If the number of voters is always the same, the number of voters will always be odd or even. If the number is odd, we will never swing the election (because there can be no ties)! This will mess up our simulation – randomly simulating the number of registered voters avoids this trap, and is also more realistic.
Let’s go through a quick example to explain why you can’t swing an election if an odd number of voters turnout. Let’s pick the odd number of 99 for our example. In a near perfect split, 49 people voted for your candidate and 50 did not. If you then vote for your candidate you have caused a tie, not a swing (and we aren’t going to get into how ties are broken here)! If it is the other way, 50 for your candidate and 49 not. Your candidate has already won and your vote still doesn’t swing the state. Either way, an odd number of voters before you show up to the poll will rob you of your power to swing the election!
Simulating the state election
Okay, we now have a way of simulating the number of votes that are cast. Our next task is to determine the probability of the popular vote in your state resulting in a tie. The first thing we need to do is rescale our poll numbers to accommodate our ‘two-party’ assumption.
Let’s go back to Texas and give an example of simulating the votes for Trump (republican). At the time of this writing, Trump is polling at 50% and Harris is polling at 46%. Because of our two-party assumption, we have to scale these two numbers so that they add up to 100%, otherwise our simulation will be off. The calculation to do this is simple – an illustration is below.

Alright, with our poll numbers rescaled, we have everything we need to estimate the probability of a tie. There are multiple ways of doing this, the easiest and most computationally efficient way is using the binomial probability mass function. It is essentially the opposite of the binomial probability distribution. For the binomial probability mass function, we input a number of successes (in this case, votes needed for a tie), total trials (number of votes cast) and the probability of success (scaled poll numbers) and it returns the probability of the specific outcome. The probability we get is the probability of an exact tie in our state!

Alright, we’ve gone through all of the logic to simulate a state’s election. It’s been a lot of design talk, let’s write some Python code and finally simulate the probability of swinging an election in our state!
This article has excerpts from the code base in this repo : Simulation GitHub Link – feel free to modify and run your own simulations 😁 !
Here is the code for the ‘state’ class:
import numpy as np
from scipy.stats import binom
class state():
def __init__(self,
state_abbrv,
elect_votes,
reg_voters,
voter_turn_out,
vote_prob_dem,
vote_prob_repub,
party,
exclude_odd_vote_results = False):
'''
state_abbrv (str) : state abbreviation
elect_votes (int) : number of electoral votes that state has
reg_voters (int) : number of registered voters in state
voter_turn_out (float) : percent of registered voters that vote
vote_prob_dem (float) : probability that a single voter
votes for the democrate candidate
vote_prob_rep (float) : probability that a single voter
votes for the republican candidate
party (str) : the party of the potential swing voter
'rep' or 'dem'
'''
self.state_abbrv = state_abbrv
self.elect_votes = elect_votes
self.reg_voters = reg_voters
self.voter_turn_out = voter_turn_out
self.vote_prob_dem = vote_prob_dem
self.vote_prob_repub = vote_prob_repub
self.party = party
self.exclude_odd_vote_results = exclude_odd_vote_results
# scale poll numbers for two-party assumption
sum_dem_rep = self.vote_prob_dem + self.vote_prob_repub
if self.party == 'dem':
self.vote_prob = self.vote_prob_dem / sum_dem_rep
else:
self.vote_prob = self.vote_prob_repub / sum_dem_rep
# simulate the number of voters that turn out
self.actual_voters = np.random.binomial(n = self.reg_voters,
p = self.vote_prob)
return
def simulate_election(self):
'''
Simulates an election by simulating the vote of each
voting registered voter in the state. Assumes popular
vote winner takes all electoral points
output
elect_points_won (int) : if the candidate wins the state, this is
the self.elect_votes else, it is 0
'''
votes_for_candidate = np.random.binomial(1, self.vote_prob, self.actual_voters)
# see if votes for candidate is greater than 50% of actual voters
if np.sum(votes_for_candidate) > 0.5*self.actual_voters:
return self.elect_votes
else:
return 0
def simulate_votes(self):
'''
Simulates the votes from a state election. If state would
be lost without resident's vote and won with it, then
the resident will swing the state's vote.
input:
no explicit inputs - uses multiple class attributes
output:
swing_vote (bool) : True if resident's vote would swing the
election, False otherwise
'''
# if actual_voters is odd, there is no chance of swinging the election
if (self.actual_voters % 2 != 0) and (self.exclude_odd_vote_results):
swing_vote = False
return swing_vote
# calculate probability of a tie using binomial distribution
prob_of_tie = binom.pmf(int(self.actual_voters*0.5), self.actual_voters, self.vote_prob)
rand_num = np.random.rand()
if rand_num <= prob_of_tie:
swing_vote = True
else:
swing_vote = False
return swing_vote
As I mentioned before, the primary attribute of the ‘election_simulation’ class is a dictionary of ‘state’ class instances. Here is an example of setting up that dictionary (the full dictionary, with all of the states can be found in the GitHub repo).
state_dict = {
'AL': state(state_abbrv='AL', elect_votes=9, reg_voters=2499000, voter_turn_out=0.454, vote_prob_dem=0.35, vote_prob_repub=0.63, party = 'dem'),
'AK': state(state_abbrv='AK', elect_votes=3, reg_voters=597000, voter_turn_out=0.429, vote_prob_dem=0.40, vote_prob_repub=0.56, party = 'dem'),
'AZ': state(state_abbrv='AZ', elect_votes=11, reg_voters=4543000, voter_turn_out=0.619, vote_prob_dem=0.49, vote_prob_repub=0.50, party = 'dem'),
'AR': state(state_abbrv='AR', elect_votes=6, reg_voters=1631000, voter_turn_out=0.434, vote_prob_dem=0.32, vote_prob_repub=0.64, party = 'dem')
}
Below is the code for the ‘simulate_election’ class. The work horse of the class is the ‘simulate_multiple_times’ method, which simulates national or state (or both) elections multiple times. This is the method I will use to create all of the election simulations in this article.
class simulate_election():
def __init__(self,
state_dict,
resid_state,
elect_votes_to_win = 270):
'''
state_dict (dictionary) : list of instances of state class
resid_state (str) : state abbreviation for the single
potential swing vote
elect_votes_to_win (int) : number of electoral votes to win
default to 270
'''
self.state_dict = state_dict
self.resid_state = resid_state
self.elect_votes_to_win = elect_votes_to_win
return
def simulate_national_election(self):
'''
Simulates a popular election for each state and adds up
electoral votes for candidate. Determines if the candidate
loses without resident's state and wins with it. This is
a pre-requisite to the resident swinging the overall
election
input:
no explicit input, but uses state_dict, resid_state
elect_votes_to_win attributes
output:
swing_election (bool) : True if resident's state would
swing election
'''
won_elect_votes = 0
# simulate election for each state
for state in self.state_dict.values():
# skip simulation for resident's state
if state != self.resid_state:
state_elect_votes = state.simulate_election()
won_elect_votes += state_elect_votes
# determine of candidate loses with resident's state's electoral votes and winds with it
loss_without_resid_state = won_elect_votes <= self.elect_votes_to_win
win_with_resid_state = won_elect_votes + self.state_dict[self.resid_state].elect_votes >= self.elect_votes_to_win
if loss_without_resid_state and win_with_resid_state:
swing_election = True
else:
swing_election = False
return swing_election
def simulate_state_election(self):
'''
Simulates the resident's state election and
determines if the resident's vote could swing
the election.
inputs
no direct inputs, uses multiple class attributes
output:
swing_state (bool) : True if resident's vote
could swing election False
if not
'''
resident_state = self.state_dict[self.resid_state]
swing_state = resident_state.simulate_votes()
return swing_state
def simulate_overall_election(self):
'''
Runs the state election and then the national election
identifies if a single vote swung the entire election
inputs
no direct inputs, uses multiple attributes
output
swing_overall_election (bool) : True means a single vote
swung the election, false
means that it did not
'''
state_swing_election = self.simulate_national_election()
vote_swing_state = self.simulate_state_election()
if state_swing_election and vote_swing_state:
swing_overall_election = True
else:
swing_overall_election = False
return swing_overall_election
def simulate_multiple_times(self,
iters,
sim_type):
'''
Runs individual simulations multiple times.
inputs
iters (int) : number of simulations to run
sim_type (str) : indicates what kind of simulation
should be run - acceptable values are
'state', 'national' and 'both'
'''
if sim_type == 'state':
sim_func = self.simulate_state_election
elif sim_type == 'national':
sim_func = self.simulate_national_election
elif sim_type == 'both':
sim_func = self.simulate_overall_election
election_results = []
for _ in range(iters + 1):
iter_result = sim_func()
election_results.append(iter_result)
swing_pct = (sum(election_results) / len(election_results))*100
return election_results
And finally, below is the code used to actually run the state simulation. This runs the simulation for residents of each state. The results are a predicted probability of your vote swinging an election by state.
from state_info_dem_reps import states_dict
import election_simulations as sim
state_abbreviations = ['AL', 'AK',
'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA',
'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD',
'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ',
'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC',
'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'
]
swinging_states_df = pd.DataFrame()
for abbrv in state_abbreviations:
print(f'running {abbrv}')
test_sim = sim.simulate_elections(states_dict,
abbrv)
swing = test_sim.simulate_multiple_times(50000000, 'state')
temp_swing_prob = (sum(swing) / len(swing))
print(f'prob of swing = {temp_swing_prob}')
Intuitively, it seems very unlikely that (1) the voter turnout is even and (2) the votes tally to a perfect tie. And…… our intuition was correct! I ran 50mm simulations per state for democrat voters and republican voters (it took quite some time on my small PC 😐 ) and not a single one of the over 5 billion simulations had a swing in the state election.
So, from this we know that it is extremely unlikely to swing a state (less than 1 in 50mm), but we still don’t know what the probability is, and I don’t have enough computational power to run the number of simulations needed to see some swings. I decided to do a straight probability calculation instead of a simulation based one. To do this, I estimated the total voters by multiplying the voter turnout and total number of registered voters – I loosened the even voter turnout assumption in this step. I then used the binomial probability mass function to calculate the probability of a perfect tie in the votes. Here’s the code to do that:
from scipy.stats import binom
# code to calculate probability of swinging state without simulation
def calc_swing_prob(state, _50_prob = False):
voters = int(state.reg_voters*state.voter_turn_out)
votes_needed_to_win = int(0.5*voters)
# scale poll numbers for two-party assumption
sum_dem_rep = state.vote_prob_dem + state.vote_prob_repub
if state.party == 'dem':
vote_prob = state.vote_prob_dem / sum_dem_rep
else:
vote_prob = state.vote_prob_repub / sum_dem_rep
if _50_prob:
vote_prob = 0.5
prob_of_tie = binom.pmf(votes_needed_to_win, voters, vote_prob)
return prob_of_tie
Python floats round to zero after 1e-324 (that is super small), so anything less than that returns a 0. As you can see from the table below, all states but a handful were rounded to zero. Given that there are still a lot of zeros, I decided to calculate the probability of swinging a state if there was exactly a 50% chance that a voter votes for your candidate. This is the best case scenario/highest probability scenario of swinging a state. This gave much higher probabilities of swinging a state. But an exact 50/50 poll is really unlikely and, to make matters worse, even small changes to this split has huge impacts. For example, in Iowa (IA) the scaled probability of a voter casting a democrat vote is 50.5%, which takes the probability of swinging an election from 0.0007 (for exactly 50%) to 1.77E-322 😲 !
So, in summary, the probability of swinging any state’s vote is so small the simulation requires an intractable (at least for my technology setup) amount of iterations to see even a single swing. We switched to using probability theory instead which shows that the probabilities are very close to zero for all states.
Simulating your state swinging the nation
We currently have a way to estimate the probability that your vote swings the state’s election. But that is only one thing that needs to happen for your vote to decide the presidency. The other thing is that your state needs to swing the national electoral college vote as well. For a president to win, they need 270 electoral votes. We need to estimate the probability that without your state, your candidate has less than 270 and with it, your candidate has at least 270. How will we do this? You guessed it, the binomial distribution again!
The process will go as follows, for all states except yours, we will simulate an election by (1) simulating voter turnout, (2) simulating who those voters vote for, (3) calculating the winning candidate for the state and (4) tallying the electoral votes for your candidate from all states but yours. Once we have the simulated electoral votes without your state, understanding if your state could decide the election is simple math. If your candidate already has 270 votes, they already win without needing your state – no swing. If they have less than 270 and adding your state’s votes still doesn’t get them to 270, they lose no matter what – no swing. But, if they have less than 270 and your state’s vote would get them at or above 270, your state swings the election!

Okay, with the logic in our heads – I’ll copy some excerpts from the full code I shared in the previous section to highlight where this logic is used.
def simulate_national_election(self):
'''
Simulates a popular election for each state and adds up
electoral votes for candidate. Determines if the candidate
loses without resident's state and wins with it. This is
a pre-requisite to the resident swinging the overall
election
input:
no explicit input, but uses state_dict, resid_state
elect_votes_to_win attributes
output:
swing_election (bool) : True if resident's state would
swing election
'''
won_elect_votes = 0
# simulate election for each state
for state in self.state_dict.values():
# skip simulation for resident's state
if state != self.resid_state:
state_elect_votes = state.simulate_election()
won_elect_votes += state_elect_votes
# determine of candidate loses without resident's state's electoral votes and wins with it
loss_without_resid_state = won_elect_votes <= self.elect_votes_to_win
win_with_resid_state = won_elect_votes + self.state_dict[self.resid_state].elect_votes >= self.elect_votes_to_win
if loss_without_resid_state and win_with_resid_state:
swing_election = True
else:
swing_election = False
return swing_election
def simulate_election(self):
'''
Simulates an election by simulating the vote of each
voting registered voter in the state. Assumes popular
vote winner takes all electoral points
output
elect_points_won (int) : if the candidate wins the state, this is
the self.elect_votes else, it is 0
'''
votes_for_candidate = np.random.binomial(1, self.vote_prob, self.actual_voters)
# see if votes for candidate is greater than 50% of actual voters
if np.sum(votes_for_candidate) > 0.5*self.actual_voters:
return self.elect_votes
else:
return 0
The code to call the national election simulation is very similar to the code to call the state simulations:
import pandas as pd
from state_info_dem_reps import states_dict
import election_simulations as sim
from closed_form_state_swing import calc_swing_prob
state_abbreviations = ['AL', 'AK',
'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA',
'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD',
'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ',
'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC',
'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'
]
swinging_states_df = pd.DataFrame()
for abbrv in state_abbreviations:
print(f'running {abbrv}')
test_sim = sim.simulate_elections(states_dict,
abbrv)
# pass 'national' to simulate national elections
swing = test_sim.simulate_multiple_times(1000, 'national')
temp_swing_prob = (sum(swing) / len(swing))
print(f'prob of swing = {temp_swing_prob}')
With the theory and the code organized, let’s run some simulations to see the probability of your state swinging the national election. I ran simulations for republican and democrat voters and then I ran a simulation where each states polling numbers were a perfect 50%-50% split (this gives us the most interesting simulations). For the most part, in the simulation with actual polling numbers, the individual states are not likely to swing the state election. There are some states that happen to have a lot of power (like CA and NY). I think this is because, given how we set up the simulation, there isn’t a lot of variance in how the states vote across simulations. So, if the math of the electoral votes happens to work out that without the state in question’s votes, the candidate has less than 270 and with it it is ≥270, then the state will swing every time (because the other states don’t swap in the simulation). Perhaps a future iteration of the simulation could give some random variation to the poll numbers?
We can see that if we switch the poll numbers to a perfect 50/50 split, most states have a higher chance of swinging the election. This is because there is a lot more variance in the outcomes – e.g., Texas isn’t always voting republican for every single simulation.
Estimating the probability that your vote decides the president
We now have ways of estimating the probabilities of the two independent events that need to happen for your vote to decide the presidential election.
- Your vote swings your state’s election
- You state’s electoral votes swing the national election
Let’s use these to finally estimate what we’ve all been waiting for! As I just mentioned, these probabilities are independent of each other. In other words, the probability of your vote swinging your state and your state swinging the election are not changed by each other. Because of the ‘multiplication rule for independent events’ we can multiply these two probabilities. This is a lot more time effective then simulating them together!
So, multiplying the two probabilities together. For the simulations with the actual poll numbers, there wasn’t a single state that had a probability of swinging higher than 0! Since a table of all 0’s isn’t very fun or informative, I put the table of the perfect 50/50 split results below. The conclusion is, in the highest probability of swing (both for your state and the national election), there is a slightly higher than 0% probability of your vote deciding the election. When we use actual polling data, all probabilities round to 0%.
Why you should still vote
This article is just an exploration of simulating a specific system that is also a culturally pertinent topic. I don’t want the takeaway to be that people shouldn’t vote because there is essentially a 0% probability that they swing an election. I vote and I think other people should vote as well.
There are political reasons to vote other than swinging elections. There are also moral/ethical reasons to vote. I’m not really qualified to get into those. My main reasons for voting are based on classic logic!
My arguments for why you should still vote come from logical issues with the statement: "You shouldn’t vote because your vote will never swing an election."
Logical issue #1 – reductio ad absurdum:
‘Reductio ad absurdum’ is a Latin phrase that translates to ‘reduction to absurdity.’ This is an argument technique that follows a statement to its logical conclusion and exposes inconsistencies or other problems. A compelling argument against the statement above can be created using reductio ad absurdum. If you shouldn’t vote, then no one should vote (since everyone is in your same situation with regards to voting). If no one voted, our system of government wouldn’t work – how would we get leaders if literally no one cast a vote? Therefore, you should vote to keep our government from collapsing.
Logical issue #2 – self refutation
I’ll first illustrate a ‘self-refuting’ argument with a classic example: ‘there is no truth.’ For this statement to be true, at the very least, the statement must be true (duh). This refutes the statement because it says there is no truth! Thus, the statement is self-refuting.
"You shouldn’t vote because your vote will never swing an election" is a self-refuting argument because, if followed to its logical conclusion, no one would vote. But, if no one voted, a single vote would decide the election and the vote would matter! As people follow the advice of the statement, the impact of an individual vote becomes more important and thus the statement becomes less valid. It is self-refuting!
Conclusion
Well, as our intuition already indicated, the probability of a single vote deciding the next election is extremely small – like impossible to conceptualize small! But, you should not let this stop you from voting! I hope this was a fun and useful exercise in simulating a real-world system to learn more about it. Happy voting!