11  Billboard Hot 100

Part 5: Case Studies

The case studies reuse the tidyverse workflow with new topics and data structures. Instead of repeating every step from the main dataset, each case concentrates on a challenge that commonly appears in journalistic data.

The new challenge: identify the song and define success

One row is one song on one weekly chart, not one unique song. Different artists can also release songs with the same title. Before ranking artists, we must decide how to identify a song and what “success” means: chart appearances, distinct Hot 100 songs, distinct number-one songs, or weeks at number one.

11.1 Learning objectives

By the end of this case, you should be able to:

  • explain why one song can appear in many rows;
  • identify a song with its artist and title together;
  • compare different measures of chart success;
  • distinguish weekly appearances from distinct-song counts; and
  • label a ranking with the measure actually calculated.

11.2 Set up the case

The column names in the source contain capital letters and spaces. rename() gives them shorter working names. parse_number() turns values such as text containing a number into numeric values.

Continue in the same project

Open djr.Rproj and create 09-hot100.Rmd. Download hot100.csv and save it in data/. This case changes the topic, but it uses the same project and tidyverse workflow.

library(tidyverse)

hot100 <- read_csv("data/hot100.csv") |>
  rename(
    date = Date,
    song = Song,
    artist = Artist,
    rank = Rank,
    peak_position = `Peak Position`,
    weeks_in_chart = `Weeks in Charts`
  ) |>
  mutate(weeks_in_chart = parse_number(weeks_in_chart))

glimpse(hot100)
Rows: 345,887
Columns: 8
$ date           <date> 1958-08-06, 1958-08-06, 1958-08-06, 1958-08-06, 1958-0…
$ song           <chr> "Poor Little Fool", "Nel Blu Dipinto Di Blu (Volare)", …
$ artist         <chr> "Ricky Nelson", "Domenico Modugno", "Perez Prado And Hi…
$ rank           <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 11, 12, 13, 14, 15, 16, 1…
$ `Last Week`    <dbl> 1, 54, 2, 3, 5, 8, 4, 6, 12, 9, 7, 14, 10, 18, 11, 19, …
$ peak_position  <dbl> 1, 2, 2, 3, 5, 6, 4, 6, 9, 9, 7, 12, 10, 14, 11, 16, 16…
$ weeks_in_chart <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ `Image URL`    <chr> "#", "https://charts-static.billboard.com/img/1958/08/d…

One row represents one song’s position on one weekly chart date. A song that appears for 20 weeks contributes 20 rows.

11.3 Strategy 1: identify a song with two columns

A title alone does not always identify a song. Several artists may have songs with the same title. The following check keeps every artist-title combination once, then finds titles associated with more than one artist:

hot100 |>
  distinct(artist, song) |>
  count(song, name = "number_of_artists") |>
  filter(number_of_artists > 1) |>
  arrange(desc(number_of_artists)) |>
  slice_head(n = 10)

For this case, we define a unique song as one published artistsong combination. This is an analytical rule, not a universal identifier. Remixes, featured artists, and changing chart credits may require additional reporting decisions.

11.4 Strategy 2: define the period and threshold

We will study chart records from 2000 onward. First create the period, then make the number-one subset used by several measures:

chart_period <- hot100 |>
  filter(date >= "2000-01-01")

number_ones <- chart_period |>
  filter(rank == 1)

The date boundary makes “from 2000 onward” precise. The end of the period is the latest date contained in the supplied file.

The next decision is the chart threshold. “Appeared in the Hot 100,” “reached the top 10,” and “reached number one” are different achievements. A defensible analysis names the threshold before counting.

11.5 Compare measures of success

Consider the reporting question:

Which artists were most successful on the Billboard Hot 100 from 2000 onward?

The dataset does not contain one correct success column. We could measure:

Measure What it counts
Distinct Hot 100 songs Different artist-title combinations appearing anywhere on the chart
Distinct number-one songs Different artist-title combinations that reached number one
Weekly number-one appearances Number-one rows across weekly charts
Longest-running number-one song Number-one rows for one artist-title combination

First count distinct Hot 100 songs by artist:

artist_hot100_songs <- chart_period |>
  distinct(artist, song) |>
  count(artist, name = "hot100_songs") |>
  arrange(desc(hot100_songs))

artist_hot100_songs |>
  slice_head(n = 10)

11.6 Strategy 3: count weekly number-one appearances

count() counts weekly rows for each artist:

artist_weeks <- number_ones |>
  count(artist) |>
  arrange(desc(n))

artist_weeks |>
  slice_head(n = 10)

If one song stays at number one for ten weeks, it contributes ten rows to this measure. A clear name would be weekly number-one appearances.

11.7 Strategy 4: count distinct number-one songs

To count songs rather than weeks, keep each artist-song pair once before counting:

artist_songs <- number_ones |>
  distinct(artist, song) |>
  count(artist) |>
  arrange(desc(n))

artist_songs |>
  slice_head(n = 10)

This ranking may differ from the weekly ranking. One long-running hit and several shorter hits represent different forms of chart success.

11.8 Strategy 5: keep the artist and title together

Keep the song and artist together, then count their weekly rows:

song_weeks <- number_ones |>
  count(artist, song) |>
  arrange(desc(n))

song_weeks |>
  slice_head(n = 10)

Grouping by title alone could combine different songs that happen to share a name.

11.9 Make the label match the metric

Create a bar chart of distinct number-one songs:

top_artists <- artist_songs |>
  slice_head(n = 10)

top_artists |>
  ggplot(aes(x = n, y = fct_reorder(artist, n))) +
  geom_col() +
  labs(
    title = "Artists with the most distinct number-one songs from 2000 onward",
    x = "Distinct songs that reached number one",
    y = NULL,
    caption = "Source: Billboard Hot 100 data supplied with the course"
  ) +
  theme_minimal()

If the code counts weekly rows, the title must say weeks or weekly appearances. Calling both measures “number of songs” would change the finding.

11.10 Check artist credits

The artist column contains the credit printed on the chart. A performer may appear alone, with a featured artist, or as part of a group. Before combining names, inspect possible variants:

hot100 |>
  distinct(artist) |>
  filter(str_detect(str_to_lower(artist), "taylor swift"))

This analysis ranks published credit strings. Splitting collaborations or merging name variants requires a rule that should be documented.

11.11 Practice

Choose a decade and calculate:

  1. distinct Hot 100 songs by artist;
  2. weekly number-one appearances by artist;
  3. distinct number-one songs by artist; and
  4. weeks at number one by artist-song pair.

Compare the leading five results. Make one chart whose title and axis describe the chosen metric exactly, and write one note about collaborations or artist name variants.

11.12 Takeaways

Function What it does in this case
rename() Gives difficult source columns shorter working names
parse_number() Converts a column containing numeric text
filter() Defines the dates and chart position included
count() Counts weekly chart rows at the current grouping
distinct() Keeps one artist-song combination before counting
str_detect() Searches artist credits for possible name variants
Metric definition Turns the broad idea of “success” into a reproducible measure
Want more control?

The official stringr reference lists other tidyverse tools for finding and cleaning text. Use them only when the published artist credits require another rule.