Polling Table Makeover

statistics
r
data viz
Author

Mark Jurries II

Published

April 23, 2025

I came across a table from Gallup showing polling on the economy. It was a well designed table, but it made its job - showing change between time period - more cumbersome than it needs to be.

Again, not terrible, and it doesn’t take long to get the gist of it. But I couldn’t help but think it could be displayed better. They made the data available for download, it required some light transformation to get it ready for analysis. I could’ve done it in R, but it’s a very small dataset and it took about a minute in Excel.

I also want to add error bars. Gallup indicates standard error is plus/minus 6 points and the most recent poll had 1,006 participants. I’ll assume the same population for the January poll. For starters, we’ll look at a line chart (sometimes called a slope chart when comparing only two points) for comparison.

Show the code
library(hrbrthemes)
library(tidyverse)


poll_raw <- read_csv('data-lHINT.csv')

muted_palette <- c("#87CEEB", "#D3D3D3", "#A0522D")

up_good <- c('Economic growth', 'The stock market')

poll_munged <- poll_raw %>%
  mutate(perc = Percent / 100,
         n = 1006,
         se = sqrt((perc * (1 - perc)) / n),
         se_high = perc + (se * 2),
         se_low = perc - (se * 2)) %>%
  mutate(Direction = fct_relevel(Direction, c('Go down a lot/a little', 'Remain the same', 'Go up a lot/a little'))) %>%
  mutate(Date = fct_relevel(Date, '2025 Jan 2-15', '2025 Apr 1-14')) %>%
  mutate(direction_type = case_when(Direction == 'Remain the same' ~ 'Neutral',
                                    Direction == 'Go down a lot/a little' & Poll %in% up_good ~ 'Bad',
                                    Direction == 'Go up a lot/a little' & Poll %in% up_good ~ 'Good',
         Direction == 'Go down a lot/a little' & Poll %in% up_good == FALSE ~ 'Good',
         Direction == 'Go up a lot/a little' & Poll %in% up_good == FALSE ~ 'Bad'))

poll_munged %>%
  ggplot(aes(x = Date, y = perc, color = Direction, group = Direction))+
  geom_line()+
  #geom_errorbar(aes(ymin = se_low, ymax = se_high))+
  facet_wrap(Poll ~ .)+
  scale_y_percent()+
  theme_ipsum()+
  theme(legend.position = 'bottom',
        panel.grid.major = element_line(color = "gray95"),
        panel.grid.minor = element_line(color = "gray95")
        )+
  scale_color_manual(values = muted_palette)+
  xlab('')+
  ylab('')

We can quickly see that compared to January, this poll shows dramatic swings in expectations around economic growth, inflation, and the stock market. Those expecting unemployment to go remained flat, while there was movement from “remain the same” to “go up a lot/a little”. Typically, we’d want a longer time series so we can see in either month is unusual compared to longer trends, but this will suffice for now.

*For more on tariffs, check this famous lecture.

However; polls have margin of error. What if these overlap and this is just a sampling error? Let’s look at the same, this time with error bars.

Show the code
poll_munged %>%
  ggplot(aes(x = perc, y = Date, color = Date))+
  geom_point()+
  geom_errorbar(aes(xmin = se_low, xmax = se_high))+
  facet_grid(Direction ~ Poll)+
  theme_ipsum()+
  theme(legend.position = 'bottom')+
  scale_color_manual(values = c('#4682B4', '#FFA500'))+
  scale_x_percent()+
  scale_y_discrete(limits=rev)+
  xlab('')+
  ylab('')

While Interest Rates and Unemployment are close, generally each poll shows some statistically significant change from the earlier poll. This all assumes that polls were done with similar populations, same questions, etc., stuff Gallup is pretty forthcoming with.

The application to an aspiring analyst is to plot your data. Even if it’s simple and you can make a killer table, showing it in a chart makes it easier and faster to digest - even if it’s decidedly unpleasant information.