---
title: "Senate support for presidential executive branch nominees since 1989"
author: "Jeff Lewis"
description: Putting Democratic senators' support for Trump appointees in recent historical context.
original_date: "2019-05-23"
date: "`r format(Sys.time(), '%B %d, %Y')`"
update_delta: 31
tags:
  - blog
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(pacman)
p_load(ggplot2, wnominate, kableExtra, directlabels, tidyverse)
```

```{r download data, message=F, warning=F, include=FALSE}
rc <- read_csv("https://voteview.com/static/data/out/rollcalls/Sall_rollcalls.csv",
               show_col_types = FALSE) |>
        filter(str_detect(bill_number,"^PN"))

votes <- read_csv("https://voteview.com/static/data/out/votes/Sall_votes.csv",
                  show_col_types = FALSE) |>
            filter(congress>100)

mems <- read_csv("https://voteview.com/static/data/out/members/Sall_members.csv",
                 show_col_types = FALSE) |>
            filter(congress>100) |>
            mutate(party_code = ifelse(icpsr==29147, 100, party_code))  # Make BS a Dem
```

```{r make dataset, include=FALSE}
dat <- rc |>
        right_join(votes, by=c("congress", "rollnumber","chamber")) |>
        left_join(mems, by=c("congress","icpsr","chamber"))
```


## Overview

There has been a good deal of attention given to President Trump's filling of high-level positions within the executive branch.  During his first term, many high-level positions were [left unfilled](https://www.washingtonpost.com/graphics/politics/trump-administration-appointee-tracker/database/?noredirect=on&utm_term=.63487772ed79) for lengthy periods.  Many of his nominees have been drawn from outside the pool of what have historically been considered [qualified](https://www.nbcnews.com/politics/white-house/heather-nauert-joins-long-list-questionably-qualified-trump-nominees-n945406) candidates. And, there has been strong and consistent [opposition](https://thehill.com/homenews/senate/452822-trump-nominees-meet-fiercest-opposition-from-warren-sanders-gillibrand) among Democratic senators to President Trump's nominees.  This opposition as increased in Trump's second term. Here we place Democratic senators support for President Trump's executive branch nominees in recent historical context by comparing support for his nominees to support for other president's nominees since 1989.

We find that the average level of support among opposition (Democratic) senators for President Trump's nominees was lower that for previous president's nominees in his first term and has been astoundingly low his second term. Similarly, the fraction of President Trump's nominees who have received a majority of Democratic senators votes was lower than is recent predecessors  and has been remarkably low in his second term, though Republican senators' support for President Biden's nominees was also very low.

Finally, looking at the support for presidential nominees among invidual senators, we find that Senators Kirsten Gillibrand, Bernie Sanders[^2], Elizabeth Warren, Cory Booker, Edward Markey, and Jeff Merkley .   

## Analysis

All of the computer code used to generate this analysis can be accessed [here](trump_nominee_confirmations.Rmd).

The plot below shows the overall share of affirmative votes in support of executive branch nominees by congress among senators of the president's party and among opposition party senators since 1989.   As expected, support among presidents' co-partisans is uniformly high over the period. However, support from opposition-party senators has fallen over time reaching its lowest level during the Trump administration.


### Overall support of presidential nominations

```{r make overall support by congress, include=FALSE}
overall_party_support <- dat |>
  filter(party_code %in% c(100,200),
         vote_question == "On the Nomination",
         !str_detect(str_to_lower(vote_desc), "judge|justice")) |>
  summarize( pct_support = sum(cast_code %in% 1:3)/sum(cast_code %in% 1:6), .by = c(congress, party_code) ) |>
  pivot_wider(names_from = party_code, values_from = pct_support) |>
  mutate(pres = c("G. H. W. Bush", "G. H. W. Bush",
                  "Clinton", "Clinton", "Clinton", "Clinton",
                  "G. W. Bush", "G. W. Bush","G. W. Bush", "G. W. Bush",
                  "Obama", "Obama", "Obama", "Obama",
                  "Trump", "Trump", "Biden", "Biden", "Trump"),
         pres_party = c("R","R",
                        "D", "D", "D", "D",
                        "R", "R", "R", "R",
                        "D", "D", "D", "D",
                        "R", "R", "D", "D","R")) 
```

```{r overall support, warning=FALSE, echo=FALSE}
library(ggplot2)
library(directlabels)

add_pres_boxes <- function(gg) {
   gg + 
    geom_rect(aes(xmin=100.66, xmax=102.33, ymin=0, ymax=105), 
                  fill="#FFF0F0", alpha=0.1, inherit.aes = FALSE) +
    geom_rect(aes(xmin=102.66, xmax=106.33, ymin=0, ymax=105), 
                  fill="#F2F2FF", alpha=0.1, inherit.aes = FALSE) +
    geom_rect(aes(xmin=106.66, xmax=110.33, ymin=0, ymax=105), 
                  fill="#FFF2F2", alpha=0.1, inherit.aes = FALSE) +
    geom_rect(aes(xmin=110.66, xmax=114.33, ymin=0, ymax=105), 
                  fill="#F2F2FF", alpha=0.1, inherit.aes = FALSE) +
    geom_rect(aes(xmin=114.66, xmax=116.33, ymin=0, ymax=105), 
                  fill="#FFF2F2", alpha=0.05, inherit.aes = FALSE) +
    geom_rect(aes(xmin=116.66, xmax=118.33, ymin=0, ymax=105), 
                  fill="#F2F2FF", alpha=0.05, inherit.aes = FALSE) +
    geom_rect(aes(xmin=118.66, xmax=120.33, ymin=0, ymax=105), 
                  fill="#FFF2F2", alpha=0.05, inherit.aes = FALSE) +

    geom_text(aes(x=101.5, y=110, label="Bush"), 
              col="darkgrey", size=3, inherit.aes=FALSE) +
    geom_text(data=tibble(), aes(x=104.5, y=110, label="Clinton"), 
              col="darkgrey", size=3, inherit.aes=FALSE) +
    geom_text(data=tibble(), aes(x=108.5, y=110, label="Bush"), 
              col="darkgrey", size=3, inherit.aes=FALSE) +
    geom_text(data=tibble(), aes(x=112.5, y=110, label="Obama"), 
              col="darkgrey", size=3, inherit.aes=FALSE) +
    geom_text(data=tibble(), aes(x=115.5, y=110, label="Trump"), 
              col="darkgrey", size=3, inherit.aes=FALSE) +
    geom_text(data=tibble(), aes(x=117.5, y=110, label="Biden"), 
              col="darkgrey", size=3, inherit.aes=FALSE) +
    geom_text(data=tibble(), aes(x=119.5, y=110, label="Trump"), 
              col="darkgrey", size=3, inherit.aes=FALSE)
}

overall_party_support_long <- overall_party_support %>%
                        pivot_longer(c(`100`, `200`),
                                     names_to = "party", 
                                     values_to = "support") %>%
                        mutate( party = ifelse(party==100, "D", "R"),
                                of_pres_party = ifelse(party==pres_party,
                                                       "  President's party",
                                                       "  Opposition party"))
                  
ggplot(overall_party_support_long, aes(x=congress, y=100*support,
                               group=of_pres_party, col=party)) |>
  add_pres_boxes() +
  geom_point(show.legend = FALSE) +
  geom_line(size=0.15, color="grey") +
  ylab("Overall percent vote for nominees") + xlab("Congress") +
  scale_x_continuous(breaks=seq(101, 119, 2), limits=c(100.5,121.8),
                     minor_breaks = NULL) +
  scale_y_continuous(breaks=seq(0,100,10), limits=c(0,112) ) +
  scale_color_manual(values=c("R"="red","D"="blue")) +
  geom_dl(aes(label = of_pres_party), 
          method = list(dl.combine("last.points"), 
                        cex = 0.8), color="darkgrey") +
  theme_minimal()
```


### Fraction of president's nominees receiving majority support from each party's caucus

The figure below shows the fraction of each president's nominees in each congress that were supported by a majority of the president's co-partisans and opposition-party senators.  Note that only President Clinton had any nominees who were not supported by a majority of his co-partisan senators.  The fraction of nominees who have received majority support from the opposition-party's senators has varied substantially since 1989 reaching a low of 40 percent in the 115th Congress before falling all the way to 10 percent in the 119th Congress. 

```{r Calculate fraction of nominees supported, include=FALSE}
party_supported <- dat |>
  filter(party_code %in% c(100,200),
         vote_question == "On the Nomination",
         !str_detect(str_to_lower(vote_desc), "judge|justice")) |>
  summarize( supported = sum(cast_code %in% 1:3)/sum(cast_code %in% 1:6) > 0.5, .by = c(congress, party_code, rollnumber)) |>
  summarize(supported = mean(supported), .by = c(congress, party_code)) |>
  pivot_wider(names_from = party_code, values_from = supported) |>
  mutate(pres = c("G. H. W. Bush", "G. H. W. Bush",
                  "Clinton", "Clinton", "Clinton", "Clinton",
                  "G. W. Bush", "G. W. Bush","G. W. Bush", "G. W. Bush",
                  "Obama", "Obama", "Obama", "Obama",
                  "Trump", "Trump", "Biden", "Biden", "Trump"),
         pres_party = c("R","R",
                        "D", "D", "D", "D",
                        "R", "R", "R", "R",
                        "D", "D", "D", "D",
                        "R", "R", "D", "D", "R")) 

```


```{r plot percent of nominees supported, warning=FALSE, echo=FALSE}
party_supported_long <- party_supported |>
                        pivot_longer(cols = c(`100`, `200`), names_to = "party", values_to = "supported") |>
                        mutate( party = ifelse(party=="100", "D", "R"),
                                of_pres_party = ifelse(party==pres_party,
                                                       "  President's party",
                                                       "  Opposition party"))

ggplot(party_supported_long, aes(x=congress, y=100*supported,
                               group=of_pres_party, col=party)) |>
  add_pres_boxes() +
  geom_point(show.legend = FALSE) +
  geom_line(size=0.15, color="grey")  +
  ylab("Percent of nomminees supported") + xlab("Congress") +
  scale_x_continuous(breaks=seq(101, 120, 2), limits=c(100.5,122.35), 
                     minor_breaks = NULL) +
  scale_y_continuous(breaks=seq(0, 100, 10), limits=c(0,112)) +
  scale_color_manual(values=c("R"="red","D"="blue")) +
  geom_dl(aes(label = of_pres_party), 
          method = list(dl.combine("last.points"), 
                        cex = 0.8), color="darkgrey") +
  theme_minimal()
```

### Rates of nominee support by senator and president 

The two tables below show the senators who voted to confirm the nominees of particular presidents at the lowest levels since 1989.  The first table shows the lowest rates among opposition senators.  The second table shows the lowest rates among the presidents co-partisans.

#### Opposition party senators

The table below shows the lowest rates of support for nominees of each president since 1989.  The table shows every senator who supported less the half of any president's nominees.[^1]  Notice how many of these involve Trump nominees and the very low rates of support for Trump nominees among a number of notable current Democratic senators.

```{r rates of nominee opposition by senator, echo=FALSE, warning=FALSE}
pres <- tibble(congress=101:119,
               pres = factor(c("G. H. W. Bush", "G. H. W. Bush", 
                  "Clinton", "Clinton", "Clinton", "Clinton",
                  "G. W. Bush", "G. W. Bush","G. W. Bush", "G. W. Bush",
                  "Obama", "Obama", "Obama", "Obama",
                  "Trump (I)", "Trump (I)", "Biden", "Biden", "Trump (II)"), 
                  levels=c("G. H. W. Bush", "Clinton", "G. W. Bush",
                           "Obama", "Trump (I)", "Biden", "Trump (II)")),
               pres_party = c("R","R",
                        "D", "D", "D", "D",
                        "R", "R", "R", "R",
                        "D", "D", "D", "D",
                        "R", "R", "D", "D", "R"))
mem_support <- dat %>%
  left_join(pres, by="congress") %>%
  filter(party_code %in% c(100,200), 
         vote_question == "On the Nomination",
         !str_detect(str_to_lower(vote_desc), "judge|justice")) %>%
  filter( ifelse(party_code==100, "D", "R") != pres_party) %>%
  summarize( supported = sum(cast_code %in% 1:3)/sum(cast_code %in% 1:6),
             n = n(),
             .by = c(pres, party_code, bioname, state_abbrev, icpsr)) %>%
  mutate(member = sprintf("%s (%s-%s)", 
                          bioname, 
                          ifelse(party_code==100, "D", "R"), 
                          state_abbrev)) %>%
  filter(n>10) %>%
  select(pres, member, party_code, supported) %>%
  arrange(supported)

knitr::kable(mem_support |>
               filter(supported < 0.50) |>
               select(-party_code) |>
               mutate(supported = round(100*supported,1)) |>
               rename(President=pres,
                      Senator = member,
                      "Pct.\\nSupported" = supported) |>
               select(Senator, President, `Pct.\\nSupported`)) |>
  kableExtra::kable_styling(bootstrap_options = c("striped", "hover"),
                            font_size = 10,
                            full_width = FALSE) 
```

#### Distribution of opposition senator support

The histogram below shows the distribution of nominee support rates among opposition-party senators by president since 1989.  The red bars contain senators who supported fewer than half of a president's nominees.  The blue bars contain senators who supported more than half of a president's nominees.  Notice that every Democrat supported over 70 percent of President G. H. W. Bush's nominees and no Democrats supported fewer than half of President G. W. Bush's nominees.  In contrast a substantial number of Republican's supported fewer than half of President Obama's nominees.  However, for President Trump, most Democrats have opposed more than half of his nominees and a sizable number have supported fewer of his nominees than has been seen for any opposition-party senator since 1989.  


```{r Make distribution of support across senator-president combinations, echo=FALSE, warning=FALSE}
ggplot(mem_support, aes(x=supported*100, fill=supported<=0.5)) +
    geom_histogram(breaks=seq(0, 100, by=10), show.legend=FALSE) + 
    facet_wrap(~pres) +
    theme_minimal() +
    xlab("Percent of nominees supported")
```


#### Presidents' co-partisan senators

The table below shows the lowest rates of support for the nominees of presidents since 1989 from senators who are the president's co-partisans.  The table shows every co-partisan senator who supported less than 95 percent of a given president's nominees during this period. 


```{r echo=FALSE}
pp_mem_support <- dat |>
  left_join(pres, by="congress") |>
  filter(party_code %in% c(100,200),
         vote_question == "On the Nomination",
         !str_detect(str_to_lower(vote_desc), "judge|justice")) %>%
  filter( ifelse(party_code==100, "D", "R") == pres_party) %>%
  summarize( supported = sum(cast_code %in% 1:3)/sum(cast_code %in% 1:6),
             n = n(),
             .by = c(pres, party_code, bioname, state_abbrev, icpsr)) %>%
  mutate(member = sprintf("%s (%s-%s)", 
                          bioname, 
                          ifelse(party_code==100, "D", "R"), 
                          state_abbrev)) %>%
  filter(n>10) %>%
  select(pres, member, party_code, supported) %>%
  arrange(supported)

knitr::kable(pp_mem_support |>
               filter(supported < 0.95) |>
               select(-party_code) |>
               mutate(supported = round(100*supported,1)) |>
               rename(President=pres,
                      Senator = member,
                      "Pct.\\nSupported" = supported) |>
               select(Senator, President, `Pct.\\nSupported`)) |>
  kableExtra::kable_styling(bootstrap_options = c("striped", "hover"),
                            font_size = 10,
                            full_width = FALSE)
```
### Notes

[^1]: Among senators casting more than 10 confirmation votes for the given president's nominees. 

[^2]: Though elected as an independent, Senator Sanders is considered to be a Democrat for the purposes of this analysis.
