Describing: Statistics and Graphics

S23 · Chapter 12 · MC 451 Research Methods in Mass Media

Dr. Alex Leith

What we are building today

Describing Data, 75 points, due this week

  • Chapter 11 left us with analysis, a tidy table of about 35,000 rows
  • Nobody can read 35,000 rows. A figure makes the pattern visible.
  • Today we build three figures and one summary table
  • Each figure is a different chart type, chosen to fit a different question
  • These figures become the Results section of your White Paper

The grammar of graphics

ggplot2 is not a catalog of chart types. It is one idea, borrowed from Wilkinson’s The Grammar of Graphics: every plot is the same few parts.

  • Data: the table being shown
  • Aesthetic mappings: which column goes to x, to y, to color
  • Geometry: the mark used to draw it, a line or bar or point

Choose those three and the plot is specified.

The skeleton in code

ggplot(data, aes(x = ..., y = ...)) +
  geom_line()

ggplot() names the data and, inside aes(), says which column maps to which visual property. geom_line() says what mark to draw. The + stacks layers.

Swap geom_line() for geom_col() and the same data is drawn as bars. That is the payoff: a handful of interchangeable parts covers an enormous range.

Your turn

  • You have a variable you plan to describe in your paper. What shape do you expect it to have?
  • Would a line, a bar, or a histogram answer your question best?
  • What would surprise you if you saw it?

Two minutes with a neighbor, then we compare.

A line for change over time

The first question: across the collection week, how did viewership move, split by the game being played?

viewers_over_time <- streams %>%
  filter(!is.na(game)) %>%
  mutate(
    timestamp = as.POSIXct(date / 1000, origin = "1970-01-01", tz = "UTC"),
    six_hour  = floor_date(timestamp, "6 hours"),
    category  = fct_lump_n(game, n = 5)
  ) %>%
  group_by(six_hour, category) %>%
  summarise(total_viewers = sum(viewers), .groups = "drop")

Bucket the snapshots into six-hour blocks, keep the top five games by name and call everything else “Other,” then sum the viewers inside each bucket.

Drawing the line

ggplot(viewers_over_time,
       aes(x = six_hour, y = total_viewers, color = category)) +
  geom_line(linewidth = 0.9) +
  labs(title = "Concurrent viewers by game category",
       x = "Date (UTC, six-hour buckets)",
       y = "Total viewers in bucket", color = "Category") +
  v2v::scale_colour_v2v() +
  v2v::theme_v2v()

Time on x, summed viewers on y, category to color, so each game gets its own line. theme_v2v() gives every figure in the set one consistent look.

What the line chart shows

  • The dominant line is “Other,” spiking above 20 million viewers
  • One reading is substantive: viewership really is spread across a long tail
  • The other is a caution: lumping fifty categories into one bucket guarantees that bucket wins
  • Design cost: the five named lines get pressed flat against the axis
  • A dominant series crowds out the rest. Notice that, and say so.

A bar for counts

Hour of day is not a continuous sweep. It is 24 discrete categories, and what we want per category is a count.

chat_by_hour <- analysis %>%
  mutate(hour = hour(timestamp)) %>%
  count(hour, name = "messages")

ggplot(chat_by_hour, aes(x = hour, y = messages)) +
  geom_col(fill = "#2f7d8a") +
  labs(x = "Hour of day (UTC)", y = "Messages in sample") +
  v2v::theme_v2v()

geom_col() draws a bar whose height is a value you already computed, which is exactly what count() produced.

What the bar chart shows

Twitch, November 2018

  • A clear daily pulse: busiest through UTC midday and afternoon
  • Peak at 13:00 with 2,201 messages, floor at 03:00 with 833
  • A swing of well over two to one between loudest and quietest hour
  • Not mysterious: the audience sat in the Americas and Europe
  • Twenty-four numbers become a rhythm you read in one glance

A histogram for shape

The study’s central question: how long is a chat message, and does it depend on the kind of channel?

msglen <- analysis %>%
  filter(!is.na(is_gaming)) %>%
  mutate(length_shown = pmin(message_length, 120))

ggplot(msglen, aes(x = length_shown, fill = is_gaming)) +
  geom_histogram(binwidth = 5, position = "identity", alpha = 0.55) +
  v2v::scale_fill_v2v() +
  v2v::theme_v2v()

A histogram slices a numeric variable into equal intervals (bins) and draws a bar for how many values land in each. Two groups overlaid, so shapes compare.

Two choices you have to disclose

  • binwidth = 5 sets each bar to five characters. Wider smooths, narrower roughens. It is a judgment, so report it.
  • pmin(message_length, 120) caps the display at 120 characters
  • Twitch’s real limit is 500, so that last bar is a genuine pile-up
  • Capping keeps the bulk legible instead of stretched by a few outliers
  • A cap that is not announced is a quiet distortion. Label the axis.

What the histogram shows

  • Both groups are heavily right-skewed: a tall stack of very short messages, then a long thin tail
  • Twitch chat is mostly brief, a word or an emote
  • A minority of long messages stretches the range
  • This is the most important thing the figure reveals
  • It is invisible in any single summary number

Mean and median disagree

Group by is_gaming, then summarise() n, mean, median, and sd. Send it through v2v::pretty_table() and you get this:

is_gaming n mean median sd
FALSE 3,457 33.70 16 60.68
TRUE 31,309 28.49 17 38.47

Why they disagree

  • Read the mean and non-gaming chat looks longer: 33.70 against 28.49
  • Read the median and the story collapses: 16 against 17, near identical, pointing the other way
  • The mean is pulled by a long tail. The median is not.
  • Non-gaming has the heavier tail, and its sd of 60.68 against 38.47 records it
  • The gap in means is real arithmetic, but it is the tail’s work

Checkpoint

You should now have:

  • A line chart, a bar chart, and a histogram, all using theme_v2v()
  • A grouped summary table with n, mean, median, and sd
  • The binwidth and any cap written into your axis labels
  • One sentence per figure saying what it shows

If a figure will not render, check that every + ends the line above it.

Before next time

  • Describing Data [R] is due this week, 75 points
  • Thursday is a lab: you build these three figures on your own variables
  • Bring your analysis table and your research question
  • Read Chapter 12 if you have not, especially the section on readable figures
  • A figure can frame the five-character question. It cannot answer it. That is Chapter 13.