1  Bar graphs

Graphs in this chapter use fmggp2::theme_gameboy(), modeled on the original Game Boy screen: the four shade green palette, a dark green frame, and the pixel font Press Start 2P (bundled with the package).

Requirements:

✅ a categorical variable


1.1 Description

A bar graph shows a number for each group as a bar, so we can compare the groups by how long the bars are.1 The bars can stand up or run across, with the numbers going up the side of the graph and the groups going across under the bars.2 When a bar graph compares more than one thing, a key3 tells us what each color or mark means.

In ggplot2, we can make bar graphs with geom_bar().

1.2 Set up

PACKAGES:

Bring in the code we’ll use.4

show/hide
library(ggplot2)
library(dplyr) # for tibble() and data manipulation

DATA:

Alleyway box art

The Game Boy is a small computer for playing games that you hold in your hands. Alleyway was one of the games you could buy when the Game Boy first came out in 1989. Mario is a little man who shows up in many games. In Alleyway, Mario moves a short bar with round ends from side to side and hits a ball up into rows of small boxes that break,5 and a game ends when the last ball is lost.

Alleyway

We’ll make up6 the last stage reached by 300 players with sample(), and give each of the first three stages its own chance.7 Starting with set.seed()8 means you’ll get the same 300 games every time you run the code below.

show/hide
set.seed(1998) # same 300 games every time the code runs
alleyway_games <- tibble(
  player_id = 1:300, # 300 different players, one row (and one game) each
  stage = sample(
    c("Stage 1", "Stage 2", "Stage 3"), # stages where the last ball can be lost
    size = 300, # one stage for each player
    replace = TRUE, # stages can repeat across players
    prob = c(0.30, 0.42, 0.28) # probabilities for each stage (Stage 2 is most likely)
    )
)
glimpse(alleyway_games)
#> Rows: 300
#> Columns: 2
#> $ player_id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,…
#> $ stage     <chr> "Stage 2", "Stage 2", "Stage 2…

1.3 Distribution

A count is how many times something happens. The next two graphs in this book9 put numbers into boxes10 and count how many fall in each box. A bar graph is simpler: it counts how many times each group shows up. We picked the chances in sample(), so we know what those counts should be before we make any graph. Below we’ll move from the choices, to a graph, to the rule behind it.11

COUNT IT:

Start with the first ten players.

show/hide
head(alleyway_games$stage, 10)
#>  [1] "Stage 2" "Stage 2" "Stage 2" "Stage 2"
#>  [5] "Stage 3" "Stage 2" "Stage 2" "Stage 3"
#>  [9] "Stage 3" "Stage 1"

Six of these ten players lost their last ball in Stage 2. Ten games are too few to trust, so we count all 300 and compare each count to the count we’d expect:12 the number of players (300) times the chance we gave each stage.

show/hide
stage_counts <- alleyway_games |>
  count(stage) |>
  mutate(expected = 300 * c(0.30, 0.42, 0.28))
stage_counts

DRAW IT:

A bar model shows the three counts as parts of one whole. The full bar is all 300 players, and Stage 2 takes up the biggest part.

show/hide
ggplot(data = stage_counts,
    aes(x = n, y = "300 players", fill = stage)) +
  
  geom_col(position = position_stack(reverse = TRUE)) +
  
  geom_text(
    aes(label = n), 
    color = c("#9BBC0F", "#9BBC0F", "#0F380F"),
    position = position_stack(vjust = 0.5, reverse = TRUE)
    ) +
  labs(
    x = "Number of players", 
    y = NULL, 
    fill = "Stage")

A bar graph takes the same three parts, stands each one up, and puts them side by side. The broken lines below mark the counts we’d expect. Each bar lands near its line, and the Stage 2 bar matches its line exactly.

show/hide
ggplot(data = alleyway_games,
    aes(x = stage)) +
  geom_bar(aes(fill = stage), show.legend = FALSE) +
  geom_errorbar(
    data = stage_counts,
    aes(
      y = expected, 
      ymin = expected, 
      ymax = expected),
    linetype = "dashed", 
    width = 0.9) +
  labs(x = "Stage", y = "Count")

NAME IT:

Each game is like a turn with a three sided die that doesn’t land on each side the same number of times. Counting what comes up in 300 turns gives a rule for how many times each side comes up:13

\[ (N_{\text{Stage 1}}, N_{\text{Stage 2}}, N_{\text{Stage 3}}) \sim \text{Multinomial}(n = 300, \; p = (0.30, 0.42, 0.28)) \]

We’d expect each bar to be \(n \times p\) high:14 \(300 \times 0.30 = 90\) for Stage 1, \(300 \times 0.42 = 126\) for Stage 2, and \(300 \times 0.28 = 84\) for Stage 3. The three chances add up to 1, so the three bars always add up to 300. If one bar comes out higher than we’d expect, another has to come out shorter.

The players we made up show just that: Stage 1 came in 6 below the count we’d expect, and Stage 3 came in 6 above. Change the number in set.seed() and the bars move around their broken lines, but they always add up to 300.

1.4 Grammar

CODE:

  1. Make the words around the graph15 with labs()

  2. Start the graph with ggplot() and give it data

  3. Put stage on the x axis16

  4. Inside the aes() of geom_bar(), join stage to fill so each bar gets its own color17

  5. Take away the key with show.legend = FALSE

show/hide
labs_bar <- labs(
  title = "Alleyway",
  caption = "Simulated data",
  subtitle = "Last stage reached by 300 players",
  x = "Stage", y = "Count",
  fill = "Stage")
ggp2_bar <- ggplot(data = alleyway_games,
       aes(x = stage)) +
    geom_bar(aes(fill = stage),
        show.legend = FALSE)
ggp2_bar +
  labs_bar

GRAPH:

1.5 More info

Ways to show the data18 and ways to work out new numbers from the data19 go together. Knowing how they work together is important for building graphs with ggplot2 (and for learning its rules20). Below we show why geom_bar(stat = "count") makes the same graph as stat_count(geom = "bar").21

“every geom has a default stat, and every stat a default geom.” - ggplot2 book

1.5.1 Stats and geoms

stat_count():

Unless we tell it to do something else, geom_bar() sets stat to "count",22 which ‘counts the number of cases at each x position’, so it works well for columns of groups.23

We can also make bar graphs with stat_count() by setting its geom.24

The code below shows how geom_geom_name(stat = "stat_name") and stat_stat_name(geom = "geom_name") go together:

show/hide
ggp2_geom_bar <- ggplot(data = alleyway_games,
       aes(x = stage)) +
    geom_bar(aes(fill = stage),
        stat = "count") +
    labs(title = "geom_bar(stat = 'count')")
ggp2_geom_bar


ggp2_stat_count <- ggplot(data = alleyway_games,
       aes(x = stage)) +
    stat_count(aes(fill = stage),
        geom = "bar") +
    labs(title = "stat_count(geom = 'bar')")
ggp2_stat_count

1.5.2 geom_col()

geom_col():

To make a bar graph with geom_col(), we have to work out the count column first and then put it on the y axis.25

show/hide
alleyway_games |>
    # create column of counts
    dplyr::count(stage, name = "count") |>
    # map into x and y
    ggplot(mapping = aes(x = stage, y = count)) +
    geom_col(aes(fill = stage),
        show.legend = FALSE) +
    labs_bar +
    labs(caption = "geom_col()")


# compare to geom_bar()
ggp2_bar +
  labs_bar


  1. Bar graphs compare categories (the levels of a categorical variable) using rectangular bars that vary in length or height.↩︎

  2. Bars can be vertical or horizontal; the vertical axis shows the quantities being measured, and the horizontal axis lists the categories.↩︎

  3. A legend explaining the colors or patterns used when comparing multiple variables.↩︎

  4. Install and load the packages.↩︎

  5. Mario steers a horizontal, pill shaped paddle along the bottom of the screen and bounces the ball into rows of bricks.↩︎

  6. Simulate.↩︎

  7. A probability (the prob argument in sample()).↩︎

  8. Setting the random seed.↩︎

  9. Histograms and frequency polygons.↩︎

  10. Bins.↩︎

  11. The formula.↩︎

  12. The expected count.↩︎

  13. A multinomial distribution: the counts in each of \(k\) categories across \(n\) independent trials with fixed probabilities.↩︎

  14. The expected count, where \(n\) is the number of trials (players) and \(p\) is the probability for each stage.↩︎

  15. The labels (title, subtitle, caption, and axis titles).↩︎

  16. Map stage to the x axis in aes().↩︎

  17. Map stage to the fill aesthetic.↩︎

  18. Geoms (geometric objects).↩︎

  19. Statistical transformations (stats).↩︎

  20. The grammar of graphics.↩︎

  21. Bar graphs can also be created with geom_col()↩︎

  22. The default stat argument.↩︎

  23. Categorical variables (or factors).↩︎

  24. The geom argument.↩︎

  25. The count variable needs to be computed before being mapped to the y aesthetic.↩︎