tidyr::pivot_longer() / tidyr::pivot_wider()
pivot_longer(data, cols, names_to = "name", values_to = "value") Returns:
tibble · Updated March 13, 2026 · Tidyverse tidyr reshape tidyverse pivot data-wrangling
pivot_longer() and pivot_wider() are tidyr functions for reshaping data between long and wide formats. They replace the older gather() and spread() functions with a more intuitive interface.
Syntax
pivot_longer(
data,
cols,
names_to = "name",
names_prefix = NULL,
names_sep = NULL,
names_pattern = NULL,
values_to = "value",
values_drop_na = FALSE,
...
)
pivot_wider(
data,
names_from,
values_from,
id_cols = NULL,
names_prefix = "",
names_sep = "_",
values_fill = NULL,
values_drop_na = FALSE
)
Parameters
pivot_longer()
| Parameter | Type | Default | Description |
|---|---|---|---|
data | tibble / data.frame | — | Input data frame |
cols | columns | — | Columns to pivot into longer format (use tidyselect) |
names_to | string | ”name” | Name of the column to store column names |
values_to | string | ”value” | Name of the column to store values |
names_prefix | string | NULL | Remove prefix from column names |
values_drop_na | logical | FALSE | Drop rows where values are NA |
pivot_wider()
| Parameter | Type | Default | Description |
|---|---|---|---|
data | tibble / data.frame | — | Input data frame |
names_from | column | — | Column containing names for new columns |
values_from | column | — | Column containing values for new columns |
values_fill | value | NULL | Value to use for missing combinations |
values_drop_na | logical | FALSE | Drop rows where values are NA |
Examples
Basic pivot_longer
Convert wide data to long format:
library(tidyr)
library(dplyr)
df <- data.frame(
id = 1:3,
score_2022 = c(85, 92, 78),
score_2023 = c(88, 95, 82),
score_2024 = c(90, 98, 85)
)
df |> pivot_longer(
cols = starts_with("score_"),
names_to = "year",
names_prefix = "score_",
values_to = "score"
)
# # A tibble: 9 × 3
# id year score
# <dbl> <chr> <dbl>
# 1 1 2022 85
# 2 1 2023 88
# 3 1 2024 90
# 4 2 2022 92
# 5 2 2023 95
# 6 2 2024 98
# 7 3 2022 78
# 8 3 2023 82
# 9 3 2024 85
Basic pivot_wider
Convert long data to wide format:
df_long <- data.frame(
id = c(1, 1, 2, 2),
year = c("2022", "2023", "2022", "2023"),
score = c(85, 88, 92, 95)
)
df_long |> pivot_wider(
names_from = year,
values_from = score
)
# # A tibble: 2 × 3
# id X2022 X2023
# <dbl> <dbl> <dbl>
# 1 1 85 88
# 2 2 92 95
Multiple value columns
Pivot multiple value columns simultaneously:
df <- data.frame(
id = 1:2,
treatment_a = c(10, 15),
treatment_b = c(20, 25),
control_a = c(8, 12),
control_b = c(18, 22)
)
df |> pivot_longer(
cols = -id,
names_to = c("group", "outcome"),
names_sep = "_"
)
# # A tibble: 8 × 4
# id group outcome
# <dbl> <chr> <dbl>
# 1 1 treatment 10
# 2 1 treatment 20
# 3 1 control 8
# 4 1 control 18
# 5 2 treatment 15
# 6 2 treatment 25
# 7 2 control 12
# 8 2 control 22
Common Patterns
Handling missing values with values_fill
Fill missing values when pivoting wider:
df <- data.frame(
id = c(1, 1, 2),
metric = c("a", "b", "a"),
value = c(10, 20, 30)
)
df |> pivot_wider(
names_from = metric,
values_from = value,
values_fill = 0
)
# # A tibble: 2 × 3
# id a b
# <dbl> <dbl> <dbl>
# 1 1 10 20
# 2 2 30 0
Using names_pattern for complex column names
Extract multiple pieces information from column names:
df <- data.frame(
id = 1:2,
result_q1_pre = c(85, 90),
result_q1_post = c(92, 95),
result_q2_pre = c(78, 82),
result_q2_post = c(88, 90)
)
df |> pivot_longer(
cols = -id,
names_to = c("question", "time"),
names_pattern = "result_(q\\d+)_(pre|post)"
)