Tidy Data with tidyr
Prerequisites: dplyr: mutate, summarise, and group_by
Tidy data follows three rules:
- Each variable is a column.
- Each observation is a row.
- Each value is a cell.
Most tidyverse tools expect tidy data. Real data often isn't: a common example is one column per year. tidyr reshapes it.
pivot_longer — wide to long
library(tidyr)
sales <- tibble::tibble(
region = c("North", "South"),
`2023` = c(120, 95),
`2024` = c(135, 110)
)
sales
sales_long <- sales |>
pivot_longer(cols = c(`2023`, `2024`), names_to = "year", values_to = "sales")
sales_long
# A tibble: 2 × 3
region `2023` `2024`
<chr> <dbl> <dbl>
1 North 120 135
2 South 95 110
# A tibble: 4 × 3
region year sales
<chr> <chr> <dbl>
1 North 2023 120
2 North 2024 135
3 South 2023 95
4 South 2024 110
"Year" is a variable, so it should be one column — now it is. The long
form is what ggplot2 and dplyr's group_by work best with. (Column
names that start with a number need backticks.)
pivot_wider — long to wide
The reverse, useful for presenting a summary table:
library(tidyr)
long <- tibble::tibble(
region = c("North", "North", "South", "South"),
year = c("2023", "2024", "2023", "2024"),
sales = c(120, 135, 95, 110)
)
long |> pivot_wider(names_from = year, values_from = sales)
# A tibble: 2 × 3
region `2023` `2024`
<chr> <dbl> <dbl>
1 North 120 135
2 South 95 110
Splitting and handling missing values
library(tidyr)
people <- tibble::tibble(full_name = c("Ada Lovelace", "Alan Turing"), score = c(90, NA))
people |> separate_wider_delim(full_name, delim = " ", names = c("first", "last"))
people |> replace_na(list(score = 0))
people |> drop_na(score)
# A tibble: 2 × 3
first last score
<chr> <chr> <dbl>
1 Ada Lovelace 90
2 Alan Turing NA
# A tibble: 2 × 2
full_name score
<chr> <dbl>
1 Ada Lovelace 90
2 Alan Turing 0
# A tibble: 1 × 2
full_name score
<chr> <dbl>
1 Ada Lovelace 90
Common mistakes
- Keeping data wide and then struggling to plot or summarise it. If a piece of information (a year, a category) is stored in column names, pivot it longer first.