Introduction to the voteogram package

Bob Rudis

2023-03-08

Basic usage only requires this package and ggplot2:

library(voteogram)
library(ggplot2)

Getting Vote Data

The cartograms need data and the best way to do that is by obtaining roll call vote data from ProPublica via the roll_call() function. Data can be retrieved for any House or Senate vote by specificing the target vote parameters:

sen <- roll_call("senate", 115, 1, 110)
rep <- roll_call("house", 115, 1, 256)

Their structures look the same and there is a print-method to make the console output easier on the eyes:

str(sen)
#> List of 29
#>  $ vote_id              : chr "S_115_1_110"
#>  $ chamber              : chr "Senate"
#>  $ year                 : int 2017
#>  $ congress             : chr "115"
#>  $ session              : chr "1"
#>  $ roll_call            : int 110
#>  $ needed_to_pass       : int 51
#>  $ date_of_vote         : chr "April  6, 2017"
#>  $ time_of_vote         : chr "12:35 PM"
#>  $ result               : chr "Cloture Motion Agreed to"
#>  $ vote_type            : chr "1/2"
#>  $ question             : chr "On the Cloture Motion"
#>  $ description          : chr "Neil M. Gorsuch, of Colorado, to be an Associate Justice of the Supreme Court of the United States"
#>  $ nyt_title            : chr "On the Cloture Motion"
#>  $ total_yes            : int 55
#>  $ total_no             : int 45
#>  $ total_not_voting     : int 0
#>  $ gop_yes              : int 52
#>  $ gop_no               : int 0
#>  $ gop_not_voting       : int 0
#>  $ dem_yes              : int 3
#>  $ dem_no               : int 43
#>  $ dem_not_voting       : int 0
#>  $ ind_yes              : int 0
#>  $ ind_no               : int 2
#>  $ ind_not_voting       : int 0
#>  $ dem_majority_position: chr "No"
#>  $ gop_majority_position: chr "Yes"
#>  $ votes                : tibble [100 × 11] (S3: tbl_df/tbl/data.frame)
#>   ..$ bioguide_id         : chr [1:100] "A000360" "B001230" "B001261" "B001267" ...
#>   ..$ role_id             : int [1:100] 526 481 498 561 535 547 507 551 480 555 ...
#>   ..$ member_name         : chr [1:100] "Lamar  Alexander" "Tammy Baldwin" "John Barrasso" "Michael Bennet" ...
#>   ..$ sort_name           : chr [1:100] "Alexander" "Baldwin" "Barrasso" "Bennet" ...
#>   ..$ party               : chr [1:100] "R" "D" "R" "D" ...
#>   ..$ state_abbrev        : chr [1:100] "TN" "WI" "WY" "CO" ...
#>   ..$ display_state_abbrev: chr [1:100] "Tenn." "Wis." "Wyo." "Colo." ...
#>   ..$ district            : chr [1:100] "2" "1" "1" "1" ...
#>   ..$ position            : chr [1:100] "Yes" "No" "Yes" "No" ...
#>   ..$ dw_nominate         : logi [1:100] NA NA NA NA NA NA ...
#>   ..$ pp_id               : chr [1:100] "TN" "WI" "WY" "CO" ...
#>  - attr(*, "class")= chr [1:2] "pprc" "list"

sen$votes
#> # A tibble: 100 × 11
#>    biogu…¹ role_id membe…² sort_…³ party state…⁴ displ…⁵ distr…⁶ posit…⁷ dw_no…⁸
#>  * <chr>     <int> <chr>   <chr>   <chr> <chr>   <chr>   <chr>   <chr>   <lgl>  
#>  1 A000360     526 Lamar … Alexan… R     TN      Tenn.   2       Yes     NA     
#>  2 B001230     481 Tammy … Baldwin D     WI      Wis.    1       No      NA     
#>  3 B001261     498 John B… Barras… R     WY      Wyo.    1       Yes     NA     
#>  4 B001267     561 Michae… Bennet  D     CO      Colo.   1       No      NA     
#>  5 B001277     535 Richar… Blumen… D     CT      Conn.   2       No      NA     
#>  6 B000575     547 Roy  B… Blunt   R     MO      Mo.     2       Yes     NA     
#>  7 B001288     507 Cory  … Booker  D     NJ      N.J.    2       No      NA     
#>  8 B001236     551 John  … Boozman R     AR      Ark.    1       Yes     NA     
#>  9 B000944     480 Sherro… Brown   D     OH      Ohio    1       No      NA     
#> 10 B001135     555 Richar… Burr    R     NC      N.C.    1       Yes     NA     
#> # … with 90 more rows, 1 more variable: pp_id <chr>, and abbreviated variable
#> #   names ¹​bioguide_id, ²​member_name, ³​sort_name, ⁴​state_abbrev,
#> #   ⁵​display_state_abbrev, ⁶​district, ⁷​position, ⁸​dw_nominate
str(rep)
#> List of 29
#>  $ vote_id              : chr "H_115_1_256"
#>  $ chamber              : chr "House"
#>  $ year                 : int 2017
#>  $ congress             : chr "115"
#>  $ session              : chr "1"
#>  $ roll_call            : int 256
#>  $ needed_to_pass       : int 216
#>  $ date_of_vote         : chr "May  4, 2017"
#>  $ time_of_vote         : chr "02:18 PM"
#>  $ result               : chr "Passed"
#>  $ vote_type            : chr "RECORDED VOTE"
#>  $ question             : chr "On Passage"
#>  $ description          : chr "American Health Care Act"
#>  $ nyt_title            : chr "On Passage"
#>  $ total_yes            : int 217
#>  $ total_no             : int 213
#>  $ total_not_voting     : int 1
#>  $ gop_yes              : int 217
#>  $ gop_no               : int 20
#>  $ gop_not_voting       : int 1
#>  $ dem_yes              : int 0
#>  $ dem_no               : int 193
#>  $ dem_not_voting       : int 0
#>  $ ind_yes              : int 0
#>  $ ind_no               : int 0
#>  $ ind_not_voting       : int 0
#>  $ dem_majority_position: chr "No"
#>  $ gop_majority_position: chr "Yes"
#>  $ votes                : tibble [435 × 11] (S3: tbl_df/tbl/data.frame)
#>   ..$ bioguide_id         : chr [1:435] "A000374" "A000370" "A000055" "A000371" ...
#>   ..$ role_id             : int [1:435] 274 294 224 427 268 131 388 320 590 206 ...
#>   ..$ member_name         : chr [1:435] "Ralph Abraham" "Alma  Adams" "Robert B. Aderholt" "Pete Aguilar" ...
#>   ..$ sort_name           : chr [1:435] "Abraham" "Adams" "Aderholt" "Aguilar" ...
#>   ..$ party               : chr [1:435] "R" "D" "R" "D" ...
#>   ..$ state_abbrev        : chr [1:435] "LA" "NC" "AL" "CA" ...
#>   ..$ display_state_abbrev: chr [1:435] "La." "N.C." "Ala." "Calif." ...
#>   ..$ district            : int [1:435] 5 12 4 31 12 3 2 19 36 2 ...
#>   ..$ position            : chr [1:435] "Yes" "No" "Yes" "No" ...
#>   ..$ dw_nominate         : logi [1:435] NA NA NA NA NA NA ...
#>   ..$ pp_id               : chr [1:435] "LA_5" "NC_12" "AL_4" "CA_31" ...
#>  - attr(*, "class")= chr [1:2] "pprc" "list"

fortify(rep)
#> # A tibble: 435 × 11
#>    biogu…¹ role_id membe…² sort_…³ party state…⁴ displ…⁵ distr…⁶ posit…⁷ dw_no…⁸
#>  * <chr>     <int> <chr>   <chr>   <chr> <chr>   <chr>     <int> <chr>   <lgl>  
#>  1 A000374     274 Ralph … Abraham R     LA      La.           5 Yes     NA     
#>  2 A000370     294 Alma  … Adams   D     NC      N.C.         12 No      NA     
#>  3 A000055     224 Robert… Aderho… R     AL      Ala.          4 Yes     NA     
#>  4 A000371     427 Pete A… Aguilar D     CA      Calif.       31 No      NA     
#>  5 A000372     268 Rick A… Allen   R     GA      Ga.          12 Yes     NA     
#>  6 A000367     131 Justin… Amash   R     MI      Mich.         3 Yes     NA     
#>  7 A000369     388 Mark A… Amodei  R     NV      Nev.          2 Yes     NA     
#>  8 A000375     320 Jodey … Arring… R     TX      Texas        19 Yes     NA     
#>  9 B001291     590 Brian … Babin   R     TX      Texas        36 Yes     NA     
#> 10 B001298     206 Don Ba… Bacon   R     NE      Neb.          2 Yes     NA     
#> # … with 425 more rows, 1 more variable: pp_id <chr>, and abbreviated variable
#> #   names ¹​bioguide_id, ²​member_name, ³​sort_name, ⁴​state_abbrev,
#> #   ⁵​display_state_abbrev, ⁶​district, ⁷​position, ⁸​dw_nominate

That data may be useful on its own (ouside of plotting).

Note, also, that ggplot2’s fortify() method uses the provided object class method for roll call objects to know how to extract the rectangular data necessary for plotting.

Making Cartograms

These cartograms have a few style options:

ProPublica

senate_carto(sen) +
  labs(title="Senate Vote 110 - Invokes Cloture on Neil Gorsuch Nomination") +
  theme_voteogram()

house_carto(rep, pp_square=TRUE) +
  labs(x=NULL, y=NULL, 
       title="House Vote 256 - Passes American Health Care Act,\nRepealing Obamacare") +
  theme_voteogram()

house_carto(rep, pp_square=FALSE) +
  labs(x=NULL, y=NULL, 
       title="House Vote 256 - Passes American Health Care Act,\nRepealing Obamacare") +
  theme_voteogram()

GovTrack

house_carto(rep, "gt") +
  labs(x=NULL, y=NULL, 
       title="House Vote 256 - Passes American Health Care Act,\nRepealing Obamacare") +
  theme_voteogram()

They can be shrunk down well (though that likely means annotating them in some other way):

Tiny Cartograms

senate_carto(sen) + theme_voteogram(legend=FALSE)

house_carto(rep) + theme_voteogram(legend=FALSE)

house_carto(rep, pp_square=TRUE) + theme_voteogram(legend=FALSE)