Skip to content

Instantly share code, notes, and snippets.

@NaimKabir
Last active December 1, 2020 10:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save NaimKabir/108c2992c9c6c8f0f09e2586e641f30f to your computer and use it in GitHub Desktop.
Save NaimKabir/108c2992c9c6c8f0f09e2586e641f30f to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@jcdoster
Copy link

jcdoster commented Nov 14, 2020

You are incorrect in your analysis. The X-axis is partyline republican votes, not precinct republican population. I took the liberty of correcting your overall code:

import numpy as np
import matplotlib.pyplot as plt

p_NR_partyline = 0.5
p_NR_rep_non_partyline = 0.8
p_NR_demindep = 0.3

num_precincts = 1000 # let's deal with 1000 precincts.
r_partyline_percentages = np.random.rand(num_precincts) # modeling the fraction of R PARTYLINE voters in a precint, randomly from [0-1]

non_r_pop_size_dem = 100
split_votes_dem = np.random.binomial(non_r_pop_size_dem, p_NR_demindep, num_precincts) # simulating
split_trump_percentage_demindep = split_votes_dem / non_r_pop_size_dem

non_r_pop_size_rep = 100
split_votes_rep = np.random.binomial(non_r_pop_size_rep, p_NR_rep_non_partyline, num_precincts) # simulating
split_trump_percentage_rep = split_votes_rep / non_r_pop_size_rep

rep_non_partyline_percentage = 2*(1-p_NR_partyline)*r_partyline_percentages
r_percentages = r_partyline_percentages + rep_non_partyline_percentage
demindep_percentage = (1-r_percentages)

total_trump_vote = r_partyline_percentages + split_trump_percentage_reprep_non_partyline_percentage + split_trump_percentage_demindepdemindep_percentage

diffs = total_trump_vote - r_partyline_percentages
plt.scatter(r_partyline_percentages100, diffs100)
plt.xlabel('% republican straight-ticket votes')
plt.ylabel('% individual trump votes - % straight ticket votes')
plt.savefig('diff')

The only way a negative slope occurs is if you assume almost no non-partyline republicans voted for Trump. That didn't happen.

@jcdoster
Copy link

jcdoster commented Nov 14, 2020

This is what one would get assuming 50/50 partyline voting, Republicans partyline 100% for Trump, added to your assumption of 30% dems/independents voting for Trump, and then 80% of non-partyline Republicans voting for Trump. Dr. Shiva is correct the negative trend makes no sense if any reasonable number of non-partyline voters voted for Trump, unless Shiva misrepresented the data in some way, or his axes he states are indeed wrong from what he says.

p_NR_partyline = 0.5
p_NR_rep_non_partyline = 0.8
p_NR_demindep = 0.3

Your analysis really makes no sense from a basic perspective. The non-partyline rep vote should always increase the overall Trump vote given most Republicans will vote for Trump.
diff

@jcdoster
Copy link

jcdoster commented Nov 14, 2020

With the modified code, here is what 100% non-partyline voters and zero dem/independents voting for Trump looks like. Familiar.

p_NR_partyline = 0.5
p_NR_rep_non_partyline = 1.0
p_NR_demindep = 0.0

diff

@jcdoster
Copy link

And here is what it looks like if zero non-partyline Republicans vote for Trump. This is what you are trying to portray. It is not at all realistic.

p_NR_partyline = 0.5
p_NR_rep_non_partyline = 0.0
p_NR_demindep = 0.3

diff

@NaimKabir
Copy link
Author

NaimKabir commented Nov 14, 2020

Why are you incorporating "dem votes" at all? Ayyadurai only deals with two quantities: straight-ticket republican voter percentage in a precinct, and split-ticket Trump vote percentage in a precinct.

image

And these are combined naively to make his graphs, like so:

image

Even these two slides alone can show he's being misleading, since he's by definition plotting a line of the form:

Y = -X + C, where X is % straight-ticket republican votes, and C is some random variable describing the precinct's percentage of split-votes for Trump.

C could be positively correlated with X, but its correlation would have to be a perfect 1 for there to be no negative slope. So we can say in most cases except the most extraordinary, a negative slope must exist.

@jcdoster

@jcdoster
Copy link

jcdoster commented Nov 14, 2020

You HAVE to incorporate Dem voters. Some of Trumps votes came from them! And they are part of the Y-axis, by his own definition, they are part of the overall Trump candidate vote. The subset of potential dem/independent voters that voted for Trump come from the non-party-line voters. Here is an updated code, cleaned up the subset definitions. There is a shallow curve to the analysis, but nowhere near what you are showing, and with reasonable numbers fairly shallow....

import numpy as np
import matplotlib.pyplot as plt

p_NR_partyline = 0.5
p_NR_rep_non_partyline = 0.8
p_NR_demindep = 0.3

num_precincts = 1000 # let's deal with 1000 precincts.
r_partyline_percentages = np.random.rand(num_precincts) # modeling the fraction of R PARTYLINE voters in a precint, randomly from [0-1]

non_r_pop_size_dem = 100
split_votes_dem = np.random.binomial(non_r_pop_size_dem, p_NR_demindep, num_precincts) # simulating
split_trump_percentage_demindep = split_votes_dem / non_r_pop_size_dem

non_r_pop_size_rep = 100
split_votes_rep = np.random.binomial(non_r_pop_size_rep, p_NR_rep_non_partyline, num_precincts) # simulating
split_trump_percentage_rep = split_votes_rep / non_r_pop_size_rep

rep_non_partyline_percentages = r_partyline_percentages
demindep_percentages = (1-rep_non_partyline_percentages)

trump_partyline_percentages = p_NR_partyliner_partyline_percentages
trump_nonpartyline_percentages = (1-p_NR_partyline)
(split_trump_percentage_reprep_non_partyline_percentages + split_trump_percentage_demindepdemindep_percentages)

total_trump_vote_percentages = trump_partyline_percentages + trump_nonpartyline_percentages

diffs = total_trump_vote_percentages - r_partyline_percentages
plt.scatter(r_partyline_percentages100, diffs100)
plt.xlim(0,100)
plt.ylim(-50,50)
plt.xlabel('% republican straight-ticket votes')
plt.ylabel('% individual trump votes - % straight ticket votes')
plt.savefig('diff')

@jcdoster
Copy link

A reasonable situation, very shallow curve, hardly dips below zero.

p_NR_partyline = 0.3
p_NR_rep_non_partyline = 0.9
p_NR_demindep = 0.3

diff

@jcdoster
Copy link

An unreasonable situation, similar to the ones you depict. This didn't happen.

p_NR_partyline = 0.1
p_NR_rep_non_partyline = 0.5
p_NR_demindep = 0.1

diff

@jcdoster
Copy link

jcdoster commented Nov 14, 2020

To be even more general, taking into account uniform distributions on overall partyline voting 25% - 75%, Republican non-partyline voting 75% - 95%, and Dem/Indep non-partyline voting 10% - 40%, so a better monte carlo is done over 1000 precincts. The result is largely the same, with even less of a slope, and a bit more scatter. Again, I don't see how the data Dr. Shiva showed is possible. Something is going on in those counties. We need access to the data he is seeing.

import numpy as np
import matplotlib.pyplot as plt

num_precincts = 1000 # let's deal with 1000 precincts.
r_partyline_percentages = np.random.rand(num_precincts) # modeling the fraction of REP PARTYLINE voters in a precint, randomly from [0-1]
p_NR_partyline = 0.5np.random.rand(num_precincts) + 0.25 # prob range of fraction of OVERALL PARTYLINE vote in a precint [0.25-0.75]
p_NR_demindep = 0.3
np.random.rand(num_precincts) + 0.1 # prob range of fraction of DEM/INEPPENDENT vote for Trump in a precint [0.1-0.4]
p_NR_rep_non_partyline = 0.2*np.random.rand(num_precincts) + 0.75 # prob range of fraction of REP NON-PARTYLINE vote for Trump in a precint [0.75-0.95]

non_r_pop_size_dem = 100
split_votes_dem = np.random.binomial(non_r_pop_size_dem, p_NR_demindep, num_precincts) # simulating binomial weighted for non-partyline dem/indep
split_trump_percentage_demindep = split_votes_dem / non_r_pop_size_dem

non_r_pop_size_rep = 100
split_votes_rep = np.random.binomial(non_r_pop_size_rep, p_NR_rep_non_partyline, num_precincts) # simulating binomial weighted for non-partyline rep
split_trump_percentage_rep = split_votes_rep / non_r_pop_size_rep

rep_non_partyline_percentages = r_partyline_percentages # assumes Republican voter breakout is the same whether party-line voting or non-partyline
demindep_percentages = (1-rep_non_partyline_percentages) # dem/indepent non-partyline percentage is rest of non-partyline voter population

trump_partyline_percentages = p_NR_partyliner_partyline_percentages # partyline voter tally for trump
trump_nonpartyline_percentages = (1-p_NR_partyline)
(split_trump_percentage_reprep_non_partyline_percentages + split_trump_percentage_demindepdemindep_percentages) # non-partyline voter tally for trump

total_trump_vote_percentages = trump_partyline_percentages + trump_nonpartyline_percentages # add total Trump vote up by percentages

diffs = total_trump_vote_percentages - r_partyline_percentages
plt.scatter(r_partyline_percentages100, diffs100)
plt.xlim(0,100)
plt.ylim(-50,50)
plt.xlabel('% republican straight-ticket votes')
plt.ylabel('% individual trump votes - % straight ticket votes')
plt.savefig('diff')

diff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment