The purpose of this post is to explore the voting records of Senators Barbara Boxer and Diane Feinstein.
The Sunlight Foundation is a nonpartisan, nonprofit organization that uses the tools of civic tech, open data, policy analysis, and journalism to make government and politics more accountable and transparent. They have several APIs available, and we’ll use a few to learn about our elected officials. You’ll need to obtain an API key first, and you can do so here.
Let’s say we’re interested in the voting records of California’s senators, Diane Feinstein and Barbara Boxer. Unfortunately, the Congress API only has data going back to 2009, but that’s still a seven year period to observe.
Before we can access their voting records, we need to obtain their legislative ids. These are identifiers that appear throughout the API.
library(jsonlite)
library(httr)
library(dplyr)
apikey <- "xxxkeyxxx"
res <- GET("https://congress.api.sunlightfoundation.com",
path = "legislators/locate",
query = list(zip = "94087",
apikey = apikey)) %>%
content(type = "text") %>%
fromJSON(flatten = TRUE)
leg_ids <- res$results %>%
filter(chamber == "senate") %>%
.$bioguide_id
leg_ids
## [1] "B000711" "F000062"
Boxer’s id is B000711 and Feinstein’s is F000062.
Now that we have the ids, let’s make another API to obtain their respective voting records. In brief, I’m (1) specifying the precise fields I want returned; (2) creating a vector of years to loop through; (3) for every year between 2009-2016, looping through the API and extracting the senators voting record for that year; and (4) binding all the years together into a table called votes.
fields <- "bill_id,question,voters.vote,voters,year"
years <- as.character(2009:2016)
ca_sen_list <- list()
for (i in 1:length(years)) {
sen <- GET("https://congress.api.sunlightfoundation.com",
path = "votes",
query = list(chamber = "senate",
fields = fields,
year = years[i],
apikey = apikey)) %>%
content(type = "text") %>%
fromJSON(flatten = TRUE)
sen_df <- sen[[1]]
sen_df <- sen_df %>%
select(question, bill_id, year, voters.B000711.vote, voters.F000062.vote)
ca_sen_list[[i]] <- sen_df
}
votes <- bind_rows(ca_sen_list)
Let’s glance at our votes table:
| question | bill_id | year | voters.B000711.vote | voters.F000062.vote |
|---|---|---|---|---|
| On the Cloture Motion S. 22 | s22-111 | 2009 | Yea | Yea |
| On the Cloture Motion S. 22 | s22-111 | 2009 | Yea | Yea |
| On Passage of the Bill S. 22 | s22-111 | 2009 | Yea | Yea |
| On the Cloture Motion S. 181 | s181-111 | 2009 | Yea | Yea |
| On the Joint Resolution S.J.Res. 5 | sjres5-111 | 2009 | Nay | Nay |
| On the Nomination PN64-1 | NA | 2009 | Yea | Yea |
Now let’s answer some questions.
1. How many times did Boxer and Fienstein cast opposing votes?
votes %>%
filter(voters.B000711.vote != voters.F000062.vote &
voters.B000711.vote != "Not Voting" &
voters.F000062.vote != "Not Voting") %>%
kable()
| question | bill_id | year | voters.B000711.vote | voters.F000062.vote |
|---|---|---|---|---|
| On the Amendment S.Amdt. 3301 to S.Amdt. 3299 to H.J.Res. 45 (No short title on file) | hjres45-111 | 2010 | Nay | Yea |
| On the Nomination PN959 | NA | 2010 | Nay | Yea |
| On the Amendment S.Amdt. 1500 to S.Amdt. 1470 to S. 2038 (Stop Trading on Congressional Knowledge Act of 2012) | s2038-112 | 2012 | Yea | Nay |
| On the Amendment S.Amdt. 1493 to S.Amdt. 1470 to S. 2038 (Stop Trading on Congressional Knowledge Act of 2012) | s2038-112 | 2012 | Nay | Yea |
| On the Amendment S.Amdt. 3871 to S.Amdt. 3801 to H.R. 2028 (Energy and Water Development and Related Agencies Appropriations Act, 2016) | hr2028-114 | 2016 | Yea | Nay |
| On the Amendment S.Amdt. 3812 to S.Amdt. 3801 to H.R. 2028 (Energy and Water Development and Related Agencies Appropriations Act, 2016) | hr2028-114 | 2016 | Yea | Nay |
It’s only happened six times in the past seven years:
vote_plot <- votes %>%
mutate(vote_cast = ifelse(voters.B000711.vote != voters.F000062.vote & voters.B000711.vote != "Not Voting" & voters.F000062.vote != "Not Voting", "Opposing Vote", "Same Vote"))
ggplot(vote_plot, aes(vote_cast)) +
geom_bar(stat = "count", fill = "lightgreen", color = "black", width = 0.5) +
annotate("text", x = 2, y = 158, label = "153 votes", color = "black") +
annotate("text", x = 1, y = 12, label = "6 votes", color = "black") +
labs(x = "", y = "") +
ggtitle("Senator Boxer and Senator Fienstein's \nVoting Records, 2009-2016") +
theme_minimal()
2. How many times have either Senator Boxer or Senator Fienstein voted for a bill sponsored by a Republican colleague?
This is going to take a few steps. First, let’s get the ids for every Republican senator:
req <- GET("https://congress.api.sunlightfoundation.com",
path = "legislators",
query = list(chamber = "senate",
party = "R",
apikey = apikey)) %>%
content(type = "text") %>%
fromJSON(flatten = TRUE)
rep_ids <- req$results %>%
.$bioguide_id
rep_ids
## [1] "S001197" "R000605" "T000476" "E000295" "P000612" "S001198" "C001098"
## [8] "F000463" "D000618" "C001095" "H001041" "V000127" "T000461" "T000250"
## [15] "S000320" "S001184" "R000595" "P000449" "P000603" "M001153"
Second, let’s get every bill_id that’s been sponsored by a Republican senator:
republican_bill_ids <- c()
for (i in 1:length(rep_ids)) {
req <- GET("https://congress.api.sunlightfoundation.com",
path = "bills",
query = list(chamber = "senate",
sponsor_id = rep_ids[i],
apikey = apikey)) %>%
content(type = "text") %>%
fromJSON(flatten = TRUE)
republican_bill_ids <- append(republican_bill_ids, req$results$bill_id)
}
head(republican_bill_ids)
## [1] "s2849-114" "s2803-114" "sconres33-114" "s2128-114"
## [5] "s2066-114" "s748-114"
Finally, let’s see how many times and to which bills Boxer or Feinstein voted “Yea”. Good thing we thought ahead and already stashed the bill_id in one of our earlier calls:
votes %>%
filter(bill_id %in% republican_bill_ids,
voters.B000711.vote == "Yea" | voters.F000062.vote == "Yea") %>%
kable()
| question | bill_id | year | voters.B000711.vote | voters.F000062.vote |
|---|---|---|---|---|
| On Passage of the Bill S. 2012 | s2012-114 | 2016 | Yea | Yea |
| On the Amendment S.Amdt. 3312 to S.Amdt. 2953 to S. 2012 (Energy Policy Modernization Act of 2015) | s2012-114 | 2016 | Yea | Yea |
The two senators voted for a Republican-sponsored bill only four times, and it was three amendments to the same bill. Before we wrap up, let’s take a look at the Energy Policy Modernization Act of 2015.
rep_bill <- GET("https://congress.api.sunlightfoundation.com",
path = "bills/search",
query = list(bill_id = "s2012-114",
apikey = apikey)) %>%
content(type = "text") %>%
fromJSON(flatten = TRUE)
rep_bill[[1]] %>%
select(official_title, history.senate_passage_result, history.enacted) %>%
kable()
| official_title | history.senate_passage_result | history.enacted |
|---|---|---|
| An original bill to provide for the modernization of the energy policy of the United States, and for other purposes. | pass | FALSE |
Looks like the bill passed the senate, but it has yet to be enacted.