Datasets
Descriptions of the datasets used in class.
US Billboard Hot 100 lyrics, 1973–2023
Collected by Foramitti et al. (2025) to study long-term trends in stress, negativity, and simplicity in popular music lyrics and how societal crises affect those.
Observations. 266,087 entries, one per song per chart week, from January 6, 1973 to December 30, 2023 (51 years)
Variables.
| Name | Description |
|---|---|
Date |
Chart week (weekly, 1973-01-06 to 2023-12-30) |
Rank |
Position on that week’s Billboard Hot 100 chart (1–100) |
Song Title |
Song title |
Artist |
Performing artist |
Lyrics_Sentiment |
VADER compound sentiment score of the lyrics, from −1 (most negative) to +1 (most positive) |
Stress |
Frequency of stress-related words in the lyrics, from LIWC |
Lyrics_Sentiment and Stress are missing for about 13,600 rows: these correspond to songs excluded from the analysis for being instrumental, having incorrect scraping returns, or having non-English lyrics.
How it was collected. The Billboard Hot 100 chart was scraped weekly with BeautifulSoup; lyrics for each charted song were retrieved via the Lyrics.ovh and Genius APIs, cleaned of metadata/inserts (e.g. “[Chorus]”), and filtered down to English-language lyrics only. Sentiment was scored with the VADER sentiment analysis tool, and stress-related language with the LIWC tool; each song’s score is the average across all its lyrics’ words.
Links.
- Data repository (OSF): https://osf.io/2k7ut/
- Article: Foramitti et al. (2025), Societal crises disrupt long-term increases in stress, negativity, and simplicity in US Billboard song lyrics from 1973 to 2023, Scientific Reports
Loading the data in pandas. Download lyrics_OSF.csv from the OSF repository above, then:
import pandas as pd
df = pd.read_csv("lyrics_OSF.csv", index_col=0, parse_dates=["Date"])
df.head()Spotify songs
Audio features and metadata for ~32,800 Spotify tracks across 6 playlist genres, compiled by researcher Kaylin Pavlik using Spotify’s API (via the R spotifyr package) to explore genre classification patterns, and distributed through the TidyTuesday project.
Observations. 32,833 rows, one per song per playlist it appears in (28,356 unique tracks; a song can appear in multiple playlists, hence multiple rows). Album release dates range from 1957 to early 2020.
Variables.
| Name | Description |
|---|---|
track_id, track_name, track_artist |
Track identifier, title, and performing artist |
track_popularity |
Popularity score (0–100) |
track_album_id, track_album_name, track_album_release_date |
Album identifier, title, and release date |
playlist_name, playlist_id |
Playlist title and identifier |
playlist_genre, playlist_subgenre |
Primary genre (edm, latin, pop, r&b, rap, rock) and subgenre |
danceability, energy, key, loudness, mode, speechiness, acousticness, instrumentalness, liveness, valence, tempo |
Spotify audio features, mostly on a 0–1 scale (see Spotify’s audio features docs) |
duration_ms |
Track length in milliseconds |
Links.
- Data source (TidyTuesday): https://github.com/rfordatascience/tidytuesday/blob/main/data/2020/2020-01-21/readme.md
- Related article: Kaylin Pavlik, “Understanding audio features and exploring genre classification”
- R package used to collect the data:
spotifyr
Loading the data in pandas. Load it directly from TidyTuesday’s raw CSV, no download needed:
import pandas as pd
url = "https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2020/2020-01-21/spotify_songs.csv"
df = pd.read_csv(url)
df.head()Pokémon
Information on 949 Pokémon (English and Brazilian Portuguese), compiled from the {pokemon} R package by William Amorim and distributed through the TidyTuesday project (2025-04-01 dataset, curated by Frank Hull).
Observations. 949 rows, one per Pokémon.
Variables.
| Name | Description |
|---|---|
id, pokemon, species_id |
Unique ID, name, and species ID |
height, weight |
Height and weight |
base_experience |
Base experience |
type_1, type_2 |
Primary and secondary type |
hp, attack, defense, special_attack, special_defense, speed |
Battle stats |
color_1, color_2, color_f |
Primary, secondary, and final color |
egg_group_1, egg_group_2 |
Primary and secondary egg group |
url_icon, url_image |
Icon and image URLs (url_icon is missing its leading “https:”) |
generation_id |
Generation ID |
Links.
- Data source (TidyTuesday): https://github.com/rfordatascience/tidytuesday/blob/main/data/2025/2025-04-01/readme.md
- Related blog post: Hanah Shih, “Pokemon Data Visualization and Analysis with R”
- R package used to collect the data:
pokemon
Loading the data in pandas. Load it directly from TidyTuesday’s raw CSV:
import pandas as pd
url = "https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-04-01/pokemon_df.csv"
df = pd.read_csv(url)
df.head()Pixar films
Release, runtime, and critical-reception data for Pixar’s feature films, from the {pixarfilms} R package by Eric Leung, distributed through the TidyTuesday project.
Observations. 27 rows, one per Pixar film (release ratings are missing for the most recent films, not yet scored by all outlets). The upstream data is missing the title for film #27 (Elemental, released 2023-06-16); the bundled copy in the dashboard fills it in.
Variables.
| Name | Description |
|---|---|
number |
Order of release |
film |
Film title |
release_date |
Premiere date |
run_time |
Film length in minutes |
film_rating |
MPA film rating |
rotten_tomatoes |
Rotten Tomatoes score (0–100) |
metacritic |
Metacritic score (0–100) |
cinema_score |
CinemaScore letter grade (A–F) |
critics_choice |
Critics’ Choice Movie Awards score (0–100) |
Links.
- Data source (TidyTuesday): https://github.com/rfordatascience/tidytuesday/blob/main/data/2025/2025-03-11/readme.md
Loading the data in pandas.
import pandas as pd
films = pd.read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-03-11/pixar_films.csv")
response = pd.read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-03-11/public_response.csv")
df = films.merge(response, on="film", how="left")
df.head()Titanic passengers and crew
This is a well-known dataset about the passengers and crew aboard the Titanic’s 1912 maiden voyage. Refer to Dawson (1995) for information on how this dataset was collected.
Observations. 2,201 rows, one per person aboard.
Variables.
| Name | Description |
|---|---|
Class |
Ticket class (1st, 2nd, 3rd) or Crew |
Sex |
Male or Female |
Age |
Child or Adult |
Survived |
No or Yes |
Loading the data in pandas.
import pandas as pd
url = "https://vincentarelbundock.github.io/Rdatasets/csv/datasets/Titanic.csv"
counts = pd.read_csv(url, index_col=0)
df = counts.loc[counts.index.repeat(counts["Freq"])].drop(columns="Freq").reset_index(drop=True)
df.head()Old Faithful geyser
Continuous measurements of eruptions from the Old Faithful geyser in Yellowstone National Park, Wyoming, from August 1 to August 15, 1985, collected by Azzalini and Bowman (1990) and distributed as the geyser dataset in the R MASS package (Ripley and Venables 2009).
Observations. 299 rows, one per eruption. Some nocturnal durations were only recorded as “short”, “medium”, or “long” and are coded here as 2, 3, or 4 minutes.
Variables.
| Name | Description |
|---|---|
duration |
Eruption time, in minutes |
waiting |
Waiting time before this eruption, in minutes |
Loading the data in pandas.
import pandas as pd
url = "https://vincentarelbundock.github.io/Rdatasets/csv/MASS/geyser.csv"
df = pd.read_csv(url, index_col=0)
df.head()Breakfast cereals
Nutritional and shelf-placement information for 77 US breakfast cereals, based on the F&DA food label, collected for the American Statistical Association’s 1993 Statistical Graphics Exposition (“Serial Correlation or Cereal Correlation??”).
Observations. 77 rows, one per cereal.
Variables.
| Name | Description |
|---|---|
name |
Cereal name |
mfr |
Manufacturer: A = American Home Food Products, G = General Mills, K = Kelloggs, N = Nabisco, P = Post, Q = Quaker Oats, R = Ralston Purina |
type |
cold or hot |
calories |
Calories per serving |
protein |
Protein (g) |
fat |
Fat (g) |
sodium |
Sodium (mg) |
fiber |
Dietary fiber (g) |
carbo |
Complex carbohydrates (g) |
sugars |
Sugars (g) |
shelf |
Display shelf (1, 2, or 3, counting from the floor) |
potass |
Potassium (mg) |
vitamins |
Vitamins & minerals (0 = none added, 25 = enriched, 100 = 100% FDA recommended) |
weight |
Weight of one serving (oz) |
cups |
Cups per serving |
None of the cereals had any cholesterol. Missing values (coded -1 in the original data) are encoded as NaN.
Links.
- Original call for data / documentation: https://community.amstat.org/jointscsg-section/dataexpo/dataexpo1993
- Mirrored (with the
ratingcolumn added later) in the Rcandiscpackage’scerealdataset
Loading the data in pandas.
import pandas as pd
import numpy as np
cols = ["name", "mfr", "type", "calories", "protein", "fat", "sodium", "fiber",
"carbo", "sugars", "shelf", "potass", "vitamins", "weight", "cups"]
df = pd.read_csv(
"https://raw.githubusercontent.com/friendly/candisc/master/data-raw/cereal/cereal.dat",
sep=r"\s+", names=cols, na_values=-1,
)
df["name"] = df["name"].str.replace("_", " ")
df["type"] = df["type"].map({"C": "cold", "H": "hot"})
df.head()Galton’s family heights
Heights of parents and their adult children, recorded by Francis Galton and analysed in Galton (1886) to demonstrate regression toward the mean. This is Galton’s original notebook data (205 families, 962 adult children — 486 sons and 476 daughters), recovered and transcribed from University College London’s archives; after excluding entries recorded non-numerically (e.g. “tall”, “medium”, “short”), 934 children (481 sons, 453 daughters) remain.
Observations. 934 rows, one per child.
Variables.
| Name | Description |
|---|---|
family |
Family ID |
father |
Father’s height (in) |
mother |
Mother’s height (in) |
midparentHeight |
Mid-parent height, (father + 1.08 * mother) / 21 |
children |
Number of children in this family |
childNum |
This child’s number within the family (children are listed tallest to shortest, boys before girls) |
gender |
male or female |
childHeight |
Child’s height (in) |
Links.
- Article: Galton (1886), Regression Towards Mediocrity in Hereditary Stature, Journal of the Anthropological Institute of Great Britain and Ireland
Loading the data in pandas.
import pandas as pd
url = "https://vincentarelbundock.github.io/Rdatasets/csv/HistData/GaltonFamilies.csv"
df = pd.read_csv(url, index_col=0)
df.head()Cavendish’s determinations of the density of the Earth
Henry Cavendish’s 1798 experiments to determine the mean density of the Earth (relative to water) were used to indirectly calculate the gravitational constant in Newton’s law of gravitation. Distributed as the Cavendish dataset in the R HistData package (Friendly 2021).
Observations. 29 rows, one per determination.
Variables.
| Name | Description |
|---|---|
density |
Cavendish’s 29 measurements, as he originally recorded and analysed them |
density2 |
Same as density, but with the third value corrected from 4.88 to 5.88 — Cavendish himself treated 4.88 as a recording error and analysed it as 5.88 |
The modern accepted value is 5.517.
Links.
- Article: Cavendish, H. (1798), Experiments to Determine the Density of the Earth, Philosophical Transactions of the Royal Society of London, 88.
- Analysis: Stephen M. Stigler (1977), Do robust estimators work with real data?, Annals of Statistics, 5.
Loading the data in pandas.
import pandas as pd
url = "https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Cavendish.csv"
df = pd.read_csv(url, index_col=0)
df.head()Shakespeare’s Complete Works
The full text of Shakespeare’s plays and sonnets, used to study word prediction through n-gram statistics and to introduce probability concepts.
Observations. 970,821 words extracted from the public-domain Project Gutenberg edition of Shakespeare’s Complete Works (file #100). Stage directions and front matter removed.
Variables.
| Name | Description |
|---|---|
bigrams |
Two consecutive words (context, next_word) and their count across the corpus (368,664 unique bigrams) |
trigrams |
Three consecutive words (context_1, context_2, next_word) and their count (794,095 unique trigrams) |
These are derived files, not raw Shakespeare text. See the probability chapter for examples of how to use them to compute word-prediction probabilities: P(next word = w | context) = count(context → w) / count(context → anything).
Links.
- Source (Project Gutenberg): https://www.gutenberg.org/ebooks/100
- Derived bigrams and trigrams: stored in
course-notes/assets/shakespeare/bigrams.csvandcourse-notes/assets/shakespeare/trigrams.csv
Loading the data in pandas.
import pandas as pd
bigrams = pd.read_csv("course-notes/assets/shakespeare/bigrams.csv")
trigrams = pd.read_csv("course-notes/assets/shakespeare/trigrams.csv")
bigrams.head()References
Footnotes
The 1.08 factor is the author’s attempt to rescale mothers’ heights to compensate for the average sex difference.↩︎