How to convert wide format to long format in R

· 2 min read · Updated March 14, 2026 · beginner
r reshaping tidyr data.table tidyverse

Converting wide data to long format is a common data transformation. Here is how to do it with the major approaches.

With tidyr (tidyverse)

The tidyverse approach uses pivot_longer():

library(tidyr)

# Simple case: specify columns to gather
long_df <- wide_df %>%
  pivot_longer(cols = c(q1, q2, q3, q4),
               names_to = "quarter",
               values_to = "sales")

The cols argument identifies which columns become values. Use column selection helpers:

library(tidyr)
library(dplyr)

# Select all columns from q1 to q4
long_df <- wide_df %>%
  pivot_longer(cols = q1:q4,
               names_to = "quarter",
               values_to = "sales")

# Select columns by pattern
long_df <- wide_df %>%
  pivot_longer(cols = starts_with("q"),
               names_to = "quarter",
               values_to = "sales")

With data.table

The data.table package is extremely fast for large data sets:

library(data.table)

dt <- as.data.table(wide_df)

# Melt from wide to long
long_dt <- melt(dt,
                id.vars = "id",
                measure.vars = c("q1", "q2", "q3", "q4"),
                variable.name = "quarter",
                value.name = "sales")

Use patterns for flexible column selection:

long_dt <- melt(dt,
                id.vars = "id",
                measure.vars = patterns("^q"),
                variable.name = "quarter",
                value.name = "sales")

With base R

Base R can reshape with reshape():

# Wide to long using base reshape()
long_df <- reshape(wide_df,
                   direction = "long",
                   varying = list(c("q1", "q2", "q3", "q4")),
                   v.names = "sales",
                   timevar = "quarter",
                   times = c("q1", "q2", "q3", "q4"))

This is more verbose but works without any packages.

Common Options


Optiontidyrdata.tablePurpose
ID columnsid.varsid.varsColumns to keep as identifiers
Value columnscolsmeasure.varsColumns to reshape
Names outputnames_tovariable.nameName for column with old column names
Values outputvalues_tovalue.nameName for column with cell values

Handling Multiple Value Columns

When you have multiple value columns (e.g., revenue and profit for each quarter):

library(tidyr)

long_df <- wide_df %>%
  pivot_longer(cols = c(revenue_q1, revenue_q2, profit_q1, profit_q2),
               names_to = c(".value", "quarter"),
               names_sep = "_")

This creates separate columns for revenue and profit.

See Also