Playing around with new Congress.gov API see: https://github.com/LibraryOfCongress/api.congress.gov/ and https://api.congress.gov/
# install.packages(c("httr", "jsonlite"))
# install.packages("reticulate")
library(reticulate)
library(httr)
library(jsonlite)
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6 ✔ purrr 0.3.4
## ✔ tibble 3.1.8 ✔ dplyr 1.0.9
## ✔ tidyr 1.2.0 ✔ stringr 1.4.0
## ✔ readr 2.1.2 ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ purrr::flatten() masks jsonlite::flatten()
## ✖ dplyr::lag() masks stats::lag()
We’ve saved our api key in a JSON file in our project directory. An API Key can be requested online easily.. This key can also be used with other data.gov products.
creds <- read_json("congress_gov_api.json", simplifyVector = TRUE)
By default, the api brings back 20 items, but we can increase this up to 250. So, we add a new named list item in creds with the limit.
creds$limit <- 250
r <- GET("https://api.congress.gov/v3/bill", query = creds)
http_status(r)
## $category
## [1] "Success"
##
## $reason
## [1] "OK"
##
## $message
## [1] "Success: (200) OK"
bills <- content(r, "parsed")$bills
for (i in 1:20){
print(bills[[i]]$title)
}
## [1] "Patient Advocate Tracker Act"
## [1] "A bill to extend by 19 days the authorization for the special assessment for the Domestic Trafficking Victims' Fund."
## [1] "Eliminating Limits to Justice for Child Sex Abuse Victims Act of 2022"
## [1] "To prohibit the Corps of Engineers from issuing a permit for the Delta Conveyance Project, and for other purposes."
## [1] "Requesting the President to transmit certain documents to the House of Representatives relating to any initiative or negotiations regarding Iran's nuclear program."
## [1] "Requesting the President, and directing the Secretary of State, to transmit to the House of Representatives copies of all documents in their possession referring or relating to certain aspects of the United States withdrawal from Afghanistan."
## [1] "Indo-Pacific Engagement Act"
## [1] "YSEALI Act"
## [1] "Peace and Tolerance in Palestinian Education Act"
## [1] "Of inquiry directing the Secretary of the Interior to transmit certain documents to the House of Representatives relating to the actions of the Department of the Interior's Departmental Ethics Office."
## [1] "Of inquiry directing the Secretary of the Interior to transmit certain documents to the House of Representatives relating to the mineral withdrawal within the Superior National Forest."
## [1] "Of inquiry directing the Secretary of Agriculture to transmit certain documents to the House of Representatives relating to the mineral withdrawal within the Superior National Forest."
## [1] "Of inquiry directing the Secretary of the Interior to transmit certain documents to the House of Representatives relating to the compliance with the obligations of the Mineral Leasing Act."
## [1] "Of inquiry directing the Secretary of the Interior to transmit certain documents to the House of Representatives relating to the 2023-2028 five-year program for offshore oil and gas leasing."
## [1] "Department of State Authorization Act of 2022"
## [1] "A bill to amend title VI of the Social Security Act to improve the Local Assistance and Tribal Consistency Fund, and for other purposes."
## [1] "Solid Start Act of 2021"
## [1] "A resolution commemorating September 17, 2022, as \"Constitution Day\" and celebrating the signing of the Constitution."
## [1] "A bill to amend Public Law 91-378 to authorize activities relating to Civilian Conservation Centers, and for other purposes."
## [1] "Whistleblower Protection Improvement Act of 2021"
# url <- bills$pagination$`next`
creds$offset <- 250
r <- GET("https://api.congress.gov/v3/bill", query = creds)
bills <- append(bills, content(r, "parsed")$bills)
length(bills)
We can also try to capture and save the list of all members of congress.
creds$offset <- 0
r <- GET("https://api.congress.gov/v3/member", query = creds)
members <- content(r, "parsed")$members
for (i in seq.int(from = 250, to = content(r, "parsed")$pagination$count, by = 250)){
creds$offset <- i
r <- GET("https://api.congress.gov/v3/member", query = creds)
members <- append(members, content(r, "parsed")$members)
}
Make sure we got all of the members in our list, and if so, save it to a file for later use, as necessary.
if (length(members) == content(r, "parsed")$pagination$count){
saveRDS(members, file="congress_members")
}
If we don’t want to run the above, we can skip to just reading the serialized object (member list) from disk.
if (!exists("members")){
members <- readRDS(file="congress_members")
}
set.seed(1234)
random_member <- members[[sample(1:length(members), 1)]]
# r-markdown for image and text below
# 
# `r paste(random_member$name, random_member$state, random_member$party, sep=", ")`
# ; Chamber(s): `r names(random_member$served)`
Nolan, Richard M., Minnesota, Democratic; Chamber(s): House
Using reticulate, we should be able to load the membership list data we already saved (pickle) in python (colab notebooks)
# py_install("pandas")
pd <- import("pandas")
congress_members_py <- pd$read_pickle("congress_members.pickle")
We can also easily load the csv of the legislation data we saved through python (avoiding the two api calls per member). I moved from my colab notebook to my R folder.
legislation_data <- read.csv("legislation_to_2251.csv")
Let’s do some plots. Need to fix the way I gathered the data again to reflect the correct Chamber for Eleanor Holmes Norton!
top_ten <- legislation_data %>%
distinct() %>%
select(Name, Count_Sponsored, Count_Cosponsored, Chamber) %>%
mutate(total_count = Count_Sponsored + Count_Cosponsored) %>%
mutate(Chamber = replace(Chamber, Name == "Norton, Eleanor Holmes", "House")) %>%
arrange(desc(total_count)) %>%
head(10)
ggplot(top_ten) +
geom_col(aes(x=reorder(Name, -total_count), y=Count_Sponsored, fill=Chamber)) +
theme_bw() +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = "Congress Member", y = "Sponsored Bill Count")
ggplot(top_ten) +
geom_col(aes(x=reorder(Name, -total_count), y=Count_Cosponsored, fill=Chamber)) +
theme_bw() +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = "Congress Member", y = "Cosponsored Bill Count")
ggplot(top_ten) +
geom_col(aes(x=reorder(Name, -total_count), y=total_count, fill=Chamber)) +
theme_classic() +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = "Congress Member", y = "Total Bill Count (sponsored and co-)")