This vignette examines the structure of the sponsorship tibbles contained within the legislation dataset and renders a network graph as an example use case.

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(aRlegislation)
library(dplyr)
library(tidyr) # needed for nest/unnest operations
library(tidygraph)
library(ggraph)

Sponsorship refers to individual laws that each lawmaker or committee presents to the legislative chamber. Some bills have a single sponsor, while others have many. Bills can be sponsored by lawmakers in one or both chambers, by a committee belonging to neither chamber, or some combination thereof. Since the number of lawmakers/committees that sponsor laws can change, this table is a two-column layout with a unique combination of act and sponsor per row:

head(legislation$sponsorship[[1]])

Summary Statistics

The purpose of this simple layout is twofold. First, we want to be able to look at summary statistics about the number of sponsors per act. For instance, we can look at the total number of sponorships by each political party over time, which tells us how much credit each party's lawmakers claim for legislation:

party.colors <- c(
  "R" = "#990000", # dark red = Republicans
  "D" = "#668cff", # light blue = Democrats
  "G" = "#00cc00", # bright green = Green party
  "I" = "#444444", # dark grey = Independent
  "unk" = "#b3b300", # dark yellow = unknown
  "bipartisan" = "#8A2BE2", # purple
  "committee" = "#888888" # medium grey
)

legislation %>%
  unnest(sponsorship) %>%
   left_join(
    legislation %>% unnest(lawmakers),
    by = c("cycle", "session", "sponsor")
  ) %>%
  filter(!is.na(chamber)) %>% # No committee acts
  count(cycle, party, chamber, act) %>% # counts all sponsors who signed onto acts
  count(cycle, party, chamber) %>% # counts acts themselves
  ggplot(aes(y = n, x = cycle, color = party)) +
    geom_point(size = 2.5) +
    geom_line(size = 3) +
    facet_wrap(~ chamber) +
    scale_x_continuous(
      breaks = seq(from = 2001, to = 2019, by = 4), 
      minor_breaks = seq(from = 2001, to = 2019, by = 2)
    ) +
    scale_color_manual(values = party.colors) +
    labs(
      title = "Act Sponsorship by Party",
      x = "", y = ""
    )

Graph Analysis

The second purpose of the sponsorship tibble to facilitate graph analysis. The sponsorship table contains information about graph edges, and the sponsor table contains additional information about graph vertices (that is, where vertices are lawmakers and not committees).

We'll illustrate how the graph works with an example from the 2019 regular session. This is a little more in-depth than the previous examples, since we'll need to generate a to-from relationship from the raw data about sponsorships. The pipeline is a little on the long side, so here are the steps:

selected.cycle <- 27

sponsorship_graph <- legislation$sponsorship[[selected.cycle]] %>%
  right_join( # Right join, because we are excluding committees
      legislation$lawmakers[[selected.cycle]] %>%
        select(sponsor, party),
        by = "sponsor"
  ) %>%
  rename(from = sponsor, from.party = party) %>%
  left_join(
    legislation$sponsorship[[selected.cycle]] %>% 
      right_join( # Right join, because we are excluding committees
        legislation$lawmakers[[selected.cycle]] %>%
        select(sponsor, party, chamber),
        by = "sponsor"
    ) 
    %>% rename(to = sponsor, to.party = party), 
    by = "act"
  ) %>% 
  select(from, from.party, to, to.party, act) %>%
  filter(from < to) %>% # filters duplicate rows; links are unordered
  group_by(from, from.party, to, to.party) %>%
  count(from, from.party, to, to.party) %>% 
  ungroup() %>%
  mutate(
    wt = log(n + 1),
    partisan = ifelse(to.party == from.party, to.party, "bipartisan")
  ) %>%
  arrange(desc(wt)) %>%
  as_tbl_graph() %>%
  activate(nodes) %>%
  left_join(
    legislation$lawmakers[[selected.cycle]] %>%
        select(sponsor, party, chamber),
        by = c("name" = "sponsor")
  ) %>%
  mutate(name = ifelse(chamber == "Senate", toupper(name), tolower(name)))

sponsorship_graph

With the graph constructed from the table of links, we can now visualize the links between the lawmakers:

sponsorship_graph %>%
  mutate(degree = centrality_degree(weights = n)) %>%
  ggraph(layout = "fr") +
    geom_node_text(aes(label = name, color = party), size = 2.5) +
    geom_edge_diagonal(aes(edge_color = partisan, edge_width = wt / 10), edge_alpha = 0.005) +
    scale_color_manual(values = party.colors) +
    scale_edge_color_manual(values = party.colors) +
    theme_graph() +
    theme(legend.position = "none")


titaniumtroop/aRlegislation documentation built on May 4, 2020, 3:24 a.m.