Presentation on the topic given at the University of Maryland, College Park on April 11th, 2023 as part of the Applied Political Analytics Master’s Program.
This research uses data at the candidate and district level to understand the impact of the Dobbs decision on the 2022 U.S. Midterm elections at the U.S. House and U.S. Senate level. Two measurements were modeled, controlling for relevant factors, to track individual candidate performance: individual contribution fundraising after the Dobbs decision and candidate win probability. Two measurements were modeled, controlling for relevant factors, to track electoral performance at the district level: vote margin shift from the 2020 Presidential election and the probability of a Democrat winning based on district characteristics. It was found that states with higher salience of abortion, measured by Google Trends search data, increased Democratic candidate fundraising at both office levels. States that implemented abortion bans or were hostile towards abortion saw an increased shift in Democratic vote share from the 2020 Presidential election at both office levels. It is recommended that Democrats focus on the abortion issue in campaign and party messaging in the upcoming 2024 elections to increase candidate fundraising performance and raise awareness of bans and hostile policies toward abortion to mobilize pro-choice voters, increasing Democratic vote share. Recommended competitive House districts to implement this strategy include: AZ-1, AZ-6, IA-3, MI-10, MT-1, NE-2, and WI-3. Recommended competitive Senate races to implement this strategy include: AZ, WI, and PA.
On June 24th, 2022, the United States Supreme court decided in Dobbs v. Jackson Women’s Health Organization that the U.S. constitution does not provide the right to abortion, overruling Roe v. Wade and Planned Parenthood v. Casey. This gave individual states the power to regulate any aspect of abortion not protected by federal law. Debate over the abortion issue increased with many states implementing trigger bans and several other states proposing policies hostile towards abortion. This made abortion a highly salient issue during the 2022 Midterm election cycle with many candidates discussing the Dobbs decision in campaign messaging.
Political science research has shown that abortion can be considered an “easy issue” due to its persistence, salience, and ability to be easily understood election cycle to election cycle. The abortion issue has gradually transformed the political parties with elites polarizing on the issue with Democrats adopting the “pro-choice” policy position and Republicans adopting the “pro-life” policy position. This led to mass level polarization with voters sorting themselves along party lines on this issue. Previous research has shown that past Supreme Court decisions on abortion have had electoral impacts including influences on U.S. President, Senate, House, gubernatorial, and state legislature elections.
Given the surprising midterm election results with Democrats overperforming fundamentals and the high salience of abortion this election cycle, this research looks to address the question: what impact did the Dobbs decision have on the results of the 2022 U.S. House and U.S. Senate midterm elections?
Four hypotheses were formed to test the electoral impact of the Dobbs decision:
Data used in this analysis was collected from multiple sources including:
Four multivariate regression models were created to measure electoral performance, controlling for relevant variables, among House, Senate, and competitive House candidates/districts with competitive House districts being determined by the 2020 Presidential vote share being within a margin of 10 ppt. The four measurements of electoral performance include: individual contribution fundraising proportion after the Dobbs decision (Democrat fundraising amount / Democrat and Republican fundraising amount in race), candidate win probability, vote margin shift from the 2020 Presidential election, and the probability of a Democrat winning based on district characteristics. Data was collected and processed in R with data visuals created in Tableau. The R Markdown file and Tableau workbook can be viewed on github upon request along with data files for replication purposes. Districts without a Democratic or Republican opponent or had two Republicans/Democrats running against each other were removed resulting in 848 candidates (786 House candidates, 62 Senate candidates) and 424 districts (393 House districts, 31 Senate districts) included in analysis.
The results of the first model measuring the fundraising proportion of individual contributions given to candidates after the Dobbs decision found that salience of abortion was statistically significant, increasing the post-Dobbs fundraising proportion for Democrats among House, Senate, and Competitive House candidates. Abortion law status (whether the state banned or had hostile policies towards abortion) significantly increased the fundraising proportion for Democrats at the Senate level with religious adherence slightly increasing the fundraising proportion for Democrats among all House candidates. The results of the second model measuring the probability of a candidate winning the general election found that gender was the only variable of interest to be statistically significant, increasing the probability of a candidate win when the candidate was a woman by 8%.
The results of the third model measuring the Democratic vote margin shift from the 2020 Presidential election to the 2022 Midterm election found that salience of abortion significantly decreased the margin shift among all House districts while abortion law status significantly increased the vote margin shift among all House and Competitive House districts. Religious adherence for Evangelical Protestants significantly decreased the margin shift among all House districts. The results of the final model measuring the probability of a Democratic candidate winning based on district characteristics found that none of the variables of interest were statistically significant predictors.
It was found through this analysis that election denialism of the 2020 Presidential election hurt Republican candidates, decreasing the post-Dobbs fundraising proportion for these candidates by 16 ppt at the Senate level and increasing the shift in Democratic vote margin from 2020 by 1.3 ppt among all House districts. However, this helped House GOP candidates in the post-Dobbs fundraising proportion by 5 ppt.
Looking at the 2024 elections, it is recommended the Democratic party: Focus on the abortion issue in campaign and party messaging as increased salience on this issue increased Democratic candidate fundraising Raise awareness of bans and hostile abortion policies from GOP state legislatures as pro-choice voters become mobilized, increasing Democratic vote share Tie the Dobbs decision and election denialism to the GOP as these are unpopular issues that Democrats can use to hurt GOP candidate electoral performance
Pick-up House districts that were within a margin of 5 ppt in 2022 to target in 2024 with this strategy include: AZ-1, AZ-6, IA-3, MI-10, MT-1, NE-2, and WI-3. Competitive Senate districts to target in 2024 with this strategy include AZ, WI, and PA. These districts all have low Evangelical religious adherence rates at the state level and could improve candidate fundraising and voter mobilization efforts with a strategy focusing on the abortion issue.
Data collected for this analysis came from multiple sources. To start, data was collected from 538’s “2022 Primary Project” GitHub repository which tracked the 2022 midterm primary candidates at the federal level. This data was processed to extract general election candidates by filtering candidates based on whether or not they won their primary election (or if there was one, their runoff election). 900 candidates were pulled with information on endorsements, incumbency status, race, and gender of the candidates.
Contributions to candidates were provided by the FEC which tracks federal level campaign finance information. This data included ‘Candidate master’, ‘Candidate-committee linkages’, and ‘Contributions by individuals’ on the bulk data webpage. Candidates not matched by the FEC fundraising data were manually confirmed on the FEC website to not having contribution records for this election cycle.
Google trends data was provided by Google, using the gtrendsR R package to identify the salience of the abortion issue this election cycle for each state.
District level data was provided by Dave’s Redistricting App (DRA) for each state. This data was manually collected for each state and inputted into this google sheet. The sources of data and processing done to calculate these values for districts can be viewed on DRA’s website. Data that was used was the 2020 presidential vote share for each party.
Election result data was manually collected for the New York Times Midterm Tracker for house and senate candidates and inputted into this google sheet.
Vote margin shift from 2020 Presidential election to 2022 Midterm election was collected in this google sheet. House level shift is provided by Ballotpedia and Senate level shift was calculated using data provided by Cook Political Report and USA Today.
Urbanization index of districts was provided by 538 and collected in this google sheet. House level data source can be found here and Senate level data source can be found here.
State region was provided by the Census Bureau and collected in this google sheet. The data source can be found here.
Religious adherence rates by state was provided by the Association of Religion Data Archives and collected in this google sheet. The data source can be found here.
State abortion law status was provided by the Center for Reproductive Rights and was collected in this google sheet. The data source can be found here.
Candidate Information
# load 538 primary candidates
dem <- read.csv("https://raw.githubusercontent.com/fivethirtyeight/data/master/primary-project-2022/dem_candidates.csv") %>%
select(Candidate, State, Office, District, Gender, Race.1, Race.2, Incumbent, Primary.Outcome, Runoff.Outcome)
rep <- read.csv("https://raw.githubusercontent.com/fivethirtyeight/data/master/primary-project-2022/rep_candidates.csv") %>%
select(Candidate, State, Office, District, Gender, Race.1, Race.2, Incumbent, Primary.Outcome, Runoff.Outcome, X2020.Election.Stance)
# process 538 primary candidate data
dem["Party"] <- "DEM"
rep["Party"] <- "GOP"
full_primary_candidates <- rbind.fill(dem, rep)
# head(full_primary_candidates)
# grab general election candidates
# create new column for general election status
full_primary_candidates["General.Election.Candidate"] <- FALSE
# determine general election candidate
for (i in 1:nrow(full_primary_candidates)) {
if (full_primary_candidates[i, "Primary.Outcome"] == "Won") {
full_primary_candidates[i, "General.Election.Candidate"] <- TRUE
} else if (full_primary_candidates[i, "Primary.Outcome"] == "Made runoff") {
if (full_primary_candidates[i, "Runoff.Outcome"] == "Won" || full_primary_candidates[i, "Runoff.Outcome"] == "" || is.null(full_primary_candidates[i, "Runoff.Outcome"])) {
full_primary_candidates[i, "General.Election.Candidate"] <- TRUE
}
}
}
# filter only general election candidates
full_general_candidates <- full_primary_candidates %>%
filter(General.Election.Candidate == TRUE) %>%
filter(Office == "Representative" | Office == "Senator (unexpired term)" | Office == "Senator")
# convert gender to a numeric with 1 representing male and 0 representing female
full_general_candidates$Gender.Num <- ifelse(full_general_candidates$Gender == "Male", 1, ifelse(full_general_candidates$Gender == "Female", 0, -99))
# convert race to dummy variables
full_general_candidates$Race.2 <- ifelse(full_general_candidates$Race.2 == "", NA, full_general_candidates$Race.2)
full_general_candidates$White <- ifelse(!is.na(full_general_candidates$Race.2), grepl("White", full_general_candidates$Race.1) | grepl("White", full_general_candidates$Race.2), grepl("White", full_general_candidates$Race.1))
full_general_candidates$White.Num <- ifelse(full_general_candidates$White, 1, 0)
full_general_candidates$Black <- ifelse(!is.na(full_general_candidates$Race.2), grepl("Black", full_general_candidates$Race.1) | grepl("Black", full_general_candidates$Race.2), grepl("Black", full_general_candidates$Race.1))
full_general_candidates$Black.Num <- ifelse(full_general_candidates$Black, 1, 0)
full_general_candidates$Asian <- ifelse(!is.na(full_general_candidates$Race.2), grepl("Asian", full_general_candidates$Race.1) | grepl("Asian", full_general_candidates$Race.2), grepl("Asian", full_general_candidates$Race.1))
full_general_candidates$Asian.Num <- ifelse(full_general_candidates$Asian, 1, 0)
full_general_candidates$Latino <- ifelse(!is.na(full_general_candidates$Race.2), grepl("Latino", full_general_candidates$Race.1) | grepl("Latino", full_general_candidates$Race.2), grepl("Latino", full_general_candidates$Race.1))
full_general_candidates$Latino.Num <- ifelse(full_general_candidates$Latino, 1, 0)
full_general_candidates$Middle_Eastern <- ifelse(!is.na(full_general_candidates$Race.2), grepl("Middle Eastern", full_general_candidates$Race.1) | grepl("Middle Eastern", full_general_candidates$Race.2), grepl("Middle Eastern", full_general_candidates$Race.1))
full_general_candidates$Middle_Eastern.Num <- ifelse(full_general_candidates$Middle_Eastern, 1, 0)
full_general_candidates$Native_American <- ifelse(!is.na(full_general_candidates$Race.2), grepl("Native", full_general_candidates$Race.1) | grepl("Native", full_general_candidates$Race.2), grepl("Native", full_general_candidates$Race.1))
full_general_candidates$Native_American.Num <- ifelse(full_general_candidates$Native_American, 1, 0)
# convert incumbent to a numeric dummy variable (incumbent as 1, else 0)
full_general_candidates$Incumbent.Num <- ifelse(str_detect(full_general_candidates$Incumbent, "Yes"), 1, 0)
# convert 2020 election stance to a numeric dummy variable (election denier marked as 1, else 0)
full_general_candidates$Election_Denier.Num <- ifelse(full_general_candidates$X2020.Election.Stance == "Fully denied", 1, 0)
full_general_candidates$Election_Denier.Num <- ifelse(is.na(full_general_candidates$X2020.Election.Stance), 0, full_general_candidates$Election_Denier.Num)
# convert Party to a numeric dummy variable (DEM as 1, REP as 0)
full_general_candidates$Party.Num <- ifelse(full_general_candidates$Party == "DEM", 1, 0)
# convert at-large and senate district values
full_general_candidates$District <- ifelse(full_general_candidates$District == "N/A" | full_general_candidates$District == "At-Large", 0, full_general_candidates$District)
# remove duplicate candidates
full_general_candidates$Office[full_general_candidates$Office == "Senator (unexpired term)"] <- "Senator"
full_general_candidates <- full_general_candidates %>%
filter(duplicated(Candidate) == FALSE)
# remove parts of name that interferes with grabbing last name
full_general_candidates$Candidate_processed <- paste(full_general_candidates$Candidate," ")
full_general_candidates$Candidate_processed <- gsub(" Sr. ", "", full_general_candidates$Candidate_processed)
full_general_candidates$Candidate_processed <- gsub(" Jr. ", "", full_general_candidates$Candidate_processed)
full_general_candidates$Candidate_processed <- gsub(" III ", "", full_general_candidates$Candidate_processed)
full_general_candidates$Candidate_processed <- gsub(" II ", "", full_general_candidates$Candidate_processed)
full_general_candidates$Candidate_processed <- trimws(full_general_candidates$Candidate_processed)
# extract last name and store in new column
full_general_candidates$Last_name <- word(full_general_candidates$Candidate_processed, - 1)
full_general_candidates$Last_name <- toupper(full_general_candidates$Last_name)
full_general_candidates$Last_name <- gsub(" ", "", full_general_candidates$Last_name)
full_general_candidates$Last_name <- gsub("Ñ", "N", full_general_candidates$Last_name)
full_general_candidates$Last_name <- gsub("Á", "A", full_general_candidates$Last_name)
full_general_candidates$Last_name <- gsub("'", "", full_general_candidates$Last_name)
full_general_candidates$Last_name <- ifelse(grepl("-", full_general_candidates$Last_name) > 0, word(full_general_candidates$Last_name, sep = "-", -1), full_general_candidates$Last_name)
# convert full state names to abbreviated names to match FEC format
states_dict <- c(AL = "Alabama",
AK = "Alaska",
AZ = "Arizona",
AR = "Arkansas",
CA = "California",
CO = "Colorado",
CT = "Connecticut",
DE = "Delaware",
FL = "Florida",
GA = "Georgia",
HI = "Hawaii",
ID = "Idaho",
IL = "Illinois",
IN = "Indiana",
IA = "Iowa",
KS = "Kansas",
KY = "Kentucky",
LA = "Louisiana",
ME = "Maine",
MD = "Maryland",
MA = "Massachusetts",
MI = "Michigan",
MN = "Minnesota",
MS = "Mississippi",
MO = "Missouri",
MT = "Montana",
NE = "Nebraska",
NV = "Nevada",
NH = "New Hampshire",
NJ = "New Jersey",
NM = "New Mexico",
NY = "New York",
NC = "North Carolina",
ND = "North Dakota",
OH = "Ohio",
OK = "Oklahoma",
OR = "Oregon",
PA = "Pennsylvania",
RI = "Rhode Island",
SC = "South Carolina",
SD = "South Dakota",
TN = "Tennessee",
TX = "Texas",
UT = "Utah",
VT = "Vermont",
VA = "Virginia",
WA = "Washington",
WV = "West Virginia",
WI = "Wisconsin",
WY = "Wyoming")
full_general_candidates$State_Abbr <- state.abb[match(full_general_candidates$State,state.name)]
# select relevant columns for final candidate data set
final_general_candidates <- full_general_candidates %>%
select(Candidate, Last_name, Party.Num, State, State_Abbr, Office, District, Gender.Num, White.Num, Black.Num, Asian.Num, Latino.Num, Middle_Eastern.Num, Native_American.Num, Incumbent.Num, Election_Denier.Num)
# head(final_general_candidates)
write.csv(final_general_candidates, "output data/final_general_candidates.csv")
Individual FEC Donations
# given how large of a file, the itcont.txt file used in the code below can be downloaded on the FEC website linked above in the Data section and added to the 'input data/FEC/Individual' folder in this repository.
# individual donations header
ind_header <- t((fread("input data/FEC/Individual/indiv_header_file.csv", header=FALSE)))
# individual donations 2022
ind_22 <- read.table("input data/FEC/Individual/indiv22/itcont.txt", header=FALSE, sep = '|', fill = TRUE, quote = "", col.names = ind_header[,1]) %>%
filter(str_sub(toString(TRANSACTION_DT), -4, -1) == "2022") %>%
select(TRAN_ID, TRANSACTION_DT, TRANSACTION_AMT, CMTE_ID, STATE)
# head(ind_22)
FEC Candidate Information
# candidate header
cn_header <- t((fread("input data/FEC/Candidates/cn_header_file.csv", header=FALSE)))
# candidates 2022
cn_22 <- read.table("input data/FEC/Candidates/cn22.txt", header=FALSE, sep = '|', fill = TRUE, quote = "", col.names = cn_header[,1]) %>%
filter(CAND_ELECTION_YR == 2022 & (CAND_OFFICE == "H" | CAND_OFFICE == "S")) %>%
select(CAND_ID, CAND_NAME, CAND_PTY_AFFILIATION, CAND_ELECTION_YR, CAND_OFFICE, CAND_OFFICE_ST, CAND_OFFICE_DISTRICT, CAND_PCC)
# clean party affiliation
cn_22$CAND_PTY_AFFILIATION <- ifelse(cn_22$CAND_PTY_AFFILIATION == "DFL", "DEM", cn_22$CAND_PTY_AFFILIATION)
cn_22$CAND_PTY_AFFILIATION <- ifelse(cn_22$CAND_ID == "H4MT01041", "REP", cn_22$CAND_PTY_AFFILIATION)
# found that candidate district information for Aja Smith was incorrect in FEC. District ran was CA-39, not CA-41
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H8CA41170", 39, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information for Luis Pozzolo was incorrect in FEC. District ran was AZ-7, not AZ-3
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H2AZ03152", 7, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information for David Schweikert was incorrect in FEC. District ran was AZ-1, not AZ-6
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H4AZ06045", 1, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information for Paul Jones was incorrect in FEC. District ran was CA-44, not CA-38
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H0CA38140", 44, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information for Lisa McClain was incorrect in FEC. District ran was MI-9, not MI-10
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H0MI10287", 9, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information for Tim Walberg was incorrect in FEC. District ran was MI-5, not MI-7
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H4MI07103", 5, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information for Ben Clark was incorrect in FEC. District ran was NC-9, not NC-4
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H2NC04150", 9, cn_22$CAND_OFFICE_DISTRICT)
# found that candidate district information and name for Nicholas J. LaLota was incorrect in FEC. District ran was NY-1, not NY-2
cn_22$CAND_OFFICE_DISTRICT <- ifelse(cn_22$CAND_ID == "H0NY02200", 1, cn_22$CAND_OFFICE_DISTRICT)
cn_22$CAND_NAME <- ifelse(cn_22$CAND_ID == "H0NY02200", "LALOTA, NICK", cn_22$CAND_NAME)
# change Antonio Daza's candidate name to DAZA, ANTONIO MIGUEL instead of DAZA-FERNANDEZ, ANTONIO MIGUEL
cn_22$CAND_NAME <- ifelse(cn_22$CAND_ID == "H2GA11230", "DAZA, ANTONIO MIGUEL", cn_22$CAND_NAME)
# change Ashley Hinson's candidate name to HINSON, ASHLEY instead of ARENHOLZ, ASHLEY HINSON
cn_22$CAND_NAME <- ifelse(cn_22$CAND_ID == "H0IA01174", "HINSON, ASHLEY", cn_22$CAND_NAME)
# change Jackie Walorski's candidate name to WALORSKI, JACKIE instead of WALORSKI SWIHART, JACKIE
cn_22$CAND_NAME <- ifelse(cn_22$CAND_ID == "H0IN02190", "WALORSKI, JACKIE", cn_22$CAND_NAME)
# head(cn_22)
write.csv(cn_22, "output data/FEC Candidates/cn_22.csv")
FEC Candidate-Committee Linkage
# candidate-committee linkage header
ccl_header <- t((fread("input data/FEC/Candidate-Committee Linkage/ccl_header_file.csv", header=FALSE)))
# candidate-committee linkage 2022
ccl_22 <- read.table("input data/FEC/Candidate-Committee Linkage/ccl22.txt", header=FALSE, sep = '|', fill = TRUE, quote = "", col.names = ccl_header[,1]) %>%
filter(CAND_ELECTION_YR == 2022) %>%
select(CAND_ID, CAND_ELECTION_YR, CMTE_ID, LINKAGE_ID)
# head(ccl_22)
write.csv(ccl_22, "output data/FEC Candidate-Committee/ccl_22.csv")
Join FEC Data
# 2022 fec data
fec_22 <- ind_22 %>%
inner_join(ccl_22, by = c("CMTE_ID")) %>%
inner_join(cn_22, by = c("CAND_ID"))
# head(fec_22)
write.csv(fec_22, "output data/FEC Joined/fec_22.csv")
Candidate Fundraising Totals
# get fundraising totals for candidates by candidate ID for transactions after the Dobbs decision
fec_22_totaled <- fec_22 %>%
filter(TRANSACTION_DT >= 6242022 & TRANSACTION_DT <= 11082022) %>%
group_by(CAND_ID, CAND_NAME, CAND_PTY_AFFILIATION, CAND_OFFICE, CAND_OFFICE_ST, CAND_OFFICE_DISTRICT) %>%
dplyr::summarize(Fundraising_Total = sum(TRANSACTION_AMT, na.rm=TRUE))
## `summarise()` has grouped output by 'CAND_ID', 'CAND_NAME',
## 'CAND_PTY_AFFILIATION', 'CAND_OFFICE', 'CAND_OFFICE_ST'. You can override using
## the `.groups` argument.
# process data to be joined with 538 candidate data
fec_22_totaled$CAND_OFFICE <- ifelse(fec_22_totaled$CAND_OFFICE == "H", "Representative", "Senator")
fec_22_totaled$CAND_PTY_AFFILIATION <- ifelse(fec_22_totaled$CAND_PTY_AFFILIATION == "DEM", 1, 0)
# extract and clean candidate last name for joining
fec_22_totaled$CAND_LAST <- word(fec_22_totaled$CAND_NAME, sep = ",", 1)
fec_22_totaled$CAND_LAST <- gsub(" Sr.", "", fec_22_totaled$CAND_LAST)
fec_22_totaled$CAND_LAST <- gsub(" Jr.", "", fec_22_totaled$CAND_LAST)
fec_22_totaled$CAND_LAST <- gsub(" III", "", fec_22_totaled$CAND_LAST)
fec_22_totaled$CAND_LAST <- gsub(" II", "", fec_22_totaled$CAND_LAST)
fec_22_totaled$CAND_LAST <- gsub("'", "", fec_22_totaled$CAND_LAST)
fec_22_totaled$CAND_LAST <- ifelse(grepl(" ", fec_22_totaled$CAND_LAST) > 0, word(fec_22_totaled$CAND_LAST,-1), fec_22_totaled$CAND_LAST)
fec_22_totaled$CAND_LAST <- ifelse(grepl("-", fec_22_totaled$CAND_LAST) > 0, word(fec_22_totaled$CAND_LAST, sep = "-", -1), fec_22_totaled$CAND_LAST)
# change data type for district to string
fec_22_totaled$CAND_OFFICE_DISTRICT <- as.character(fec_22_totaled$CAND_OFFICE_DISTRICT)
# head(fec_22_totaled)
write.csv(fec_22_totaled, "output data/fec_22_totaled.csv")
# join with 538 candidate data
candidate_fundraising <- final_general_candidates %>%
left_join(fec_22_totaled, by = c("Last_name" = "CAND_LAST", "District" = "CAND_OFFICE_DISTRICT", "Office" = "CAND_OFFICE", "State_Abbr" = "CAND_OFFICE_ST")) %>%
select(Candidate, Party.Num, State, State_Abbr, Office, District, Gender.Num, White.Num, Black.Num, Asian.Num, Latino.Num, Middle_Eastern.Num, Native_American.Num, Incumbent.Num, Election_Denier.Num, Fundraising_Total)
candidate_fundraising$index <- row.names(candidate_fundraising)
candidate_fundraising$Fundraising_Total <- ifelse(is.na(candidate_fundraising$Fundraising_Total), 0, candidate_fundraising$Fundraising_Total)
# remove duplicate matches
candidate_fundraising <- candidate_fundraising %>%
filter(index != 279 & index != 385 & index != 540 & index != 280 & index != 48)
# head(candidate_fundraising)
write.csv(candidate_fundraising, "output data/candidate_fundraising.csv")
Filter out districts
# filter out districts with no Democratic or Republican opponent. This accounts for 27 districts.
# Districts included: AL-1, AL-6, AZ-8, AZ-9, CA-10, FL-5, FL-6, FL-18, IL-7, IL-16, MA-4, NY-9, NY-13, PA-3, PA-13, PA-14, SC-3, SC-4, SD-At-Large, TX-6, TX-11, TX-19, TX-25, TX-26, TX-31, UT Senate, WI-6, WI-8
# General elections for LA House districts were cancelled so were not included in analysis
# filter out districts that were missing a candidate in the 538 data. This accounts for 2 districts
# Districts included: MI-4, PA-15 (Democrat write-in candidates)
removed_districts <- c("AL-1", "AL-6", "AZ-8", "AZ-9", "CA-10", "FL-5", "FL-6", "FL-18", "IL-7", "IL-16", "MA-4", "NY-9", "NY-13", "PA-3", "PA-13", "PA-14", "SC-3", "SC-4", "SD-0", "TX-6", "TX-11", "TX-19", "TX-25", "TX-26", "TX-31", "WI-6", "WI-8", "MI-4", "PA-15", "UT-0")
candidate_fundraising_filtered <- candidate_fundraising %>%
mutate(full_district = paste(State_Abbr, "-", as.character(District), sep='')) %>%
filter(! full_district %in% removed_districts)
# remove Nicholas Begich running in AK-0 since he didn't make the final round of voting
# remove Buzz Kelley and Patricia Chesbro running in AK Senate since they didn't make it to the final round of voting
candidate_fundraising_filtered <- candidate_fundraising_filtered %>%
filter(index != 836 & index != 835 & index != 380)
# indicate special election for OK Senate
candidate_fundraising_filtered$Special <- ifelse(candidate_fundraising_filtered$index == 281 | candidate_fundraising_filtered$index == 728, 1, 0)
# remove districts with either two Republicans or two Democrats running against one another
# Districts included: AK Senate, CA-15, CA-16, CA-29, CA-30, CA-34, CA-37
same_party_districts <- c("CA-15", "CA-16", "CA-29", "CA-30", "CA-34", "CA-37")
candidate_fundraising_filtered <- candidate_fundraising_filtered %>%
filter(! full_district %in% same_party_districts)
candidate_fundraising_filtered <- candidate_fundraising_filtered %>%
filter(!(full_district == "AK-0" & Office == "Senator"))
# head(candidate_fundraising_filtered)
write.csv(candidate_fundraising_filtered, "output data/candidate_fundraising_filtered.csv")
District Level Data
districts <- data.frame(unique(candidate_fundraising_filtered[c("State","State_Abbr","Office","District","Special")]))
districts$Dem_Name <- ""
districts$Rep_Name <- ""
districts$Dem_Gender <- -1
districts$Rep_Gender <- -1
districts$Dem_Incumbent <- -1
districts$Rep_Incumbent <- -1
districts$Rep_Election_Denier <- 0
districts$Dem_Fundraised <- -1
districts$Rep_Fundraised <- -1
for (i in 1:nrow(districts)) {
for (j in 1:nrow(candidate_fundraising_filtered)) {
# match district with candidate info
if (districts[i, "State_Abbr"] == candidate_fundraising_filtered[j, "State_Abbr"] &
districts[i, "Office"] == candidate_fundraising_filtered[j, "Office"] &
districts[i, "District"] == candidate_fundraising_filtered[j, "District"] &
districts[i, "Special"] == candidate_fundraising_filtered[j, "Special"]) {
# pull relevant fields
party <- candidate_fundraising_filtered[j,"Party.Num"]
name <- candidate_fundraising_filtered[j,"Candidate"]
gender <- candidate_fundraising_filtered[j,"Gender.Num"]
incumbent <- candidate_fundraising_filtered[j,"Incumbent.Num"]
denier <- candidate_fundraising_filtered[j,"Election_Denier.Num"]
fundraised <- candidate_fundraising_filtered[j,"Fundraising_Total"]
# add values to district
if (party == 1) {
districts[i, "Dem_Name"] <- name
districts[i, "Dem_Gender"] <- gender
districts[i, "Dem_Incumbent"] <- incumbent
districts[i, "Rep_Election_Denier"] <- 0
districts[i, "Dem_Fundraised"] <- fundraised
} else {
districts[i, "Rep_Name"] <- name
districts[i, "Rep_Gender"] <- gender
districts[i, "Rep_Incumbent"] <- incumbent
districts[i, "Rep_Election_Denier"] <- denier
districts[i, "Rep_Fundraised"] <- fundraised
}
}
}
}
# create variables for models
districts$Open.Num <- ifelse(districts$Dem_Incumbent == 0 & districts$Rep_Incumbent == 0, 1, 0)
districts$Dem_Man_Rep_Man <- ifelse(districts$Dem_Gender == 1 & districts$Rep_Gender == 1, 1, 0)
districts$Dem_Woman_Rep_Man <- ifelse(districts$Dem_Gender == 0 & districts$Rep_Gender == 1, 1, 0)
districts$Dem_Man_Rep_Woman <- ifelse(districts$Dem_Gender == 1 & districts$Rep_Gender == 0, 1, 0)
districts$Dem_Woman_Rep_Woman <- ifelse(districts$Dem_Gender == 0 & districts$Rep_Gender == 0, 1, 0)
# get fundraising proportion by district
# Dem Fundraising Amount / (Dem Fundraising Amount + Rep Fundraising Amount)
districts$Fundraising_Prop <- districts$Dem_Fundraised / (districts$Dem_Fundraised + districts$Rep_Fundraised)
# head(districts)
write.csv(districts, "output data/districts.csv")
DRA District Information
# District data provided by Dave's Redistricting App https://davesredistricting.org/maps#home
# Each state's congressional district data was manually exported and combined into a csv
dra_house <- read.csv("input data/DRA/DRA Data - House Districts .csv") %>%
select(DRA.Office, ID, State, Dem.2020.Pres, Rep.2020.Pres, Total.2020.Pres)
dra_senate <- read.csv("input data/DRA/DRA Data - Senate Districts.csv") %>%
select(DRA.Office, ID, State, Dem.2020.Pres, Rep.2020.Pres, Total.2020.Pres)
# DRA processing
# append data sets
full_dra_districts <- rbind.fill(dra_house, dra_senate)
# head(full_dra_districts)
# create 2020 presidential vote share for each party
full_dra_districts["Dem.2020.Pres.%"] <- as.double(full_dra_districts$Dem.2020.Pres) / as.double(full_dra_districts$Total.2020.Pres)
full_dra_districts["Rep.2020.Pres.%"] <- as.double(full_dra_districts$Rep.2020.Pres) / as.double(full_dra_districts$Total.2020.Pres)
full_dra_districts["Dem_Margin_2020"] <- (full_dra_districts["Dem.2020.Pres.%"] - full_dra_districts["Rep.2020.Pres.%"]) * 100
# select office, id, state, and created columns
final_dra_districts <- full_dra_districts %>%
select(DRA.Office, ID, State, Dem_Margin_2020)
names(final_dra_districts)[names(final_dra_districts) == "State"] <- "State.DRA"
# change district labels to match district data set
final_dra_districts$ID <- ifelse(final_dra_districts$ID == "At-Large" | final_dra_districts$ID == "N/A", "0", final_dra_districts$ID)
# join with district data
districts_dra <- districts %>%
left_join(final_dra_districts, by = c("Office" = "DRA.Office", "State_Abbr" = "State.DRA", "District" = "ID"))
# head(districts_dra)
write.csv(districts_dra, "output data/districts_dra.csv")
NYT Election Results
# Election results were collected manually off of the NYT Election tracker: https://www.nytimes.com/interactive/2022/11/08/us/elections/results-senate.html?action=click&pgtype=Article&state=default&module=election-results&context=election_recirc®ion=NavBar
# Data was collected and inputed into this spreadsheet: https://docs.google.com/spreadsheets/d/1PFxFBpbsdMT8_b8weiqAeTIx1Q11vgNIWIlYYAjOU0M/edit?usp=sharing
nyt_election_results <- read.csv("input data/NYT/NYT Election Tracker Data - General Election Candidates.csv") %>%
select(State, Office, District, Candidate, Party, Winner)
# change district labels to match candidate data set
nyt_election_results$District <- ifelse(nyt_election_results$District == "At-Large" | nyt_election_results$District == "N/A", "0", nyt_election_results$District)
nyt_election_results$Winner <- ifelse(nyt_election_results$Winner, 1, 0)
# join with candidate data set
candidate_fundraising_filtered_nyt <- candidate_fundraising_filtered %>%
left_join(nyt_election_results, by = c("State" = "State", "Office" = "Office", "District" = "District", "Candidate" = "Candidate")) %>%
select(-c(Party))
# head(candidate_fundraising_filtered_nyt)
write.csv(candidate_fundraising_filtered_nyt, "output data/candidate_fundraising_filtered_nyt.csv")
# create District Dem Win
nyt_election_results <- nyt_election_results %>%
filter(Party == "DEM") %>%
group_by(State, Office, District) %>%
dplyr::summarize(District_DEM_Win = sum(Winner))
## `summarise()` has grouped output by 'State', 'Office'. You can override using
## the `.groups` argument.
districts_dra_nyt <- districts_dra %>%
left_join(nyt_election_results, by = c("State" = "State", "Office" = "Office", "District" = "District"))
# head(districts_dra_nyt)
Shift from 2020
# house districts
house_shift <- read.csv("input data/Vote Shift/2020 to 2022 Shift - House Shift.csv") %>%
select(District, X2022.U.S..House.margin, Difference)
# clean up data
house_shift$State.Shift <- word(house_shift$District, sep = "-", 1)
house_shift$District.Shift <- word(house_shift$District, sep = "-", 2)
house_shift$District.Shift <- sub("^0+", "", house_shift$District.Shift)
house_shift$District.Shift <- ifelse(house_shift$District.Shift == "AL", "0", house_shift$District.Shift)
house_shift$Margin_2022 <- ifelse(substr(house_shift$X2022.U.S..House.margin, 1, 1) == "D", as.double(substring(house_shift$X2022.U.S..House.margin, 3)), as.double(substring(house_shift$X2022.U.S..House.margin, 3)) * -1)
house_shift$Shift <- ifelse(substr(house_shift$Difference, 1, 1) == "D", as.double(substring(house_shift$Difference, 3)), as.double(substring(house_shift$Difference, 3)) * -1)
house_shift$Office.Shift <- "Representative"
house_shift <- house_shift %>%
select(Office.Shift, State.Shift, District.Shift, Margin_2022, Shift)
# join with house district data
districts_dra_nyt_shift <- districts_dra_nyt %>%
left_join(house_shift, by = c("Office" = "Office.Shift", "State_Abbr" = "State.Shift", "District" = "District.Shift"))
# senate districts
senate_shift <- read.csv("input data/Vote Shift/2020 to 2022 Shift - Senate Shift.csv") %>%
select(stateid, X2022.Dem.This.Margin, X20.22.Dem.Margin.Shift, Special)
# clean up data
names(senate_shift)[names(senate_shift) == "X2022.Dem.This.Margin"] <- "Senate_Margin_2022"
names(senate_shift)[names(senate_shift) == "X20.22.Dem.Margin.Shift"] <- "Senate_Shift"
senate_shift$Senate_Margin_2022 <- as.double(sub("%","", senate_shift$Senate_Margin_2022))
senate_shift$Senate_Shift <- as.double(sub("%","", senate_shift$Senate_Shift))
senate_shift$Office.Shift <- "Senator"
# join with senate district data
districts_dra_nyt_shift <- districts_dra_nyt_shift %>%
left_join(senate_shift, by = c("Office" = "Office.Shift", "State_Abbr" = "stateid", "Special" = "Special"))
# combine house and senate columns
districts_dra_nyt_shift$Dem_Margin_2022 <- ifelse(is.na(districts_dra_nyt_shift$Margin_2022), districts_dra_nyt_shift$Senate_Margin_2022, districts_dra_nyt_shift$Margin_2022)
districts_dra_nyt_shift$Dem_Margin_Shift <- ifelse(is.na(districts_dra_nyt_shift$Shift), districts_dra_nyt_shift$Senate_Shift, districts_dra_nyt_shift$Shift)
districts_dra_nyt_shift <- districts_dra_nyt_shift %>%
select(-c(Margin_2022, Shift, Senate_Margin_2022, Senate_Shift))
# head(districts_dra_nyt_shift)
write.csv(districts_dra_nyt_shift, "output data/districts_dra_nyt_shift.csv")
State Abortion status
state_abortion_status <- read.csv("input data/Center for Reproductive Rights/State Abortion Status - Data.csv")
# create numeric dummy variables for illegal, hostile, and other abortion status
state_abortion_status$Illegal.Status <- ifelse(state_abortion_status$Abortion.Status == "Illegal", 1, 0)
state_abortion_status$Hostile.Status <- ifelse(state_abortion_status$Abortion.Status == "Hostile", 1, 0)
state_abortion_status$Other.Status <- ifelse(state_abortion_status$Hostile.Status == 0 & state_abortion_status$Illegal.Status == 0, 1, 0)
state_abortion_status <- state_abortion_status %>%
select(-c(Abortion.Status))
# join to district data set
districts_dra_nyt_shift_status <- districts_dra_nyt_shift %>%
left_join(state_abortion_status, by = c("State" = "State"))
# head(districts_dra_nyt_shift_status)
write.csv(districts_dra_nyt_shift_status, "output data/districts_dra_nyt_shift_status.csv")
Google Trends data
# get overall salience compared to other issues
Gtrenddata2022 <- data.frame(gtrends(c("Abortion", "Crime", "Inflation", "Gas Prices", "Border"),
geo = "US", time = "2022-01-01 2022-12-01",onlyInterest = TRUE))
write.csv(Gtrenddata2022, "output data/Gtrenddata2022.csv")
full_states <- c("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")
gtrends_data <- data.frame(full_states)
gtrends_data$Abortion_Salience <- 0
# get the relative number of searches for "abortion" in the last full week before the 2022 midterm general elections
for (i in 1:nrow(gtrends_data)) {
# print(gtrends_data[i, "used_states"])
temp <- data.frame(gtrends(c("abortion"), geo = paste0("US-", gtrends_data[i, "full_states"]), time = "2022-01-01 2022-12-01",onlyInterest = TRUE)) %>%
filter(as.character(interest_over_time.date) == "2022-10-30") %>%
select(interest_over_time.hits)
gtrends_data$Abortion_Salience[i] <- temp[1, "interest_over_time.hits"]
}
write.csv(gtrends_data, "output data/gtrends_data.csv")
# join with district data
districts_dra_nyt_shift_status_trend <- districts_dra_nyt_shift_status %>%
left_join(gtrends_data, by = c("State_Abbr" = "full_states"))
# head(districts_dra_nyt_shift_status_trend)
Census data
# pull relevant information
# education level: profln: 59 for population 25 and over, 68 for bachelor's degree or higher
census_education <- read.csv("input data/Census/DP02_1yr_500.csv") %>%
filter(PROFLN == 59 | PROFLN == 68) %>%
select(GEONAME, PROFLN, TITLE, PRF_ESTIMATE, PCT_ESTIMATE)
# process data
census_education$State <- trimws(word(census_education$GEONAME, sep = ",", -1))
census_education$District <- word(census_education$GEONAME, 3)
census_education$District <- ifelse(census_education$District == "(at", "0", census_education$District)
census_education$Total <- ifelse(census_education$PROFLN == 59, as.double(sub(",", "", census_education$PRF_ESTIMATE)), NA)
census_education$Bachelors <- ifelse(census_education$PROFLN == 68, as.double(sub(",", "", census_education$PRF_ESTIMATE)), NA)
names(census_education)[names(census_education) == "PCT_ESTIMATE"] <- "Share_Bachelors"
census_education$Share_Bachelors <- as.double(census_education$Share_Bachelors)
## Warning: NAs introduced by coercion
census_education$Office <- "Representative"
census_education_house <- census_education %>%
filter(PROFLN == 68) %>%
select(State, District, Office, Share_Bachelors)
census_education_senate <- census_education %>%
group_by(State) %>%
dplyr::summarize(State_Total = sum(Total, na.rm=TRUE), State_Bachelors = sum(Bachelors, na.rm=TRUE))
census_education_senate$Share_Bachelors <- census_education_senate$State_Bachelors / census_education_senate$State_Total * 100
census_education_senate$District <- "0"
census_education_senate$Office <- "Senator"
census_education_senate <- census_education_senate %>%
select(-c(State_Total, State_Bachelors))
# union the two data sets
census_education_total <- rbind(census_education_house, census_education_senate)
# join with district data set
districts_dra_nyt_shift_status_trend_census <- districts_dra_nyt_shift_status_trend %>%
left_join(census_education_total, by = c("State" = "State", "District" = "District", "Office" = "Office"))
# income level: profln: 51 for total households, 57-61 for households above $50k income
census_income <- read.csv("input data/Census/DP03_1yr_500.csv") %>%
filter(PROFLN == 51 | (PROFLN >= 58 & PROFLN <= 61)) %>%
select(GEONAME, PROFLN, TITLE, PRF_ESTIMATE)
# process data
census_income$State <- trimws(word(census_income$GEONAME, sep = ",", -1))
census_income$District <- word(census_income$GEONAME, 3)
census_income$District <- ifelse(census_income$District == "(at", "0", census_income$District)
census_income$Income_Group <- ifelse(census_income$PROFLN == 51, "Total", "Above 75k")
census_income <- census_income %>%
group_by(State, District, Income_Group) %>%
dplyr::summarize(Summed = sum(as.double(sub(",", "", PRF_ESTIMATE)), na.rm=TRUE))
## Warning in mask$eval_all_summarise(quo): NAs introduced by coercion
## `summarise()` has grouped output by 'State', 'District'. You can override using
## the `.groups` argument.
census_income$Total <- ifelse(census_income$Income_Group == "Total", census_income$Summed, NA)
census_income$Above <- ifelse(census_income$Income_Group == "Above 75k", census_income$Summed, NA)
census_income <- census_income %>%
group_by(State, District) %>%
dplyr::summarize(Total = sum(Total, na.rm=TRUE), Above = sum(Above, na.rm=TRUE))
## `summarise()` has grouped output by 'State'. You can override using the
## `.groups` argument.
census_income$Share_Above_75k <- census_income$Above / census_income$Total * 100
census_income$Office <- "Representative"
census_income_house <- census_income %>%
select(State, District, Office, Share_Above_75k)
census_income_senate <- census_income %>%
group_by(State) %>%
dplyr::summarize(State_Total = sum(Total, na.rm=TRUE), State_Above = sum(Above, na.rm=TRUE))
census_income_senate$Share_Above_75k <- census_income_senate$State_Above / census_income_senate$State_Total * 100
census_income_senate$District <- "0"
census_income_senate$Office <- "Senator"
census_income_senate <- census_income_senate %>%
select(State, District, Office, Share_Above_75k)
# union the two data sets
census_income_total <- rbind(census_income_house, census_income_senate)
# join with district data set
districts_dra_nyt_shift_status_trend_census <- districts_dra_nyt_shift_status_trend_census %>%
left_join(census_income_total, by = c("State" = "State", "District" = "District", "Office" = "Office"))
# share white: profln: 37 for white alone, 33 for total population
census_race <- read.csv("input data/Census/DP05_1yr_500.csv") %>%
filter(PROFLN == 37 | PROFLN == 33) %>%
select(GEONAME, PROFLN, TITLE, PRF_ESTIMATE, PCT_ESTIMATE)
# process data
census_race$State <- trimws(word(census_race$GEONAME, sep = ",", -1))
census_race$District <- word(census_race$GEONAME, 3)
census_race$District <- ifelse(census_race$District == "(at", "0", census_race$District)
census_race$Total <- ifelse(census_race$PROFLN == 33, as.double(sub(",", "", census_race$PRF_ESTIMATE)), NA)
## Warning in ifelse(census_race$PROFLN == 33, as.double(sub(",", "",
## census_race$PRF_ESTIMATE)), : NAs introduced by coercion
census_race$White <- ifelse(census_race$PROFLN == 37, as.double(sub(",", "", census_race$PRF_ESTIMATE)), NA)
## Warning in ifelse(census_race$PROFLN == 37, as.double(sub(",", "",
## census_race$PRF_ESTIMATE)), : NAs introduced by coercion
names(census_race)[names(census_race) == "PCT_ESTIMATE"] <- "Share_White"
census_race$Share_White <- as.double(census_race$Share_White)
## Warning: NAs introduced by coercion
census_race$Office <- "Representative"
census_race_house <- census_race %>%
filter(PROFLN == 37) %>%
select(State, District, Office, Share_White)
census_race_senate <- census_race %>%
group_by(State) %>%
dplyr::summarize(State_Total = sum(Total, na.rm=TRUE), State_White = sum(White, na.rm=TRUE))
census_race_senate$Share_White <- census_race_senate$State_White / census_race_senate$State_Total * 100
census_race_senate$District <- "0"
census_race_senate$Office <- "Senator"
census_race_senate <- census_race_senate %>%
select(-c(State_Total, State_White))
# union the two data sets
census_race_total <- rbind(census_race_house, census_race_senate)
# join with district data set
districts_dra_nyt_shift_status_trend_census <- districts_dra_nyt_shift_status_trend_census %>%
left_join(census_race_total, by = c("State" = "State", "District" = "District", "Office" = "Office"))
# gender share: profln: 3 for female, 1 for total population
census_gender <- read.csv("input data/Census/DP05_1yr_500.csv") %>%
filter(PROFLN == 3 | PROFLN == 1) %>%
select(GEONAME, PROFLN, TITLE, PRF_ESTIMATE, PCT_ESTIMATE)
# process data
census_gender$State <- trimws(word(census_gender$GEONAME, sep = ",", -1))
census_gender$District <- word(census_gender$GEONAME, 3)
census_gender$District <- ifelse(census_gender$District == "(at", "0", census_gender$District)
census_gender$Total <- ifelse(census_gender$PROFLN == 1, as.double(sub(",", "", census_gender$PRF_ESTIMATE)), NA)
## Warning in ifelse(census_gender$PROFLN == 1, as.double(sub(",", "",
## census_gender$PRF_ESTIMATE)), : NAs introduced by coercion
census_gender$Female <- ifelse(census_gender$PROFLN == 3, as.double(sub(",", "", census_gender$PRF_ESTIMATE)), NA)
## Warning in ifelse(census_gender$PROFLN == 3, as.double(sub(",", "",
## census_gender$PRF_ESTIMATE)), : NAs introduced by coercion
names(census_gender)[names(census_gender) == "PCT_ESTIMATE"] <- "Share_Female"
census_gender$Share_Female <- as.double(census_gender$Share_Female)
## Warning: NAs introduced by coercion
census_gender$Office <- "Representative"
census_gender_house <- census_gender %>%
filter(PROFLN == 3) %>%
select(State, District, Office, Share_Female)
census_gender_senate <- census_gender %>%
group_by(State) %>%
dplyr::summarize(State_Total = sum(Total, na.rm=TRUE), State_Female = sum(Female, na.rm=TRUE))
census_gender_senate$Share_Female <- census_gender_senate$State_Female / census_gender_senate$State_Total * 100
census_gender_senate$District <- "0"
census_gender_senate$Office <- "Senator"
census_gender_senate <- census_gender_senate %>%
select(-c(State_Total, State_Female))
# union the two data sets
census_gender_total <- rbind(census_gender_house, census_gender_senate)
# join with district data set
districts_dra_nyt_shift_status_trend_census <- districts_dra_nyt_shift_status_trend_census %>%
left_join(census_gender_total, by = c("State" = "State", "District" = "District", "Office" = "Office"))
# age share: profln: 1 for total population, 8-11 for 15 to 44 years old
census_age <- read.csv("input data/Census/DP05_1yr_500.csv") %>%
filter(PROFLN == 1 | (PROFLN >= 8 & PROFLN <= 11)) %>%
select(GEONAME, PROFLN, TITLE, PRF_ESTIMATE, PCT_ESTIMATE)
# process data
census_age$State <- trimws(word(census_age$GEONAME, sep = ",", -1))
census_age$District <- word(census_age$GEONAME, 3)
census_age$District <- ifelse(census_age$District == "(at", "0", census_age$District)
census_age$Age_Group <- ifelse(census_age$PROFLN == 1, "Total", "Age 15-44")
census_age <- census_age %>%
group_by(State, District, Age_Group) %>%
dplyr::summarize(Summed = sum(as.double(sub(",", "", PRF_ESTIMATE)), na.rm=TRUE))
## Warning in mask$eval_all_summarise(quo): NAs introduced by coercion
## Warning in mask$eval_all_summarise(quo): NAs introduced by coercion
## `summarise()` has grouped output by 'State', 'District'. You can override using
## the `.groups` argument.
census_age$Total <- ifelse(census_age$Age_Group == "Total", census_age$Summed, NA)
census_age$Age <- ifelse(census_age$Age_Group == "Age 15-44", census_age$Summed, NA)
census_age <- census_age %>%
group_by(State, District) %>%
dplyr::summarize(Total = sum(Total, na.rm=TRUE), Age = sum(Age, na.rm=TRUE))
## `summarise()` has grouped output by 'State'. You can override using the
## `.groups` argument.
census_age$Total <- ifelse(census_age$State == "Delaware", 1003384, census_age$Total)
census_age$Share_Age_15_to_44 <- census_age$Age / census_age$Total * 100
census_age$Office <- "Representative"
census_age_house <- census_age %>%
select(State, District, Office, Share_Age_15_to_44)
census_age_senate <- census_age %>%
group_by(State) %>%
dplyr::summarize(State_Total = sum(Total, na.rm=TRUE), State_Age = sum(Age, na.rm=TRUE))
census_age_senate$Share_Age_15_to_44 <- census_age_senate$State_Age / census_age_senate$State_Total * 100
census_age_senate$District <- "0"
census_age_senate$Office <- "Senator"
census_age_senate <- census_age_senate %>%
select(State, District, Office, Share_Age_15_to_44)
# union the two data sets
census_age_total <- rbind(census_age_house, census_age_senate)
# join with district data set
districts_dra_nyt_shift_status_trend_census <- districts_dra_nyt_shift_status_trend_census %>%
left_join(census_age_total, by = c("State" = "State", "District" = "District", "Office" = "Office"))
# head(districts_dra_nyt_shift_status_trend_census)
write.csv(districts_dra_nyt_shift_status_trend_census, "output data/districts_dra_nyt_shift_trend_census.csv")
State Region
# regions provided by the Census
regions <- read.csv("input data/Census/State Regions - State.csv")
# create dummy variables
regions$South <- ifelse(regions$Region == "South", 1, 0)
regions$West <- ifelse(regions$Region == "West", 1, 0)
regions$Northeast <- ifelse(regions$Region == "Northeast", 1, 0)
regions$Midwest <- ifelse(regions$Region == "Midwest", 1, 0)
# join with district data set
districts_dra_nyt_shift_status_trend_census_regions <- districts_dra_nyt_shift_status_trend_census %>%
left_join(regions, by = c("State" = "State")) %>%
select(-c(Region))
# head(districts_dra_nyt_shift_status_trend_census_regions)
Urbanization Index
# house level
urban_house <- read.csv("input data/538/Urbanization Index - House.csv")
# process data
urban_house$Office <- "Representative"
urban_house$District <- as.character(as.integer(word(urban_house$tcd, sep = "-", 2)))
urban_house$District <- ifelse(urban_house$state == "ND" | urban_house$state == "SD" | urban_house$state == "DE" | urban_house$state == "WY" | urban_house$state == "VT", 0, urban_house$District)
names(urban_house)[names(urban_house) == "state"] <- "State_Abbr"
urban_house <- urban_house %>%
select(State_Abbr, Office, District, urbanindex)
# senate level
urban_senate <- read.csv("input data/538/Urbanization Index - Senate.csv")
# process data
names(urban_senate)[names(urban_senate) == "Urbanization.Index"] <- "urbanindex"
urban_senate$Office <- "Senator"
urban_senate$District <- "0"
urban_senate$State_Abbr <- state.abb[match(urban_senate$State,state.name)]
urban_senate <- urban_senate %>%
select(State_Abbr, Office, District, urbanindex)
# union two data sets
urban_total <- rbind(urban_house, urban_senate)
# join with district data set
districts_dra_nyt_shift_status_trend_census_regions_urban <- districts_dra_nyt_shift_status_trend_census_regions %>%
left_join(urban_total, by = c("State_Abbr" = "State_Abbr", "Office" = "Office", "District" = "District"))
# head(districts_dra_nyt_shift_status_trend_census_regions_urban)
State Religious Adherence
all_denominations <- read.csv("input data/ARDA/Religious Adherence - All Denominations.csv") %>%
select(name, value)
names(all_denominations)[names(all_denominations) == "value"] <- "Adherence_per_1000_All"
evangelical <- read.csv("input data/ARDA/Religious Adherence - Evangelical Protestant.csv") %>%
select(name, value)
names(evangelical)[names(evangelical) == "value"] <- "Adherence_per_1000_Evan"
# join the two data sets
adherence_both <- all_denominations %>%
left_join(evangelical, by = c("name"))
write.csv(adherence_both, "output data/adherence_both.csv")
# join with district data set
districts_dra_nyt_shift_status_trend_census_regions_urban_religion <- districts_dra_nyt_shift_status_trend_census_regions_urban %>%
left_join(adherence_both, by = c("State" = "name"))
# head(districts_dra_nyt_shift_status_trend_census_regions_urban_religion)
Processing final data sets for models
# candidate data set full
final_candidates <- candidate_fundraising_filtered_nyt %>%
left_join(districts_dra_nyt_shift_status_trend_census_regions_urban_religion, by = c("State" = "State", "State_Abbr" = "State_Abbr", "Office" = "Office", "District" = "District", "Special" = "Special")) %>%
select(State,
Office,
District,
Abortion_Salience,
Illegal.Status,
Hostile.Status,
Gender.Num,
Share_Bachelors,
Adherence_per_1000_Evan,
Election_Denier.Num,
Party.Num,
White.Num,
Black.Num,
Latino.Num,
Incumbent.Num,
Open.Num,
Dem_Margin_2020,
Share_Above_75k,
Share_Age_15_to_44,
Share_Female,
Share_White,
urbanindex,
South,
West,
Midwest,
Fundraising_Prop,
Winner)
head(final_candidates)
## State Office District Abortion_Salience Illegal.Status Hostile.Status
## 1 Texas Representative 1 11 1 0
## 2 Texas Representative 2 11 1 0
## 3 Texas Representative 3 11 1 0
## 4 Texas Representative 4 11 1 0
## 5 Texas Representative 5 11 1 0
## 6 Texas Representative 7 11 1 0
## Gender.Num Share_Bachelors Adherence_per_1000_Evan Election_Denier.Num
## 1 1 22.1 235.4 0
## 2 0 37.7 235.4 0
## 3 1 48.0 235.4 0
## 4 0 45.8 235.4 0
## 5 0 23.9 235.4 0
## 6 0 50.2 235.4 0
## Party.Num White.Num Black.Num Latino.Num Incumbent.Num Open.Num
## 1 1 0 1 0 0 1
## 2 1 1 0 0 0 0
## 3 1 0 0 0 0 1
## 4 1 0 1 0 0 0
## 5 1 0 1 0 0 0
## 6 1 1 0 0 1 0
## Dem_Margin_2020 Share_Above_75k Share_Age_15_to_44 Share_Female Share_White
## 1 -45.87259 35.44609 38.51167 50.5 66.6
## 2 -22.76599 57.17593 41.07412 50.9 54.2
## 3 -14.37608 62.71501 39.47224 50.5 60.2
## 4 -25.90530 54.34124 40.49916 50.7 64.1
## 5 -22.42478 43.41911 39.48683 51.4 51.4
## 6 29.72940 46.04369 47.60404 51.1 31.1
## urbanindex South West Midwest Fundraising_Prop Winner
## 1 9.61616 1 0 0 0.26942006 0
## 2 11.66319 1 0 0 0.03808307 0
## 3 11.57905 1 0 0 0.20247471 0
## 4 10.84754 1 0 0 0.11091497 0
## 5 10.95429 1 0 0 0.01358806 0
## 6 12.90726 1 0 0 0.93232706 1
write.csv(final_candidates, "output data/final_candidates.csv")
# house candidates data
candidate_house <- final_candidates %>%
filter(Office == "Representative") %>%
select(-c(Office, District, State))
# senate candidates data
candidate_senate <- final_candidates %>%
filter(Office == "Senator") %>%
select(-c(Office, District, State))
# competitive house candidates data
competitive_candidate_house <- final_candidates %>%
filter(Office == "Representative" & abs(Dem_Margin_2020) <= 10) %>%
select(-c(Office, District, State))
# district data set full
final_districts <- districts_dra_nyt_shift_status_trend_census_regions_urban_religion %>%
select(State,
Office,
District,
Special,
Abortion_Salience,
Illegal.Status,
Hostile.Status,
Dem_Woman_Rep_Man,
Dem_Man_Rep_Woman,
Dem_Woman_Rep_Woman,
Share_Bachelors,
Adherence_per_1000_Evan,
Rep_Election_Denier,
Dem_Incumbent,
Rep_Incumbent,
Dem_Margin_2020,
Share_Above_75k,
Share_White,
Share_Age_15_to_44,
Share_Female,
urbanindex,
South,
West,
Midwest,
Fundraising_Prop,
Dem_Margin_Shift,
District_DEM_Win)
head(final_districts)
## State Office District Special Abortion_Salience Illegal.Status
## 1 Texas Representative 1 0 11 1
## 2 Texas Representative 2 0 11 1
## 3 Texas Representative 3 0 11 1
## 4 Texas Representative 4 0 11 1
## 5 Texas Representative 5 0 11 1
## 6 Texas Representative 7 0 11 1
## Hostile.Status Dem_Woman_Rep_Man Dem_Man_Rep_Woman Dem_Woman_Rep_Woman
## 1 0 0 0 0
## 2 0 1 0 0
## 3 0 0 0 0
## 4 0 1 0 0
## 5 0 1 0 0
## 6 0 1 0 0
## Share_Bachelors Adherence_per_1000_Evan Rep_Election_Denier Dem_Incumbent
## 1 22.1 235.4 0 0
## 2 37.7 235.4 0 0
## 3 48.0 235.4 1 0
## 4 45.8 235.4 1 0
## 5 23.9 235.4 1 0
## 6 50.2 235.4 0 1
## Rep_Incumbent Dem_Margin_2020 Share_Above_75k Share_White Share_Age_15_to_44
## 1 0 -45.87259 35.44609 66.6 38.51167
## 2 1 -22.76599 57.17593 54.2 41.07412
## 3 0 -14.37608 62.71501 60.2 39.47224
## 4 1 -25.90530 54.34124 64.1 40.49916
## 5 1 -22.42478 43.41911 51.4 39.48683
## 6 0 29.72940 46.04369 31.1 47.60404
## Share_Female urbanindex South West Midwest Fundraising_Prop Dem_Margin_Shift
## 1 50.5 9.61616 1 0 0 0.26942006 -10.3
## 2 50.9 11.66319 1 0 0 0.03808307 -9.0
## 3 50.5 11.57905 1 0 0 0.20247471 -9.2
## 4 50.7 10.84754 1 0 0 0.11091497 -9.8
## 5 51.4 10.95429 1 0 0 0.01358806 -7.7
## 6 51.1 12.90726 1 0 0 0.93232706 -2.1
## District_DEM_Win
## 1 0
## 2 0
## 3 0
## 4 0
## 5 0
## 6 1
write.csv(final_districts, "output data/final_districts.csv")
# house districts data
district_house <- final_districts %>%
filter(Office == "Representative") %>%
select(-c(Office, District, State, Special))
# senate districts data
district_senate <- final_districts %>%
filter(Office == "Senator") %>%
select(-c(Office, District, State, Special))
# competitive house districts data
competitive_districts_house <- final_districts %>%
filter(Office == "Representative" & abs(Dem_Margin_2020) <= 10) %>%
select(-c(Office, District, State, Special))
Fundraising model
candidate_house_fundraising <- glm(Fundraising_Prop ~ . - Winner, data = candidate_house, family="gaussian")
summary(candidate_house_fundraising)
##
## Call:
## glm(formula = Fundraising_Prop ~ . - Winner, family = "gaussian",
## data = candidate_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.63410 -0.13162 0.00857 0.13026 0.69643
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.708e-01 5.384e-01 1.432 0.15265
## Abortion_Salience 1.028e-02 3.188e-03 3.225 0.00131 **
## Illegal.Status -2.924e-02 2.569e-02 -1.138 0.25537
## Hostile.Status -3.949e-02 1.888e-02 -2.091 0.03684 *
## Gender.Num -7.473e-03 1.464e-02 -0.511 0.60983
## Share_Bachelors -8.266e-04 1.390e-03 -0.595 0.55216
## Adherence_per_1000_Evan 2.917e-04 1.474e-04 1.979 0.04813 *
## Election_Denier.Num -5.378e-02 2.077e-02 -2.590 0.00979 **
## Party.Num -6.685e-03 1.609e-02 -0.416 0.67784
## White.Num 4.737e-02 2.839e-02 1.668 0.09563 .
## Black.Num -3.677e-02 3.164e-02 -1.162 0.24555
## Latino.Num 1.032e-02 3.304e-02 0.312 0.75478
## Incumbent.Num 5.772e-03 1.489e-02 0.388 0.69843
## Open.Num 2.882e-02 1.879e-02 1.533 0.12557
## Dem_Margin_2020 1.053e-02 5.024e-04 20.951 < 2e-16 ***
## Share_Above_75k 4.606e-04 1.315e-03 0.350 0.72625
## Share_Age_15_to_44 -8.608e-04 2.679e-03 -0.321 0.74809
## Share_Female -6.664e-05 9.770e-03 -0.007 0.99456
## Share_White -1.181e-03 7.621e-04 -1.550 0.12150
## urbanindex -2.447e-02 9.954e-03 -2.458 0.01418 *
## South -1.764e-01 3.220e-02 -5.478 5.85e-08 ***
## West -6.213e-02 2.537e-02 -2.449 0.01454 *
## Midwest -7.853e-02 2.500e-02 -3.141 0.00175 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 0.03306338)
##
## Null deviance: 107.878 on 785 degrees of freedom
## Residual deviance: 25.227 on 763 degrees of freedom
## (2 observations deleted due to missingness)
## AIC: -424.5
##
## Number of Fisher Scoring iterations: 2
candidate_senate_fundraising <- glm(Fundraising_Prop ~ . - Winner, data = candidate_senate, family="gaussian")
summary(candidate_senate_fundraising)
##
## Call:
## glm(formula = Fundraising_Prop ~ . - Winner, family = "gaussian",
## data = candidate_senate)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.25470 -0.08776 -0.01271 0.06814 0.33190
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.9123467 3.4410920 1.428 0.161379
## Abortion_Salience 0.0403511 0.0100779 4.004 0.000271 ***
## Illegal.Status 0.3777728 0.0978391 3.861 0.000414 ***
## Hostile.Status 0.2076278 0.0767153 2.706 0.010036 *
## Gender.Num 0.0115064 0.0503462 0.229 0.820416
## Share_Bachelors 0.0312148 0.0139184 2.243 0.030673 *
## Adherence_per_1000_Evan -0.0009983 0.0005060 -1.973 0.055632 .
## Election_Denier.Num 0.1358189 0.0648043 2.096 0.042637 *
## Party.Num 0.0437034 0.0447306 0.977 0.334573
## White.Num 0.0341978 0.1034687 0.331 0.742781
## Black.Num 0.0366673 0.1261842 0.291 0.772908
## Latino.Num 0.0152442 0.1187832 0.128 0.898542
## Incumbent.Num 0.0186913 0.0481982 0.388 0.700272
## Open.Num 0.1471787 0.0744451 1.977 0.055141 .
## Dem_Margin_2020 0.0128065 0.0027044 4.735 2.88e-05 ***
## Share_Above_75k -0.0216190 0.0097682 -2.213 0.032804 *
## Share_Age_15_to_44 -0.0330758 0.0242757 -1.363 0.180855
## Share_Female -0.0878430 0.0645169 -1.362 0.181154
## Share_White -0.0046213 0.0027813 -1.662 0.104625
## urbanindex 0.0894317 0.0470481 1.901 0.064730 .
## South 0.1782944 0.1161134 1.536 0.132730
## West 0.1015878 0.0974309 1.043 0.303524
## Midwest 0.2489830 0.0869841 2.862 0.006730 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 0.02100723)
##
## Null deviance: 6.72894 on 61 degrees of freedom
## Residual deviance: 0.81928 on 39 degrees of freedom
## AIC: -44.292
##
## Number of Fisher Scoring iterations: 2
competitive_candidate_house_fundraising <- glm(Fundraising_Prop ~ . - Winner, data = competitive_candidate_house, family="gaussian")
summary(competitive_candidate_house_fundraising)
##
## Call:
## glm(formula = Fundraising_Prop ~ . - Winner, family = "gaussian",
## data = competitive_candidate_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.31045 -0.12713 0.00371 0.11336 0.38221
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.3892630 2.0195311 0.193 0.84745
## Abortion_Salience 0.0220186 0.0081893 2.689 0.00809 **
## Illegal.Status 0.0106163 0.0869439 0.122 0.90300
## Hostile.Status -0.0414703 0.0418267 -0.991 0.32325
## Gender.Num -0.0328413 0.0311922 -1.053 0.29431
## Share_Bachelors 0.0029117 0.0033659 0.865 0.38856
## Adherence_per_1000_Evan 0.0004750 0.0005544 0.857 0.39314
## Election_Denier.Num 0.0056337 0.0451880 0.125 0.90097
## Party.Num 0.0140944 0.0320878 0.439 0.66120
## White.Num 0.1195727 0.0633592 1.887 0.06131 .
## Black.Num -0.0065050 0.0741638 -0.088 0.93024
## Latino.Num 0.0444779 0.0670055 0.664 0.50797
## Incumbent.Num -0.0205920 0.0351686 -0.586 0.55919
## Open.Num 0.0189792 0.0366768 0.517 0.60569
## Dem_Margin_2020 0.0184408 0.0029347 6.284 4.38e-09 ***
## Share_Above_75k 0.0024235 0.0030830 0.786 0.43321
## Share_Age_15_to_44 0.0051080 0.0084984 0.601 0.54883
## Share_Female 0.0026979 0.0363875 0.074 0.94101
## Share_White -0.0016904 0.0020639 -0.819 0.41423
## urbanindex -0.0580724 0.0223054 -2.604 0.01028 *
## South -0.1797212 0.0916540 -1.961 0.05198 .
## West -0.0212826 0.0616346 -0.345 0.73041
## Midwest -0.0535294 0.0578421 -0.925 0.35641
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 0.03010349)
##
## Null deviance: 8.3762 on 155 degrees of freedom
## Residual deviance: 4.0038 on 133 degrees of freedom
## AIC: -80.66
##
## Number of Fisher Scoring iterations: 2
a <- candidate_house_fundraising
b <- candidate_senate_fundraising
c <- competitive_candidate_house_fundraising
stargazer(a, b, c,
title="Table 1. Candidate Fundraising Model Results",
type = "html",
out="figures/Table_1.doc",
align=TRUE)
##
## <table style="text-align:center"><caption><strong>Table 1. Candidate Fundraising Model Results</strong></caption>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"></td><td colspan="3"><em>Dependent variable:</em></td></tr>
## <tr><td></td><td colspan="3" style="border-bottom: 1px solid black"></td></tr>
## <tr><td style="text-align:left"></td><td colspan="3">Fundraising_Prop</td></tr>
## <tr><td style="text-align:left"></td><td>(1)</td><td>(2)</td><td>(3)</td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Abortion_Salience</td><td>0.010<sup>***</sup></td><td>0.040<sup>***</sup></td><td>0.022<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.003)</td><td>(0.010)</td><td>(0.008)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Illegal.Status</td><td>-0.029</td><td>0.378<sup>***</sup></td><td>0.011</td></tr>
## <tr><td style="text-align:left"></td><td>(0.026)</td><td>(0.098)</td><td>(0.087)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Hostile.Status</td><td>-0.039<sup>**</sup></td><td>0.208<sup>**</sup></td><td>-0.041</td></tr>
## <tr><td style="text-align:left"></td><td>(0.019)</td><td>(0.077)</td><td>(0.042)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Gender.Num</td><td>-0.007</td><td>0.012</td><td>-0.033</td></tr>
## <tr><td style="text-align:left"></td><td>(0.015)</td><td>(0.050)</td><td>(0.031)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Bachelors</td><td>-0.001</td><td>0.031<sup>**</sup></td><td>0.003</td></tr>
## <tr><td style="text-align:left"></td><td>(0.001)</td><td>(0.014)</td><td>(0.003)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Adherence_per_1000_Evan</td><td>0.0003<sup>**</sup></td><td>-0.001<sup>*</sup></td><td>0.0005</td></tr>
## <tr><td style="text-align:left"></td><td>(0.0001)</td><td>(0.001)</td><td>(0.001)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Election_Denier.Num</td><td>-0.054<sup>***</sup></td><td>0.136<sup>**</sup></td><td>0.006</td></tr>
## <tr><td style="text-align:left"></td><td>(0.021)</td><td>(0.065)</td><td>(0.045)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Party.Num</td><td>-0.007</td><td>0.044</td><td>0.014</td></tr>
## <tr><td style="text-align:left"></td><td>(0.016)</td><td>(0.045)</td><td>(0.032)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">White.Num</td><td>0.047<sup>*</sup></td><td>0.034</td><td>0.120<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.028)</td><td>(0.103)</td><td>(0.063)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Black.Num</td><td>-0.037</td><td>0.037</td><td>-0.007</td></tr>
## <tr><td style="text-align:left"></td><td>(0.032)</td><td>(0.126)</td><td>(0.074)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Latino.Num</td><td>0.010</td><td>0.015</td><td>0.044</td></tr>
## <tr><td style="text-align:left"></td><td>(0.033)</td><td>(0.119)</td><td>(0.067)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Incumbent.Num</td><td>0.006</td><td>0.019</td><td>-0.021</td></tr>
## <tr><td style="text-align:left"></td><td>(0.015)</td><td>(0.048)</td><td>(0.035)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Open.Num</td><td>0.029</td><td>0.147<sup>*</sup></td><td>0.019</td></tr>
## <tr><td style="text-align:left"></td><td>(0.019)</td><td>(0.074)</td><td>(0.037)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Margin_2020</td><td>0.011<sup>***</sup></td><td>0.013<sup>***</sup></td><td>0.018<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.001)</td><td>(0.003)</td><td>(0.003)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Above_75k</td><td>0.0005</td><td>-0.022<sup>**</sup></td><td>0.002</td></tr>
## <tr><td style="text-align:left"></td><td>(0.001)</td><td>(0.010)</td><td>(0.003)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Age_15_to_44</td><td>-0.001</td><td>-0.033</td><td>0.005</td></tr>
## <tr><td style="text-align:left"></td><td>(0.003)</td><td>(0.024)</td><td>(0.008)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Female</td><td>-0.0001</td><td>-0.088</td><td>0.003</td></tr>
## <tr><td style="text-align:left"></td><td>(0.010)</td><td>(0.065)</td><td>(0.036)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_White</td><td>-0.001</td><td>-0.005</td><td>-0.002</td></tr>
## <tr><td style="text-align:left"></td><td>(0.001)</td><td>(0.003)</td><td>(0.002)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">urbanindex</td><td>-0.024<sup>**</sup></td><td>0.089<sup>*</sup></td><td>-0.058<sup>**</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.010)</td><td>(0.047)</td><td>(0.022)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">South</td><td>-0.176<sup>***</sup></td><td>0.178</td><td>-0.180<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.032)</td><td>(0.116)</td><td>(0.092)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">West</td><td>-0.062<sup>**</sup></td><td>0.102</td><td>-0.021</td></tr>
## <tr><td style="text-align:left"></td><td>(0.025)</td><td>(0.097)</td><td>(0.062)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Midwest</td><td>-0.079<sup>***</sup></td><td>0.249<sup>***</sup></td><td>-0.054</td></tr>
## <tr><td style="text-align:left"></td><td>(0.025)</td><td>(0.087)</td><td>(0.058)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Constant</td><td>0.771</td><td>4.912</td><td>0.389</td></tr>
## <tr><td style="text-align:left"></td><td>(0.538)</td><td>(3.441)</td><td>(2.020)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Observations</td><td>786</td><td>62</td><td>156</td></tr>
## <tr><td style="text-align:left">Log Likelihood</td><td>235.252</td><td>45.146</td><td>63.330</td></tr>
## <tr><td style="text-align:left">Akaike Inf. Crit.</td><td>-424.504</td><td>-44.292</td><td>-80.660</td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"><em>Note:</em></td><td colspan="3" style="text-align:right"><sup>*</sup>p<0.1; <sup>**</sup>p<0.05; <sup>***</sup>p<0.01</td></tr>
## </table>
house_r_squared <- with(summary(candidate_house_fundraising), 1 - deviance/null.deviance)
house_adj_r_squared <- adjR2(candidate_house_fundraising)
## [1] 0.7594
senate_r_squared <- with(summary(candidate_senate_fundraising), 1 - deviance/null.deviance)
senate_adj_r_squared <- adjR2(candidate_senate_fundraising)
## [1] 0.8096
house_comp_r_squared <- with(summary(competitive_candidate_house_fundraising), 1 - deviance/null.deviance)
house_compe_adj_r_squared <- adjR2(competitive_candidate_house_fundraising )
## [1] 0.4429
r_squared <- round(c(house_r_squared, senate_r_squared, house_comp_r_squared), 3)
r_squared
## [1] 0.766 0.878 0.522
adj_r_squared <- round(c(house_adj_r_squared, senate_adj_r_squared, house_compe_adj_r_squared), 3)
adj_r_squared
## [1] 0.759 0.810 0.443
Candidate Win model
candidate_house_win <- glm(Winner ~ . , data = candidate_house, family="binomial")
summary(candidate_house_win)
##
## Call:
## glm(formula = Winner ~ ., family = "binomial", data = candidate_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -3.02956 -0.19068 -0.01626 0.22979 3.01891
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.012e+01 1.363e+01 -0.743 0.45767
## Abortion_Salience 2.741e-02 7.538e-02 0.364 0.71612
## Illegal.Status 2.091e-01 6.218e-01 0.336 0.73668
## Hostile.Status 6.625e-02 4.362e-01 0.152 0.87929
## Gender.Num 3.604e-01 3.384e-01 1.065 0.28682
## Share_Bachelors 1.113e-02 3.440e-02 0.323 0.74636
## Adherence_per_1000_Evan 3.562e-04 3.831e-03 0.093 0.92591
## Election_Denier.Num 6.002e-01 4.977e-01 1.206 0.22785
## Party.Num -3.144e-01 3.535e-01 -0.889 0.37385
## White.Num 3.209e-01 6.388e-01 0.502 0.61538
## Black.Num 3.203e-01 7.007e-01 0.457 0.64760
## Latino.Num 2.052e+00 7.539e-01 2.721 0.00651 **
## Incumbent.Num 7.796e+00 5.656e-01 13.784 < 2e-16 ***
## Open.Num 4.011e+00 4.536e-01 8.843 < 2e-16 ***
## Dem_Margin_2020 4.814e-03 1.369e-02 0.352 0.72503
## Share_Above_75k 6.901e-03 3.101e-02 0.223 0.82386
## Share_Age_15_to_44 -1.110e-02 6.411e-02 -0.173 0.86251
## Share_Female 1.293e-01 2.454e-01 0.527 0.59824
## Share_White 1.554e-03 1.767e-02 0.088 0.92994
## urbanindex -1.627e-01 2.268e-01 -0.717 0.47324
## South -2.250e-01 8.050e-01 -0.280 0.77986
## West 8.821e-02 5.946e-01 0.148 0.88206
## Midwest 1.738e-01 5.837e-01 0.298 0.76594
## Fundraising_Prop -9.708e-02 7.884e-01 -0.123 0.90199
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1089.63 on 785 degrees of freedom
## Residual deviance: 313.99 on 762 degrees of freedom
## (2 observations deleted due to missingness)
## AIC: 361.99
##
## Number of Fisher Scoring iterations: 6
candidate_senate_win <- glm(Winner ~ . - Incumbent.Num, data = candidate_senate, family="binomial")
summary(candidate_senate_win)
##
## Call:
## glm(formula = Winner ~ . - Incumbent.Num, family = "binomial",
## data = candidate_senate)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.0067 -0.8351 -0.2531 0.8716 1.6818
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -5.092e+01 6.453e+01 -0.789 0.4300
## Abortion_Salience 8.696e-02 2.113e-01 0.412 0.6806
## Illegal.Status -1.041e+00 1.820e+00 -0.572 0.5674
## Hostile.Status 2.373e-01 1.303e+00 0.182 0.8555
## Gender.Num 1.724e+00 8.569e-01 2.011 0.0443 *
## Share_Bachelors 9.856e-02 2.486e-01 0.396 0.6918
## Adherence_per_1000_Evan 4.583e-03 8.339e-03 0.550 0.5826
## Election_Denier.Num -6.594e-01 1.028e+00 -0.642 0.5210
## Party.Num 5.883e-01 7.222e-01 0.815 0.4153
## White.Num 1.011e+00 1.613e+00 0.627 0.5307
## Black.Num -2.541e+00 2.094e+00 -1.214 0.2249
## Latino.Num 2.304e+00 1.889e+00 1.219 0.2227
## Open.Num -1.113e+00 1.163e+00 -0.957 0.3388
## Dem_Margin_2020 2.089e-03 5.264e-02 0.040 0.9683
## Share_Above_75k -5.785e-02 1.637e-01 -0.353 0.7237
## Share_Age_15_to_44 -5.910e-02 4.745e-01 -0.125 0.9009
## Share_Female 1.046e+00 1.176e+00 0.890 0.3737
## Share_White -5.122e-04 4.473e-02 -0.011 0.9909
## urbanindex -3.310e-01 8.676e-01 -0.382 0.7028
## South 1.071e-01 2.240e+00 0.048 0.9619
## West 7.758e-01 1.681e+00 0.462 0.6444
## Midwest 4.541e-01 1.609e+00 0.282 0.7777
## Fundraising_Prop -6.502e-01 2.523e+00 -0.258 0.7966
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 85.886 on 61 degrees of freedom
## Residual deviance: 68.192 on 39 degrees of freedom
## AIC: 114.19
##
## Number of Fisher Scoring iterations: 4
competitive_candidate_house_win <- glm(Winner ~ . , data = competitive_candidate_house, family="binomial")
summary(competitive_candidate_house_win)
##
## Call:
## glm(formula = Winner ~ ., family = "binomial", data = competitive_candidate_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.46181 -0.62521 0.00135 0.58853 2.27556
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.800e+01 3.499e+01 -0.514 0.606926
## Abortion_Salience -4.282e-02 1.368e-01 -0.313 0.754183
## Illegal.Status -1.108e+00 1.471e+00 -0.753 0.451471
## Hostile.Status 8.661e-02 6.983e-01 0.124 0.901288
## Gender.Num 9.174e-01 5.494e-01 1.670 0.094965 .
## Share_Bachelors -2.868e-03 5.751e-02 -0.050 0.960224
## Adherence_per_1000_Evan -2.661e-04 9.254e-03 -0.029 0.977058
## Election_Denier.Num -8.520e-01 7.941e-01 -1.073 0.283274
## Party.Num -1.480e+00 5.442e-01 -2.719 0.006544 **
## White.Num -3.479e-01 1.115e+00 -0.312 0.755015
## Black.Num -5.646e-01 1.276e+00 -0.442 0.658229
## Latino.Num 2.071e+00 1.175e+00 1.763 0.077958 .
## Incumbent.Num 4.864e+00 7.670e-01 6.342 2.27e-10 ***
## Open.Num 2.317e+00 6.314e-01 3.669 0.000243 ***
## Dem_Margin_2020 -3.434e-03 5.816e-02 -0.059 0.952918
## Share_Above_75k -2.877e-03 5.117e-02 -0.056 0.955157
## Share_Age_15_to_44 4.176e-02 1.420e-01 0.294 0.768656
## Share_Female 2.780e-01 6.287e-01 0.442 0.658322
## Share_White 1.438e-02 3.286e-02 0.438 0.661586
## urbanindex -8.095e-03 3.527e-01 -0.023 0.981688
## South 1.925e-01 1.554e+00 0.124 0.901429
## West 2.845e-01 1.074e+00 0.265 0.791206
## Midwest 1.217e-01 9.613e-01 0.127 0.899258
## Fundraising_Prop 2.921e-01 1.532e+00 0.191 0.848852
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 216.26 on 155 degrees of freedom
## Residual deviance: 127.47 on 132 degrees of freedom
## AIC: 175.47
##
## Number of Fisher Scoring iterations: 5
logit2prob <- function(logit){
odds <- exp(logit)
prob <- odds / (1 + odds)
return(prob)
}
logit2prob(coef(candidate_senate_win))
## (Intercept) Abortion_Salience Illegal.Status
## 7.649635e-23 5.217259e-01 2.609862e-01
## Hostile.Status Gender.Num Share_Bachelors
## 5.590428e-01 8.486038e-01 5.246204e-01
## Adherence_per_1000_Evan Election_Denier.Num Party.Num
## 5.011457e-01 3.408637e-01 6.429781e-01
## White.Num Black.Num Latino.Num
## 7.332158e-01 7.305217e-02 9.091914e-01
## Open.Num Dem_Margin_2020 Share_Above_75k
## 2.473620e-01 5.005222e-01 4.855405e-01
## Share_Age_15_to_44 Share_Female Share_White
## 4.852297e-01 7.399409e-01 4.998720e-01
## urbanindex South West
## 4.179909e-01 5.267525e-01 6.847674e-01
## Midwest Fundraising_Prop
## 6.116211e-01 3.429403e-01
a <- candidate_house_win
b <- candidate_senate_win
c <- competitive_candidate_house_win
stargazer(a, b, c,
title="Table 2. Candidate Win Model Results",
type = "html",
out="figures/Table_2.doc",
align=TRUE)
##
## <table style="text-align:center"><caption><strong>Table 2. Candidate Win Model Results</strong></caption>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"></td><td colspan="3"><em>Dependent variable:</em></td></tr>
## <tr><td></td><td colspan="3" style="border-bottom: 1px solid black"></td></tr>
## <tr><td style="text-align:left"></td><td colspan="3">Winner</td></tr>
## <tr><td style="text-align:left"></td><td>(1)</td><td>(2)</td><td>(3)</td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Abortion_Salience</td><td>0.027</td><td>0.087</td><td>-0.043</td></tr>
## <tr><td style="text-align:left"></td><td>(0.075)</td><td>(0.211)</td><td>(0.137)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Illegal.Status</td><td>0.209</td><td>-1.041</td><td>-1.108</td></tr>
## <tr><td style="text-align:left"></td><td>(0.622)</td><td>(1.820)</td><td>(1.471)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Hostile.Status</td><td>0.066</td><td>0.237</td><td>0.087</td></tr>
## <tr><td style="text-align:left"></td><td>(0.436)</td><td>(1.303)</td><td>(0.698)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Gender.Num</td><td>0.360</td><td>1.724<sup>**</sup></td><td>0.917<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.338)</td><td>(0.857)</td><td>(0.549)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Bachelors</td><td>0.011</td><td>0.099</td><td>-0.003</td></tr>
## <tr><td style="text-align:left"></td><td>(0.034)</td><td>(0.249)</td><td>(0.058)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Adherence_per_1000_Evan</td><td>0.0004</td><td>0.005</td><td>-0.0003</td></tr>
## <tr><td style="text-align:left"></td><td>(0.004)</td><td>(0.008)</td><td>(0.009)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Election_Denier.Num</td><td>0.600</td><td>-0.659</td><td>-0.852</td></tr>
## <tr><td style="text-align:left"></td><td>(0.498)</td><td>(1.028)</td><td>(0.794)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Party.Num</td><td>-0.314</td><td>0.588</td><td>-1.480<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.354)</td><td>(0.722)</td><td>(0.544)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">White.Num</td><td>0.321</td><td>1.011</td><td>-0.348</td></tr>
## <tr><td style="text-align:left"></td><td>(0.639)</td><td>(1.613)</td><td>(1.115)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Black.Num</td><td>0.320</td><td>-2.541</td><td>-0.565</td></tr>
## <tr><td style="text-align:left"></td><td>(0.701)</td><td>(2.094)</td><td>(1.276)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Latino.Num</td><td>2.052<sup>***</sup></td><td>2.304</td><td>2.071<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.754)</td><td>(1.889)</td><td>(1.175)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Incumbent.Num</td><td>7.796<sup>***</sup></td><td></td><td>4.864<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.566)</td><td></td><td>(0.767)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Open.Num</td><td>4.011<sup>***</sup></td><td>-1.113</td><td>2.317<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.454)</td><td>(1.163)</td><td>(0.631)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Margin_2020</td><td>0.005</td><td>0.002</td><td>-0.003</td></tr>
## <tr><td style="text-align:left"></td><td>(0.014)</td><td>(0.053)</td><td>(0.058)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Above_75k</td><td>0.007</td><td>-0.058</td><td>-0.003</td></tr>
## <tr><td style="text-align:left"></td><td>(0.031)</td><td>(0.164)</td><td>(0.051)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Age_15_to_44</td><td>-0.011</td><td>-0.059</td><td>0.042</td></tr>
## <tr><td style="text-align:left"></td><td>(0.064)</td><td>(0.475)</td><td>(0.142)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Female</td><td>0.129</td><td>1.046</td><td>0.278</td></tr>
## <tr><td style="text-align:left"></td><td>(0.245)</td><td>(1.176)</td><td>(0.629)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_White</td><td>0.002</td><td>-0.001</td><td>0.014</td></tr>
## <tr><td style="text-align:left"></td><td>(0.018)</td><td>(0.045)</td><td>(0.033)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">urbanindex</td><td>-0.163</td><td>-0.331</td><td>-0.008</td></tr>
## <tr><td style="text-align:left"></td><td>(0.227)</td><td>(0.868)</td><td>(0.353)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">South</td><td>-0.225</td><td>0.107</td><td>0.193</td></tr>
## <tr><td style="text-align:left"></td><td>(0.805)</td><td>(2.240)</td><td>(1.554)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">West</td><td>0.088</td><td>0.776</td><td>0.284</td></tr>
## <tr><td style="text-align:left"></td><td>(0.595)</td><td>(1.681)</td><td>(1.074)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Midwest</td><td>0.174</td><td>0.454</td><td>0.122</td></tr>
## <tr><td style="text-align:left"></td><td>(0.584)</td><td>(1.609)</td><td>(0.961)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Fundraising_Prop</td><td>-0.097</td><td>-0.650</td><td>0.292</td></tr>
## <tr><td style="text-align:left"></td><td>(0.788)</td><td>(2.523)</td><td>(1.532)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Constant</td><td>-10.121</td><td>-50.925</td><td>-18.003</td></tr>
## <tr><td style="text-align:left"></td><td>(13.628)</td><td>(64.528)</td><td>(34.994)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Observations</td><td>786</td><td>62</td><td>156</td></tr>
## <tr><td style="text-align:left">Log Likelihood</td><td>-156.994</td><td>-34.096</td><td>-63.735</td></tr>
## <tr><td style="text-align:left">Akaike Inf. Crit.</td><td>361.988</td><td>114.192</td><td>175.470</td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"><em>Note:</em></td><td colspan="3" style="text-align:right"><sup>*</sup>p<0.1; <sup>**</sup>p<0.05; <sup>***</sup>p<0.01</td></tr>
## </table>
house_r_squared <- with(summary(candidate_house_win), 1 - deviance/null.deviance)
house_adj_r_squared <- adjR2(candidate_house_win)
## [1] 0.7031
senate_r_squared <- with(summary(candidate_senate_win), 1 - deviance/null.deviance)
senate_adj_r_squared <- adjR2(candidate_senate_win)
## [1] -0.2419
house_comp_r_squared <- with(summary(competitive_candidate_house_win), 1 - deviance/null.deviance)
house_compe_adj_r_squared <- adjR2(competitive_candidate_house_win)
## [1] 0.3079
r_squared <- round(c(house_r_squared, senate_r_squared, house_comp_r_squared), 3)
r_squared
## [1] 0.712 0.206 0.411
adj_r_squared <- round(c(house_adj_r_squared, senate_adj_r_squared, house_compe_adj_r_squared), 3)
adj_r_squared
## [1] 0.703 -0.242 0.308
District Shift model
district_house_shift <- glm(Dem_Margin_Shift ~ ., data = district_house, family="gaussian")
summary(district_house_shift)
##
## Call:
## glm(formula = Dem_Margin_Shift ~ ., family = "gaussian", data = district_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -11.3083 -2.3129 -0.1258 2.2451 24.1810
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 19.15347 17.76635 1.078 0.28170
## Abortion_Salience -0.33375 0.10662 -3.130 0.00189 **
## Illegal.Status 4.41746 0.85383 5.174 3.77e-07 ***
## Hostile.Status 4.31183 0.63057 6.838 3.33e-11 ***
## Dem_Woman_Rep_Man -0.54103 0.49450 -1.094 0.27462
## Dem_Man_Rep_Woman 0.32371 0.73585 0.440 0.66025
## Dem_Woman_Rep_Woman -0.08178 0.79719 -0.103 0.91835
## Share_Bachelors 0.03260 0.04640 0.703 0.48276
## Adherence_per_1000_Evan -0.01296 0.00491 -2.639 0.00867 **
## Rep_Election_Denier 1.30717 0.50693 2.579 0.01031 *
## Dem_Incumbent 1.06740 0.76976 1.387 0.16638
## Rep_Incumbent -1.30620 0.77405 -1.687 0.09235 .
## Dem_Margin_2020 -0.04419 0.02216 -1.995 0.04682 *
## Share_Above_75k -0.07443 0.04398 -1.692 0.09144 .
## Share_White 0.11214 0.02479 4.523 8.23e-06 ***
## Share_Age_15_to_44 -0.08218 0.08901 -0.923 0.35649
## Share_Female -0.48973 0.32081 -1.527 0.12772
## urbanindex -0.51994 0.33185 -1.567 0.11802
## South 2.75534 1.08661 2.536 0.01163 *
## West 1.67229 0.84459 1.980 0.04844 *
## Midwest 1.75110 0.83936 2.086 0.03764 *
## Fundraising_Prop 9.57720 1.32352 7.236 2.68e-12 ***
## District_DEM_Win 4.50261 1.02852 4.378 1.56e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 18.1776)
##
## Null deviance: 13516.0 on 392 degrees of freedom
## Residual deviance: 6725.7 on 370 degrees of freedom
## (1 observation deleted due to missingness)
## AIC: 2279.4
##
## Number of Fisher Scoring iterations: 2
district_senate_shift <- glm(Dem_Margin_Shift ~ ., data = district_senate, family="gaussian")
summary(district_senate_shift)
##
## Call:
## glm(formula = Dem_Margin_Shift ~ ., family = "gaussian", data = district_senate)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -4.177 -1.248 0.204 1.901 3.945
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 485.147728 230.014340 2.109 0.0680 .
## Abortion_Salience 0.526353 0.588602 0.894 0.3973
## Illegal.Status 13.345946 5.594487 2.386 0.0442 *
## Hostile.Status 6.755777 3.987420 1.694 0.1287
## Dem_Woman_Rep_Man -1.649461 2.908349 -0.567 0.5862
## Dem_Man_Rep_Woman -4.020081 3.856900 -1.042 0.3277
## Dem_Woman_Rep_Woman -7.362884 6.908707 -1.066 0.3176
## Share_Bachelors 0.749649 0.672470 1.115 0.2973
## Adherence_per_1000_Evan 0.013594 0.025886 0.525 0.6137
## Rep_Election_Denier -1.954112 3.531101 -0.553 0.5951
## Dem_Incumbent -0.424918 7.088472 -0.060 0.9537
## Rep_Incumbent -8.091423 5.956094 -1.359 0.2114
## Dem_Margin_2020 -0.003393 0.189877 -0.018 0.9862
## Share_Above_75k -0.183352 0.515028 -0.356 0.7310
## Share_White -0.125617 0.165189 -0.760 0.4688
## Share_Age_15_to_44 -3.055194 1.707213 -1.790 0.1113
## Share_Female -7.467760 3.859605 -1.935 0.0891 .
## urbanindex -1.635559 2.514936 -0.650 0.5337
## South 7.322645 7.778260 0.941 0.3740
## West 5.723521 6.286324 0.910 0.3892
## Midwest 11.180536 8.534203 1.310 0.2265
## Fundraising_Prop -3.070798 11.100885 -0.277 0.7891
## District_DEM_Win 10.640023 7.790518 1.366 0.2092
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 18.78929)
##
## Null deviance: 1143.50 on 30 degrees of freedom
## Residual deviance: 150.31 on 8 degrees of freedom
## AIC: 184.92
##
## Number of Fisher Scoring iterations: 2
competitive_districts_house_shift <- glm(Dem_Margin_Shift ~ ., data = competitive_districts_house, family="gaussian")
summary(competitive_districts_house_shift)
##
## Call:
## glm(formula = Dem_Margin_Shift ~ ., family = "gaussian", data = competitive_districts_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -10.5796 -2.0587 -0.0487 1.3447 9.4971
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -41.48910 61.17167 -0.678 0.500463
## Abortion_Salience -0.43112 0.26871 -1.604 0.114356
## Illegal.Status 8.12014 2.72766 2.977 0.004322 **
## Hostile.Status 3.91459 1.35543 2.888 0.005533 **
## Dem_Woman_Rep_Man -0.38734 1.21735 -0.318 0.751552
## Dem_Man_Rep_Woman 1.30907 1.45768 0.898 0.373071
## Dem_Woman_Rep_Woman -0.35299 1.41790 -0.249 0.804324
## Share_Bachelors 0.10855 0.11029 0.984 0.329315
## Adherence_per_1000_Evan -0.02415 0.01845 -1.309 0.196010
## Rep_Election_Denier 1.54103 1.10622 1.393 0.169207
## Dem_Incumbent 3.45055 1.36371 2.530 0.014290 *
## Rep_Incumbent -1.98977 1.28037 -1.554 0.125908
## Dem_Margin_2020 -0.32656 0.13312 -2.453 0.017359 *
## Share_Above_75k -0.13803 0.09759 -1.414 0.162879
## Share_White 0.18440 0.06530 2.824 0.006591 **
## Share_Age_15_to_44 0.07642 0.27106 0.282 0.779050
## Share_Female 0.52029 1.10612 0.470 0.639950
## urbanindex -0.68500 0.72403 -0.946 0.348240
## South 5.48802 3.05482 1.797 0.077906 .
## West 6.37090 1.92145 3.316 0.001623 **
## Midwest 3.40902 1.85702 1.836 0.071803 .
## Fundraising_Prop 10.64218 2.86712 3.712 0.000482 ***
## District_DEM_Win 6.59599 1.61261 4.090 0.000142 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 14.6557)
##
## Null deviance: 4417.79 on 77 degrees of freedom
## Residual deviance: 806.06 on 55 degrees of freedom
## AIC: 451.52
##
## Number of Fisher Scoring iterations: 2
a <- district_house_shift
b <- district_senate_shift
c <- competitive_districts_house_shift
stargazer(a, b, c,
title="Table 3. District Margin Shift Model Results",
type = "html",
out="figures/Table_3.doc",
align=TRUE)
##
## <table style="text-align:center"><caption><strong>Table 3. District Margin Shift Model Results</strong></caption>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"></td><td colspan="3"><em>Dependent variable:</em></td></tr>
## <tr><td></td><td colspan="3" style="border-bottom: 1px solid black"></td></tr>
## <tr><td style="text-align:left"></td><td colspan="3">Dem_Margin_Shift</td></tr>
## <tr><td style="text-align:left"></td><td>(1)</td><td>(2)</td><td>(3)</td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Abortion_Salience</td><td>-0.334<sup>***</sup></td><td>0.526</td><td>-0.431</td></tr>
## <tr><td style="text-align:left"></td><td>(0.107)</td><td>(0.589)</td><td>(0.269)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Illegal.Status</td><td>4.417<sup>***</sup></td><td>13.346<sup>**</sup></td><td>8.120<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.854)</td><td>(5.594)</td><td>(2.728)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Hostile.Status</td><td>4.312<sup>***</sup></td><td>6.756</td><td>3.915<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.631)</td><td>(3.987)</td><td>(1.355)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Woman_Rep_Man</td><td>-0.541</td><td>-1.649</td><td>-0.387</td></tr>
## <tr><td style="text-align:left"></td><td>(0.494)</td><td>(2.908)</td><td>(1.217)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Man_Rep_Woman</td><td>0.324</td><td>-4.020</td><td>1.309</td></tr>
## <tr><td style="text-align:left"></td><td>(0.736)</td><td>(3.857)</td><td>(1.458)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Woman_Rep_Woman</td><td>-0.082</td><td>-7.363</td><td>-0.353</td></tr>
## <tr><td style="text-align:left"></td><td>(0.797)</td><td>(6.909)</td><td>(1.418)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Bachelors</td><td>0.033</td><td>0.750</td><td>0.109</td></tr>
## <tr><td style="text-align:left"></td><td>(0.046)</td><td>(0.672)</td><td>(0.110)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Adherence_per_1000_Evan</td><td>-0.013<sup>***</sup></td><td>0.014</td><td>-0.024</td></tr>
## <tr><td style="text-align:left"></td><td>(0.005)</td><td>(0.026)</td><td>(0.018)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Rep_Election_Denier</td><td>1.307<sup>**</sup></td><td>-1.954</td><td>1.541</td></tr>
## <tr><td style="text-align:left"></td><td>(0.507)</td><td>(3.531)</td><td>(1.106)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Incumbent</td><td>1.067</td><td>-0.425</td><td>3.451<sup>**</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.770)</td><td>(7.088)</td><td>(1.364)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Rep_Incumbent</td><td>-1.306<sup>*</sup></td><td>-8.091</td><td>-1.990</td></tr>
## <tr><td style="text-align:left"></td><td>(0.774)</td><td>(5.956)</td><td>(1.280)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Margin_2020</td><td>-0.044<sup>**</sup></td><td>-0.003</td><td>-0.327<sup>**</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.022)</td><td>(0.190)</td><td>(0.133)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Above_75k</td><td>-0.074<sup>*</sup></td><td>-0.183</td><td>-0.138</td></tr>
## <tr><td style="text-align:left"></td><td>(0.044)</td><td>(0.515)</td><td>(0.098)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_White</td><td>0.112<sup>***</sup></td><td>-0.126</td><td>0.184<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.025)</td><td>(0.165)</td><td>(0.065)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Age_15_to_44</td><td>-0.082</td><td>-3.055</td><td>0.076</td></tr>
## <tr><td style="text-align:left"></td><td>(0.089)</td><td>(1.707)</td><td>(0.271)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Female</td><td>-0.490</td><td>-7.468<sup>*</sup></td><td>0.520</td></tr>
## <tr><td style="text-align:left"></td><td>(0.321)</td><td>(3.860)</td><td>(1.106)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">urbanindex</td><td>-0.520</td><td>-1.636</td><td>-0.685</td></tr>
## <tr><td style="text-align:left"></td><td>(0.332)</td><td>(2.515)</td><td>(0.724)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">South</td><td>2.755<sup>**</sup></td><td>7.323</td><td>5.488<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(1.087)</td><td>(7.778)</td><td>(3.055)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">West</td><td>1.672<sup>**</sup></td><td>5.724</td><td>6.371<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.845)</td><td>(6.286)</td><td>(1.921)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Midwest</td><td>1.751<sup>**</sup></td><td>11.181</td><td>3.409<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.839)</td><td>(8.534)</td><td>(1.857)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Fundraising_Prop</td><td>9.577<sup>***</sup></td><td>-3.071</td><td>10.642<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(1.324)</td><td>(11.101)</td><td>(2.867)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">District_DEM_Win</td><td>4.503<sup>***</sup></td><td>10.640</td><td>6.596<sup>***</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(1.029)</td><td>(7.791)</td><td>(1.613)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Constant</td><td>19.153</td><td>485.148<sup>*</sup></td><td>-41.489</td></tr>
## <tr><td style="text-align:left"></td><td>(17.766)</td><td>(230.014)</td><td>(61.172)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td><td></td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Observations</td><td>393</td><td>31</td><td>78</td></tr>
## <tr><td style="text-align:left">Log Likelihood</td><td>-1,116.680</td><td>-69.458</td><td>-202.760</td></tr>
## <tr><td style="text-align:left">Akaike Inf. Crit.</td><td>2,279.360</td><td>184.915</td><td>451.520</td></tr>
## <tr><td colspan="4" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"><em>Note:</em></td><td colspan="3" style="text-align:right"><sup>*</sup>p<0.1; <sup>**</sup>p<0.05; <sup>***</sup>p<0.01</td></tr>
## </table>
house_r_squared <- with(summary(district_house_shift), 1 - deviance/null.deviance)
house_adj_r_squared <- adjR2(district_house_shift)
## [1] 0.4728
senate_r_squared <- with(summary(district_senate_shift), 1 - deviance/null.deviance)
senate_adj_r_squared <- adjR2(district_senate_shift)
## [1] 0.5071
house_comp_r_squared <- with(summary(competitive_districts_house_shift), 1 - deviance/null.deviance)
house_compe_adj_r_squared <- adjR2(competitive_districts_house_shift)
## [1] 0.7446
r_squared <- round(c(house_r_squared, senate_r_squared, house_comp_r_squared), 3)
r_squared
## [1] 0.502 0.869 0.818
adj_r_squared <- round(c(house_adj_r_squared, senate_adj_r_squared, house_compe_adj_r_squared), 3)
adj_r_squared
## [1] 0.473 0.507 0.745
District Win model
district_house_win <- glm(District_DEM_Win ~ . - Dem_Margin_Shift - Share_White - Share_Age_15_to_44 - Share_Female - Share_Above_75k , data = district_house, family="binomial")
## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
summary(district_house_win)
##
## Call:
## glm(formula = District_DEM_Win ~ . - Dem_Margin_Shift - Share_White -
## Share_Age_15_to_44 - Share_Female - Share_Above_75k, family = "binomial",
## data = district_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.23209 -0.00001 0.00000 0.00011 1.90205
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 6.74318 9.04761 0.745 0.45609
## Abortion_Salience -0.65091 0.42763 -1.522 0.12797
## Illegal.Status -4.16932 27.82084 -0.150 0.88087
## Hostile.Status 2.08570 1.74350 1.196 0.23159
## Dem_Woman_Rep_Man 1.25835 1.63754 0.768 0.44223
## Dem_Man_Rep_Woman 6.97448 3.77285 1.849 0.06452 .
## Dem_Woman_Rep_Woman -0.05878 1.58230 -0.037 0.97037
## Share_Bachelors -0.10138 0.06812 -1.488 0.13668
## Adherence_per_1000_Evan 0.03557 0.02159 1.648 0.09939 .
## Rep_Election_Denier 2.69299 1.59722 1.686 0.09179 .
## Dem_Incumbent 3.42009 1.29802 2.635 0.00842 **
## Rep_Incumbent -7.02974 2.96842 -2.368 0.01788 *
## Dem_Margin_2020 0.62343 0.20946 2.976 0.00292 **
## urbanindex -0.88623 0.77482 -1.144 0.25271
## South -4.98394 3.06318 -1.627 0.10373
## West -1.90650 1.90887 -0.999 0.31791
## Midwest -1.44982 2.19616 -0.660 0.50915
## Fundraising_Prop 10.92936 5.44756 2.006 0.04483 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 544.750 on 392 degrees of freedom
## Residual deviance: 36.545 on 375 degrees of freedom
## (1 observation deleted due to missingness)
## AIC: 72.545
##
## Number of Fisher Scoring iterations: 13
competitive_districts_house_win <- glm(District_DEM_Win ~ . - Dem_Margin_Shift - Share_White - Share_Age_15_to_44 - Share_Female - Share_Above_75k - South - Midwest - West, data = competitive_districts_house, family="binomial")
## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
summary(competitive_districts_house_win)
##
## Call:
## glm(formula = District_DEM_Win ~ . - Dem_Margin_Shift - Share_White -
## Share_Age_15_to_44 - Share_Female - Share_Above_75k - South -
## Midwest - West, family = "binomial", data = competitive_districts_house)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.81897 -0.00072 0.00000 0.00260 1.84993
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 30.91869 17.73965 1.743 0.0813 .
## Abortion_Salience -3.05691 1.69406 -1.804 0.0712 .
## Illegal.Status -2.53702 3215.93978 -0.001 0.9994
## Hostile.Status 6.61548 3.64572 1.815 0.0696 .
## Dem_Woman_Rep_Man 6.79193 4.47562 1.518 0.1291
## Dem_Man_Rep_Woman 9.40211 8.44607 1.113 0.2656
## Dem_Woman_Rep_Woman -4.50385 3.92825 -1.147 0.2516
## Share_Bachelors -0.54902 0.28921 -1.898 0.0577 .
## Adherence_per_1000_Evan -0.02432 0.02303 -1.056 0.2909
## Rep_Election_Denier 5.53850 3.05982 1.810 0.0703 .
## Dem_Incumbent 7.08121 4.47236 1.583 0.1133
## Rep_Incumbent -11.89676 8.83897 -1.346 0.1783
## Dem_Margin_2020 1.55300 0.76483 2.031 0.0423 *
## urbanindex -0.46092 1.02758 -0.449 0.6538
## Fundraising_Prop 34.66176 20.06711 1.727 0.0841 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 102.945 on 77 degrees of freedom
## Residual deviance: 17.449 on 63 degrees of freedom
## AIC: 47.449
##
## Number of Fisher Scoring iterations: 17
logit2prob <- function(logit){
odds <- exp(logit)
prob <- odds / (1 + odds)
return(prob)
}
logit2prob(coef(district_house_win))
## (Intercept) Abortion_Salience Illegal.Status
## 0.9988224911 0.3427834846 0.0152273052
## Hostile.Status Dem_Woman_Rep_Man Dem_Man_Rep_Woman
## 0.8895053599 0.7787417653 0.9990654200
## Dem_Woman_Rep_Woman Share_Bachelors Adherence_per_1000_Evan
## 0.4853095669 0.4746768857 0.5088924055
## Rep_Election_Denier Dem_Incumbent Rep_Incumbent
## 0.9366115425 0.9683265524 0.0008843755
## Dem_Margin_2020 urbanindex South
## 0.6509987157 0.2918875905 0.0068004901
## West Midwest Fundraising_Prop
## 0.1293742462 0.1900290573 0.9999820762
a <- district_house_win
c <- competitive_districts_house_win
stargazer(a, c,
title="Table 4. District Democrat Win Model Results",
type = "html",
out="figures/Table_4.doc",
align=TRUE)
##
## <table style="text-align:center"><caption><strong>Table 4. District Democrat Win Model Results</strong></caption>
## <tr><td colspan="3" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"></td><td colspan="2"><em>Dependent variable:</em></td></tr>
## <tr><td></td><td colspan="2" style="border-bottom: 1px solid black"></td></tr>
## <tr><td style="text-align:left"></td><td colspan="2">District_DEM_Win</td></tr>
## <tr><td style="text-align:left"></td><td>(1)</td><td>(2)</td></tr>
## <tr><td colspan="3" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Abortion_Salience</td><td>-0.651</td><td>-3.057<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.428)</td><td>(1.694)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Illegal.Status</td><td>-4.169</td><td>-2.537</td></tr>
## <tr><td style="text-align:left"></td><td>(27.821)</td><td>(3,215.940)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Hostile.Status</td><td>2.086</td><td>6.615<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(1.743)</td><td>(3.646)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Woman_Rep_Man</td><td>1.258</td><td>6.792</td></tr>
## <tr><td style="text-align:left"></td><td>(1.638)</td><td>(4.476)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Man_Rep_Woman</td><td>6.974<sup>*</sup></td><td>9.402</td></tr>
## <tr><td style="text-align:left"></td><td>(3.773)</td><td>(8.446)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Woman_Rep_Woman</td><td>-0.059</td><td>-4.504</td></tr>
## <tr><td style="text-align:left"></td><td>(1.582)</td><td>(3.928)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Share_Bachelors</td><td>-0.101</td><td>-0.549<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.068)</td><td>(0.289)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Adherence_per_1000_Evan</td><td>0.036<sup>*</sup></td><td>-0.024</td></tr>
## <tr><td style="text-align:left"></td><td>(0.022)</td><td>(0.023)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Rep_Election_Denier</td><td>2.693<sup>*</sup></td><td>5.538<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(1.597)</td><td>(3.060)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Incumbent</td><td>3.420<sup>***</sup></td><td>7.081</td></tr>
## <tr><td style="text-align:left"></td><td>(1.298)</td><td>(4.472)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Rep_Incumbent</td><td>-7.030<sup>**</sup></td><td>-11.897</td></tr>
## <tr><td style="text-align:left"></td><td>(2.968)</td><td>(8.839)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Dem_Margin_2020</td><td>0.623<sup>***</sup></td><td>1.553<sup>**</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(0.209)</td><td>(0.765)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">urbanindex</td><td>-0.886</td><td>-0.461</td></tr>
## <tr><td style="text-align:left"></td><td>(0.775)</td><td>(1.028)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">South</td><td>-4.984</td><td></td></tr>
## <tr><td style="text-align:left"></td><td>(3.063)</td><td></td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">West</td><td>-1.907</td><td></td></tr>
## <tr><td style="text-align:left"></td><td>(1.909)</td><td></td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Midwest</td><td>-1.450</td><td></td></tr>
## <tr><td style="text-align:left"></td><td>(2.196)</td><td></td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Fundraising_Prop</td><td>10.929<sup>**</sup></td><td>34.662<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(5.448)</td><td>(20.067)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td style="text-align:left">Constant</td><td>6.743</td><td>30.919<sup>*</sup></td></tr>
## <tr><td style="text-align:left"></td><td>(9.048)</td><td>(17.740)</td></tr>
## <tr><td style="text-align:left"></td><td></td><td></td></tr>
## <tr><td colspan="3" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Observations</td><td>393</td><td>78</td></tr>
## <tr><td style="text-align:left">Log Likelihood</td><td>-18.272</td><td>-8.725</td></tr>
## <tr><td style="text-align:left">Akaike Inf. Crit.</td><td>72.545</td><td>47.449</td></tr>
## <tr><td colspan="3" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left"><em>Note:</em></td><td colspan="2" style="text-align:right"><sup>*</sup>p<0.1; <sup>**</sup>p<0.05; <sup>***</sup>p<0.01</td></tr>
## </table>
house_r_squared <- with(summary(district_house_win), 1 - deviance/null.deviance)
house_adj_r_squared <- adjR2(district_house_win)
## [1] 0.9299
house_comp_r_squared <- with(summary(competitive_districts_house_win), 1 - deviance/null.deviance)
house_compe_adj_r_squared <- adjR2(competitive_districts_house_win)
## [1] 0.7928
r_squared <- round(c(house_r_squared, house_comp_r_squared), 3)
r_squared
## [1] 0.933 0.830
adj_r_squared <- round(c(house_adj_r_squared, house_compe_adj_r_squared), 3)
adj_r_squared
## [1] 0.930 0.793