For this exercise I have created various visualizations that will provide more understanding about the 2018 US congressional elections, which occured on November 6, 2018. The first step will be to create a bar chart of the number of seats the two major parties won. Going into the elections the Democratic party had 195 seats, and the republicans had 240.
library(plyr)
library(ggplot2)
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following objects are masked from 'package:plyr':
##
## arrange, mutate, rename, summarise
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(ggthemes)
housevote=read.csv("C:/Users/bcole/Documents/Testfile.csv")
test<-ggplot(housevote, aes(WinningParty, color=WinningParty))+ geom_bar(fill=c('blue', 'red'))+ggtitle("2018 Congressional Vote by Party")+theme(plot.title = element_text(hjust=0.5))+ylab("Number of Representatives")+xlab("Political Party")+theme(legend.title=element_blank())+scale_color_manual(values =c("blue","red"))
ggplotly(test)
This first chart uses the tool Plotly, which enables us to interact with the data. This chart shows us that the Democrats gained the house, and received 235 out of 435 seats, though one election in North Carolina hasn’t been certified yet due to allegations of fraud. Democrats flipped in 43 Republican seats in this election, and Republicans flipped 3 Democratic states.
This next chart will demonstrate the same data, but we will be able to analyze it on a state by state level, in order to determine which states sent more Republicans, or more Democrats, to congress.
Housevotebystate<-ggplot(housevote, aes(WinningParty, color=State, fill=State))+ geom_bar()+ggtitle("2018 Congressional Vote by Party")+theme(plot.title = element_text(hjust=0.5))+ylab("Number of Representatives")+xlab("Political Party")
ggplotly(Housevotebystate)
The above chart is an example of the benefits of using plotly to create graphs in R. By using plotly, we are able to analze the results of the 2016 midterms on a state by state basis. By double clicking a state of interest, you can isolate it, and see the number of seats won by Democrats, and the number of seats won by Republicans.
The next chart is a histogram that shows the Margin of victory that Democratic candidates had over their Republican opponents.
housevote1<-housevote %>%
group_by(State) %>%
mutate(Demvotesbystate = sum(DemVotes), Repvotesbystate= sum(GOPVotes), StateMargin=(Demvotesbystate-Repvotesbystate)/(Demvotesbystate+Repvotesbystate), Statepopulation= sum(population))
library(rgdal)
## Loading required package: sp
## rgdal: version: 1.3-6, (SVN revision 773)
## Geospatial Data Abstraction Library extensions to R successfully loaded
## Loaded GDAL runtime: GDAL 2.2.3, released 2017/11/20
## Path to GDAL shared files: C:/Users/bcole/Documents/R/win-library/3.5/rgdal/gdal
## GDAL binary built with GEOS: TRUE
## Loaded PROJ.4 runtime: Rel. 4.9.3, 15 August 2016, [PJ_VERSION: 493]
## Path to PROJ.4 shared files: C:/Users/bcole/Documents/R/win-library/3.5/rgdal/proj
## Linking to sp version: 1.3-1
library(tmap)
Test1<-readOGR(dsn="C:/congress2",layer="Export_Output")
## OGR data source with driver: ESRI Shapefile
## Source: "C:\congress2", layer: "Export_Output"
## with 435 features
## It has 11 fields
## Integer64 fields read as strings: OBJECTID
## Warning in readOGR(dsn = "C:/congress2", layer = "Export_Output"): Z-
## dimension discarded
Electionmap <- merge(Test1,housevote1, by="OBJECTID")
tm_shape(Electionmap)+
tm_fill("WinningParty", title = "Winning Party in 2018 House Election", palette="-RdBu")
## Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
tmap_mode("plot")
## tmap mode set to plotting
The above code has created a map of the winning party in each congressional district in the 2018 midterms. Of note is that Republicans won a significantly larger area of land, when compared to Democrats, even though Democrats won at least 35 more seats. This is because Democratic voters tend to be more concentrated in urban areas, and Republican voters tend to be located in more rural regions. This snippet of R code also involved the creation of Democratic Margin by state, which will be used in a subsequent map.
tm_shape(Electionmap)+
tm_fill("Flip", title = "Flipped Seats", palette=("-RdBu"))+ tmap_mode("plot")
## tmap mode set to plotting
The above map that was created is a map that shows the congressional seats that were flipped, and the party that flipped them. Of note is the large number of seats that were flipped in California, and in the north mid-atlantic states.
histogram<-ggplot(housevote,aes(DemMargin))+geom_histogram(aes(y = ..count.., color = ..count.., fill = ..count..), breaks=seq(-1.0,1.0, by=0.05))+ ggtitle("2018 Congressional Margin Histogram")+theme(plot.title = element_text(hjust=0.5))+ylab("Number of Representatives")+xlab("Democratic Margin (Democratic Proportion - Republican Proportion)")
ggplotly(histogram)
From this chart it would seem like Republicans actually won a lot of closely contested seats. They won 48 seats by between a margin of 0-10%. This is true, but also of note is the higher number of seats that were basically uncontested on the Democratic side. This allowed Democrats to wrack up a significant number of victories, while Republicans were forced to spread their money to defend a large number of seats that they would ultimately lose. The number of close races also suggests that the race for the House of Representative could be competitive in 2020 if the margin reverts away from Democrats in that year. However, if the Democratic party does even better in 2020, this would suggest that Democrats have the potential to gain even more seats.
tm_shape(Electionmap)+
tm_fill("DemMargin", title = "Democratic Margin of Victory/Loss",palette = "RdBu",breaks=c(-0.5,-.2,-.1,-.05,0,0.05,0.1,0.2,0.5))
## Variable "DemMargin" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.
tmap_mode("plot")
## tmap mode set to plotting
This map shows the margin of victory in every congressional district in the United States. Of note is the high margins that Republicans received in more rural areas, when compared to Democrats.
housevote$Swing<-as.numeric(as.character(housevote$Swing))
## Warning: NAs introduced by coercion
histogram<-ggplot(housevote,aes(Swing))+geom_histogram(aes(y = ..count.., color = ..count.., fill = ..count..), breaks=seq(-0.4,0.4, by=0.01))+ ggtitle("Swing from 2016 Election")+theme(plot.title = element_text(hjust=0.5))+ylab("Number of Representatives")+xlab("Dem Proportion Change from 2016 Presidential Election Margin")
ggplotly(histogram)
## Warning: Removed 41 rows containing non-finite values (stat_bin).
This chart shows the change in the proportion of Democratic votes when compared to the 2016 Presidential election, where Democrats won the popular vote by 2.1%. The curve peaks at around .055, meaning that the most common shift was about 5.5% towards Democrats. Overall, Democrats are leading the popular vote for the 2018 midterms by 8.6%, which is a 6.5% positive change from the results the Hillary received in November of 2016.
tm_shape(Electionmap)+
tm_fill("Swing", title = "Swingfrom2016",palette = "RdBu",breaks=c(-0.5,-.2,-.1,-.05,0,0.05,0.1,0.2,0.5))
## Warning: Number of levels of the variable "Swing" is 202, which is
## larger than max.categories (which is 30), so levels are combined. Set
## tmap_options(max.categories = 202) in the layer function to show all
## levels.
tmap_mode("plot")
## tmap mode set to plotting
The average congressional district went significantly more Democratic when compared with the 2016 Presidential election. Some districts swung significantly to Democrats when compared to the 2016 results. This includes some districts with strong incumbents, as well as some open districts in rural areas. Districts that swung towards Republicans tended to have strong incumbents.
In addition to the election data I downloaded, I also used data that measured economic and social conditions in each congressional district. The next few charts will involve an analysis of this data.
The next chart will examine how household income influenced voting decisions in the election. People in the upper middle class suburbs have noted their distaste for Trump, so it will be interesting to see what our results are.
incomeandvoting<-ggplot(housevote,aes(x=DemMargin, y=medianearnings))+geom_point(aes(text=paste("District:", CD,"State:", State)))+ ggtitle("Margin vs. Median Income")+theme(plot.title = element_text(hjust=0.5))+ylab("Median Income")+xlab("Democrat Margin (Dem Votes - All Votes)/ Total Vote")+geom_smooth()+theme_solarized()
## Warning: Ignoring unknown aesthetics: text
ggplotly(incomeandvoting)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
There is a slight positive trend in this data, but there is so much noise, so conclusions are hard to make. This is to be expected given the large number of data points.
In the next chart, I will explore how poverty influenced voting decisions in the 2018 midterm elections.
povertyandvoting<-ggplot(housevote,aes(x=povertylast12, y=DemMargin))+geom_point(aes(text=paste("District:", CD,"State:", State)))+ ggtitle("Poverty vs. Election Margin")+theme(plot.title = element_text(hjust=0.5))+ylab("Democrat Margin")+xlab("Percentage of People in Poverty in Past Year")+geom_smooth()+theme_solarized()
## Warning: Ignoring unknown aesthetics: text
ggplotly(povertyandvoting)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
In general, high levels of poverty are seen in a few of the districts that vote most for Democrats, though this is mainly the result of a few outlier districts. In general, Democrats do seem to have lower margins in Districts that have moderate levels of poverty.
library(ggExtra)
texas<-filter(housevote, State=="Texas")
povertexas<-ggplot(texas,aes(x=povertylast12, y=DemMargin))+geom_point(aes(text=paste("District:", CD,"State:", State)))+ ggtitle("Poverty vs. Election Margin in Texas")+theme(plot.title = element_text(hjust=0.5))+ylab("Democrat Margin")+xlab("Percentage of People in Poverty in Past Year")+geom_smooth()+theme_classic()
## Warning: Ignoring unknown aesthetics: text
ggplotly(povertexas)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
This chart relates the number of people in Texas who live in poverty vs. the Margin of Victory for Democratic candidates. This chart demonstrates the Democratic party’s higher margins with poor voters and the upper-middle class, as well as worse numbers with those in the lower middle class. However, one state is a small sample size.
My final visualization will be a map of Democratic margin of victory by state. This map could be seen as a small preview for 2020, as it will show the states that might be competitive in that year.
tm_shape(Electionmap)+
tm_fill("StateMargin", title = "Democratic Margin of Victory",palette = "RdBu",breaks=c(-0.5,-.2,-.1,-.05,0,0.05,0.1,0.2,0.5))
## Variable "StateMargin" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.
tmap_mode("plot")
## tmap mode set to plotting
This maps shows the margin of victory for Democrats in all 50 states. This map is very similar to the 2012 election, but with the states of Ohio and Florida flipped to Republicans, and the state of Arizona flipped to Democrats. The result in Florida was closer than this map would suggest, as votes are not counted in uncontested races in this state. There were 5 uncontested races in 2018, so the actual margin was very close this year. With that caveat mentioned, it is noted that this map would result in a 296-242 electoral college victory for Democrats.
Potential swing states (<5% margin) for 2018 include Arizona, Texas, Georgia, Florida, North Carolina, Ohio and Iowa). However, the upper midwestern states of Michigan, Wisconsin, and Pennsylvania were very close in 2016 so they should not be discounted.
Montana was close in 2018, but it generally leans Republican, so it will not be a top target in 2018, except perhaps for a Senate race. Montana was the only state to have higher turnout in 2018 when compared to 2016.