front-line house democrats: a quick guide

[This article was first published on Jason Timm, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

So, with an impeachment vote nigh and the 2020 general elections slowly approaching, lots of talk about the 31 House Democrats that represent congressional districts won by the sitting president in 2016. Here, we present a quick/simple/R-based investigation into the composition of this group of Democrats from several different perspectives. We also consider the 43 congressional districts that flipped Democratic in the 2018 midterms.

Pundits constantly cite these districts and count them in different ways; and I am constantly trying to recreate these counts. As open source federal election data can be a bit of a mess, this is an attempt to organize & collate some data sources.

House & presidential election returns

The R data package uspoliticalextras includes federal election returns from a couple of sources, namely the Daily Kos and the MIT Election Data and Science Lab. I use the package as a bit of a cache for US political data; it is available via Git Hub. The focus here will be on the last Presidential election (2016) & the last two House races (2016 & 2018).

library(tidyverse)
#devtools::install_github("jaytimm/uspoliticalextras")  
pres <- uspoliticalextras::uspol_dkos_returns_pres_cd 
house <- uspoliticalextras::uspol_medsl_returns_house_cd %>%
  filter(year > 2015) %>%
  mutate(party = ifelse(party == 'Independent', 'Republican Party', party)) # Amash

Trump margins in 2016

Number of congressional districts carried by DJT & HRC.

pres %>%
  filter(year == 2016) %>%
  group_by(candidate) %>%
  count() %>%
  knitr::kable()
candidate n
Clinton 205
Trump 230

Trump margins by congressional district in 2016.

library(sf)
to_map <- uspoliticalextras::uspol_dkos_equalarea_sf$hex_cds %>%
  select(GEOID) %>%
  left_join(pres %>% 
              filter(year == 2016) %>% 
              mutate(trump_margin = republican - democrat),
            by = 'GEOID') 
to_map %>%
  ggplot() + 
  geom_sf(aes(fill = trump_margin),
          color = 'white') +
  geom_sf(data=uspoliticalextras::uspol_dkos_equalarea_sf$hex_states, 
          fill = NA, 
          show.legend = F, 
          color="#5a5c5b", 
          lwd=.5) +
  ggsflabel::geom_sf_text(data = uspoliticalextras::uspol_dkos_equalarea_sf$hex_cds,
                          aes(label = district_code), 
                          size = 2,
                          color='black') +
  scale_fill_distiller(palette = "RdBu", direction=-1) +
  theme_minimal()+
  theme(axis.text.x=element_blank(),
        axis.text.y=element_blank(),
        axis.title.x=element_blank(),
        axis.title.y=element_blank(),
        legend.position = 'none') +
  labs(title = "2016 Trump Margins by Congressional District",
       caption = 'Source: Daily Kos')

Flipped House Districts from 2016 to 2018

Congressional districts that elected a Republican representative in 2016 and a Democratic representative in 2018.

house_flips <- house %>%
  select(GEOID, congress,party) %>%
  spread(congress, party) %>%
  left_join(house %>% 
              filter(year == 2018) %>% 
              mutate(house_rep_margin = round(republican - democrat, 1)) %>%
              select(GEOID, state, district_code, candidate, house_rep_margin) %>% 
              rename(house_rep = candidate))

Some corrections/amendments for Pennsylvania districts per 2019 redistricting.

pa16_rs <- c('4201', '4205', '4206',
           '4207', '4209', '4210',
           '4211', '4212', '4213','4215',
           '4216', '4217')
pa16_ds <- c('4202', '4203', '4204',
           '4208',  '4214',
           '4218')
pa18_rs <- c('4203', '4204', '4205', '4218')
pa18_ds <- c('4213', '4214')
house_flips1 <-  house_flips %>%
  mutate(`115` = ifelse(GEOID %in% pa16_rs, 'Republican Party', `115`),
         `115` = ifelse(GEOID %in% pa16_ds, 'Democratic Party', `115`)) %>%
  mutate(house_flip = paste0(`115`, ' | ', `116`)) %>%
  left_join(to_map %>% 
              sf::st_drop_geometry() %>% 
              select(GEOID, candidate, trump_margin)) %>%
  rename(Pres16 = candidate) %>%
  mutate(`116` = ifelse(GEOID %in% pa18_rs, 'Republican Party', `116`),
         `116` = ifelse(GEOID %in% pa18_ds, 'Democratic Party', `116`)) %>%  
  mutate(Pres16_House18 = paste0(Pres16, ' | ', `116`))

Democrats netted a total of 40 seats in the midterm elections in 2018. The numbers & districts presented below align with those presented on Bollotpedia.

house_flips1 %>%
  group_by(house_flip) %>%
  count() %>%
  knitr::kable()
house_flip n
Democratic Party | Democratic Party 192
Democratic Party | Republican Party 3
Republican Party | Democratic Party 43
Republican Party | Republican Party 197

House Representatives from flipped districts:

house_flips1 %>%
  filter(house_flip %in% 
           c('Democratic Party | Republican Party', 
             'Republican Party | Democratic Party')) %>%
  mutate(house_flip = ifelse(grepl('^D', house_flip), 'D -> R', 'R -> D')) %>%
  select(house_flip, state, district_code, house_rep) %>%
  DT::datatable(rownames = FALSE)

The 31 House Democrats in Trump-supportive districts

The table below summarizes how districts voted in the 2016 presidential election and House elections in 2018. Again, 31 House Democrats represent congressional districts that Trump won in 2016’s presidential election. In contrast, only three Republicans represent districts carried by HRC. Note: Numbers & districts align with those presented in this article from The Hill.

house_flips1 %>%
  group_by(Pres16_House18) %>%
  count() %>%
  #mutate(n = formattable::color_tile('white', 'steelblue')(n)) %>%
  knitr::kable()
Pres16_House18 n
Clinton | Democratic Party 202
Clinton | Republican Party 3
Trump | Democratic Party 31
Trump | Republican Party 199

The 31 Democratic lawmakers representing Trump won districts include:

house_flips1 %>%
  filter(Pres16_House18 == 'Trump | Democratic Party') %>%
  select(state, district_code, house_rep) %>%
  DT::datatable(rownames = FALSE)

A quick geographical perspective

to_map2 <- uspoliticalextras::uspol_dkos_equalarea_sf$hex_cds %>%
  select(GEOID) %>%
  left_join(house_flips1, by = 'GEOID') 

to_map2 %>%
  ggplot() + 
  geom_sf(aes(fill = Pres16_House18),
          alpha = .75,
          color = 'white') +
  geom_sf(data=uspoliticalextras::uspol_dkos_equalarea_sf$hex_states, 
          fill = NA, 
          show.legend = F, 
          color="black", 
          lwd=.5) +
  ggsflabel::geom_sf_text(data = uspoliticalextras::uspol_dkos_equalarea_sf$hex_cds,
                          aes(label = district_code), 
                          size = 2,
                          color='black') +
  ggthemes::scale_fill_stata() +
  theme_minimal()+
  theme(axis.text.x=element_blank(),
        axis.text.y=element_blank(),
        axis.title.x=element_blank(),
        axis.title.y=element_blank(),
        legend.position = 'bottom') +
  labs(title = "2016 Presidential Support & 2018 House Representative",
       subtitle = 'By Congressional District')

The 13 House Democrats in solid Trump districts

Of the 31, 13 Democrats represent districts Trump carried by more than 6 points.

house_flips1 %>%
  filter(Pres16_House18 == 'Trump | Democratic Party' & trump_margin > 6) %>%
  select(state, district_code, house_rep, trump_margin, house_rep_margin) %>%
  arrange(desc(trump_margin)) %>%
  knitr::kable()
state district_code house_rep trump_margin house_rep_margin
Minnesota 7 PETERSON, Collin Clark 30.8 -4.3
New York 22 BRINDISI, Anthony 15.5 -1.8
Oklahoma 5 HORN, Kendra 13.4 -1.4
South Carolina 1 CUNNINGHAM, Joe 13.1 -1.4
Maine 2 GOLDEN, Jared 10.3 -1.2
New Mexico 2 TORRES SMALL, Xochitl 10.2 -1.9
Pennsylvania 17 LAMB, Conor 10.1 -12.5
New York 11 ROSE, Max 9.8 -6.5
New York 19 DELGADO, Antonio 6.8 -5.2
Michigan 8 SLOTKIN, Elissa 6.7 -3.8
Utah 4 McADAMS, Ben 6.7 -0.3
Virginia 7 SPANBERGER, Abigail 6.5 -1.9
New Jersey 3 KIM, Andy 6.2 -1.3

Voting patterns in presidential elections

Counts of how districts voted in the last three presidential elections are presented below.

house_flips2 <- house_flips1 %>%
  left_join (pres %>% 
               group_by(GEOID) %>%
               summarize(pres_lineage = paste0(candidate, collapse = ' | ')) %>%
               ungroup())
house_flips2 %>%
  group_by(pres_lineage) %>%
  count() %>%
  knitr::kable()
pres_lineage n
McCain | Obama | Trump 1
McCain | Romney | Clinton 8
McCain | Romney | Trump 184
Obama | Obama | Clinton 190
Obama | Obama | Trump 20
Obama | Romney | Clinton 7
Obama | Romney | Trump 25

Voting patterns for the 31 Trump-House Dem districts

12 out of the 31 Dem-Trump districts have voted for Republican presidential candidates in the last three elections, ie, McCain-Romney-Trump districts.

house_flips2 %>%
  filter(Pres16_House18 == 'Trump | Democratic Party') %>%
  group_by(pres_lineage) %>%
  count() %>%
  knitr::kable()
pres_lineage n
McCain | Obama | Trump 1
McCain | Romney | Trump 12
Obama | Obama | Trump 14
Obama | Romney | Trump 4

Representatives for these twelve districts are presented below.

house_flips2 %>%
  filter(Pres16_House18 == 'Trump | Democratic Party' & 
           pres_lineage == 'McCain | Romney | Trump') %>%
  select(state, district_code, house_rep) %>%
  knitr::kable()
state district_code house_rep
Arizona 1 O’HALLERAN, Thomas C.
Georgia 6 McBATH, Lucy
Minnesota 7 PETERSON, Collin Clark
New Jersey 5 GOTTHEIMER, Josh S.
New Jersey 11 SHERRILL, Mikie
New Mexico 2 TORRES SMALL, Xochitl
New York 22 BRINDISI, Anthony
Oklahoma 5 HORN, Kendra
South Carolina 1 CUNNINGHAM, Joe
Utah 4 McADAMS, Ben
Virginia 2 LURIA, Elaine
Virginia 7 SPANBERGER, Abigail

The 5 House Democrats that should probably vote against impeachment

The table below lists the five House Reps representing districts that have supported Republican presidential candidates in the last three elections, with 2016 Trump margins greater than ten points.

house_flips2 %>%
  filter(Pres16_House18 == 'Trump | Democratic Party' & 
           trump_margin > 10 &
           pres_lineage == 'McCain | Romney | Trump') %>%
  select(state, district_code, house_rep, pres_lineage, trump_margin) %>%
  arrange(desc(trump_margin)) %>%
  knitr::kable()
state district_code house_rep pres_lineage trump_margin
Minnesota 7 PETERSON, Collin Clark McCain | Romney | Trump 30.8
New York 22 BRINDISI, Anthony McCain | Romney | Trump 15.5
Oklahoma 5 HORN, Kendra McCain | Romney | Trump 13.4
South Carolina 1 CUNNINGHAM, Joe McCain | Romney | Trump 13.1
New Mexico 2 TORRES SMALL, Xochitl McCain | Romney | Trump 10.2

Front-line Freshmen House Democrats

Via the Rvoteview package, we identify 88 freshman House Representatives, 56 of which are Democrats.

house_vv_freshies <- Rvoteview:: member_search(chamber= 'House', congress = 116) %>%
  filter(congresses == 'c(116, 116)' & party_name != 'Independent') %>%
  select(bioname, party_name) %>%
  rename(house_rep = bioname) 

house_vv_freshies %>%
  group_by(party_name) %>%
  count() %>%
  knitr::kable()
party_name n
Democratic Party 56
Republican Party 32

Of the 31, then, 22 are freshman. So, a pretty vulnerable group.

house_flips3 <- house_flips2 %>%
  left_join(house_vv_freshies %>% 
              mutate(is_fresh = 'Freshman') %>% 
              select(house_rep, is_fresh)) %>%
  mutate(is_fresh = ifelse(is.na(is_fresh), 'Not', is_fresh))

house_flips3 %>%
  group_by(is_fresh, Pres16_House18) %>%
  count() %>%
  #filter(is_fresh == 'Y') %>%
  spread(is_fresh, n) %>%
  janitor::adorn_totals(where = c('row', 'col')) %>%
  knitr::kable()
Pres16_House18 Freshman Not Total
Clinton | Democratic Party 35 167 202
Clinton | Republican Party NA 3 3
Trump | Democratic Party 22 9 31
Trump | Republican Party 29 170 199
Total 86 349 435

Data set

The data set compiled in this post/guide is available here.

To leave a comment for the author, please follow the link and comment on their blog: Jason Timm.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)