This is part of a series of short posts about politics that seeks to show how we use data science to learn more about the real world. Follow along here.
The only self-described socialist in Congress, Alexandria Ocasio-Cortez of New York’s 14th Congressional District, was also the only Democrat to vote no against a bill to re-open the United States’ shutdown government this last Thursday (funding has since been re-appropriated and the government opened). Given Cortez’s stated views, we expect that this no-vote came from her opposition to any number of standard Democratic party ideals. Indeed, she posted on Instagram that her no vote was rooted in the funding bill’s appropriations for Immigration and Customs Enforcement, an agency that members of the progressive left have routinely pledged to abolish.
The problem is that our computers don’t see it that way. Instead, they see that Ocasio-Cortez voted alongside 179 Republican members in blocking the Democratic-sponsored bill — she looks more like a Republican than a socialist Democrat, which is obviously wrong.
What do I mean when I say that our “computers” see it this way? Specifically, I’m talking about popular algorithms such as DW-NOMINATE that use multi-dimensional scaling to compute “ideal points” for each legislator, placing them along the traditional left-right political spectrum (it’s really more like “spectrums”). One of the major issues with them is their inability to extract meaning from such counter-intuitive no votes as Representative Ocasio-Cortez’s above; she looks more conservative, when she should look even more liberal.
Here, you can see that here DW-NOMINATE score actually places her in a quite moderate position along first dimension of DW-NOMINATE, often referred to as the economic dimension.
library(tidyverse) library(knitr) library(kableExtra) library(ggrepel) library(ggExtra) # read in the data house_ideo <- read_csv("https://voteview.com/static/data/out/members/Hall_members.csv") # filter the data just for Democrats (100) and Republicans (200), and recode # also, only keep for the present congress (116th) house_ideo <- house_ideo %>% filter(congress==116,chamber=="House") %>% mutate(party = case_when(party_code == 100 ~ "Democratic", party_code == 200 ~ "Republican")) # plot the dim 1 and 2, single out AOC gg <- ggplot(house_ideo, aes(x=nominate_dim1,y=nominate_dim2,col=party)) + geom_point() + geom_label_repel(data=house_ideo %>% filter(grepl("ocasio",tolower(bioname))), label='Ocasio-Cortez',show.legend = F,nudge_x=0.15,min.segment.length = 0.01) + scale_color_manual("Party",values=c("Republican"="#E74C3C","Democratic"="#3498DB")) + labs(x="DW-NOMINATE Ideology\n(Dimension 1)", y="DW-NOMINATE Ideology\n(Dimension 2)", title="Ocasio-Cortez Doesn't Look So Socialist (Yet)", subtitle="Could this be due to a weakness in algorithms that are based on roll call votes?", caption="Source: VoteView.com") + theme(legend.position = 'none')
preview(gg,themearg = theme(legend.position = 'none'))
While Ocasio-Cortez looks quite isolated in her point on the second (vertical) dimension of DW-NOMINATE (the “lifestyle” or “social” dimension), she gets placed in the middle of the pack along the “economic” dimension. In fact, she’s slightly to the right of the average Democrat, with an ideal point of -0.322 compared to the -0.405 average.
To be sure, there haven’t been very many roll calls in the 116th Congress yet. There are fewer than thirty roll calls with which to place Ocasio-Cortez along the spectrum. Perhaps over time she’ll drift leftward along the first dimension, where she “belongs.” In fact, at the current time NOMINATE pegs her as about 1/4th more moderate than Joe Crowley, the establishment Democratic Representative she beat in last year’s primary.
The unfortunate truth is that, without enough votes, the calculation might just not be working correctly. This single no vote makes Ocasio-Cortez look more conservative than socialist. Over time, it could be that her score really takes former and shifts left. But for now, her presence in Congress is a stark reminder that the typical scores might not be capturing what we think. However, if Rep. Ocasio-Cortez and the other members of the far-left only occasionally vote against their party to signal their ideological orientation, our quantitative estimates might not ever be able to really nail them. They’ll simply look a little more moderate — especially if those votes are dispersed among a wide array of topics..
There’s also this plot, which shows the distribution of data alongside the scatter, but at first seems impervious to my personal theming and I don’t have time to fix it.
library(ggExtra) main_plot <- ggplot(house_ideo, aes(x=nominate_dim1,y=nominate_dim2,col=party)) + geom_point() + geom_label_repel(data=house_ideo %>% filter(grepl("ocasio",tolower(bioname))), label='Ocasio-Cortez',show.legend = F,nudge_x=0.15,min.segment.length = 0.01) + scale_color_manual("Party",values=c("Republican"="#E74C3C","Democratic"="#3498DB")) + labs(x="DW-NOMINATE Ideology\n(Dimension 1)", y="DW-NOMINATE Ideology\n(Dimension 2)", title="Ocasio-Cortez Doesn't Look So Socialist (Yet)", subtitle="Could this be due to a weakness in algorithms that are based on roll call votes?", caption="Source: VoteView.com") + theme_minimal() + theme(legend.position = 'none') ggMarginal(main_plot,colour=NA,type = 'histogram',groupFill = TRUE)
- R for Political Data Science Week 7: The 2020 Twitter Primary
- R for Political Data Science Week 6: Just How Liberal Are the 2020 Democratic Candidates?
- R for Political Data Science Week 5: The Ideological Diversity of the American Electorate