Reshape, pivot, melt, and unpivot your data between long (tidy) and wide formats. Upload a CSV or Excel file, or paste your data directly. Equivalent to pandas melt()/pivot()/pivot_table(), tidyr pivot_longer()/pivot_wider(), and SQL PIVOT/UNPIVOT.
Not sure about data formats? Check out the examples in the Learn More section below. Save your data when you are done because this tool does not save your data anywhere.
Try it out with sample data:
Each row is a single observation. Variables are stacked into key-value pairs. Also known as "melted" or "unpivoted" data.
ID,Year,Measurement,Value 1,2020,Temperature,18.5 1,2020,Humidity,30 1,2021,Temperature,19.0 1,2021,Humidity,32 2,2020,Temperature,17.0 2,2020,Humidity,40 2,2021,Temperature,16.5 2,2021,Humidity,42
Each variable gets its own column. More compact and easier to read. Also known as "pivoted" or "spread" data.
ID,Year,Temperature,Humidity 1,2020,18.5,30 1,2021,19.0,32 2,2020,17.0,40 2,2021,16.5,42
| ID | Year | Measurement | Value |
|---|---|---|---|
| 1 | 2020 | Temperature | 18.5 |
| 1 | 2020 | Humidity | 30 |
| 1 | 2021 | Temperature | 19 |
| 1 | 2021 | Humidity | 32 |
| 2 | 2020 | Temperature | 17 |
| 2 | 2020 | Humidity | 40 |
| 2 | 2021 | Temperature | 16.5 |
| 2 | 2021 | Humidity | 42 |
Select these columns:
ID Columns:
Value Columns:
| ID | Year | Temperature | Humidity |
|---|---|---|---|
| 1 | 2020 | 18.5 | 30 |
| 1 | 2021 | 19 | 32 |
| 2 | 2020 | 17 | 40 |
| 2 | 2021 | 16.5 | 42 |
| ID | Year | Temperature | Humidity |
|---|---|---|---|
| 1 | 2020 | 18.5 | 30 |
| 1 | 2021 | 19 | 32 |
| 2 | 2020 | 17 | 40 |
| 2 | 2021 | 16.5 | 42 |
Select these columns:
ID Columns:
Value Columns:
This will create two new columns: "Measurement" (containing "Temperature" or "Humidity") and "Value" (containing the corresponding numbers)
| ID | Year | Measurement | Value |
|---|---|---|---|
| 1 | 2020 | Temperature | 18.5 |
| 1 | 2020 | Humidity | 30 |
| 1 | 2021 | Temperature | 19 |
| 1 | 2021 | Humidity | 32 |
| 2 | 2020 | Temperature | 17 |
| 2 | 2020 | Humidity | 40 |
| 2 | 2021 | Temperature | 16.5 |
| 2 | 2021 | Humidity | 42 |
Reshape data using pandas — the most popular Python library for data manipulation
import pandas as pd
# create wide format data
wide_df = pd.DataFrame({
'ID': [1, 1, 2, 2],
'Year': [2020, 2021, 2020, 2021],
'Temperature': [18.5, 19.0, 17.0, 16.5],
'Humidity': [30, 32, 40, 42]
})
print(wide_df)
# Convert wide to long format (melt / unpivot)
long_df = pd.melt(
wide_df,
id_vars=['ID', 'Year'],
value_vars=['Temperature', 'Humidity'],
var_name='Measurement',
value_name='Value'
)
print(long_df)
# Convert back to wide format (pivot)
wide_df = long_df.pivot_table(
index=['ID', 'Year'],
columns='Measurement',
values='Value'
).reset_index()
print(wide_df)Reshape data using tidyr from the tidyverse — the modern replacement for reshape2
library(tidyverse)
# wide format data
wide_data <- data.frame(
ID = c(1, 1, 2, 2),
Year = c(2020, 2021, 2020, 2021),
Temperature = c(18.5, 19.0, 17.0, 16.5),
Humidity = c(30, 32, 40, 42)
)
print(wide_data)
# Convert wide to long format (pivot_longer / melt)
long_data <- wide_data |>
pivot_longer(
cols = c(Temperature, Humidity),
names_to = "Measurement",
values_to = "Value"
)
print(long_data)
# Convert long back to wide format (pivot_wider / spread)
wide_data <- long_data |>
pivot_wider(
id_cols = c(ID, Year),
names_from = Measurement,
values_from = Value
)
print(wide_data)Reshape data directly in your database using SQL PIVOT/UNPIVOT or conditional aggregation
-- Long to Wide: PIVOT (SQL Server / Oracle)
SELECT ID, Year, Temperature, Humidity
FROM measurements
PIVOT (
MAX(Value)
FOR Measurement IN (Temperature, Humidity)
) AS pivoted;-- Long to Wide: conditional aggregation (works in all databases)
SELECT
ID,
Year,
MAX(CASE WHEN Measurement = 'Temperature' THEN Value END) AS Temperature,
MAX(CASE WHEN Measurement = 'Humidity' THEN Value END) AS Humidity
FROM measurements
GROUP BY ID, Year
ORDER BY ID, Year;-- Wide to Long: UNPIVOT (SQL Server / Oracle)
SELECT ID, Year, Measurement, Value
FROM weather_data
UNPIVOT (
Value FOR Measurement IN (Temperature, Humidity)
) AS unpivoted;-- Wide to Long: UNION ALL (works in all databases)
SELECT ID, Year, 'Temperature' AS Measurement, Temperature AS Value
FROM weather_data
UNION ALL
SELECT ID, Year, 'Humidity' AS Measurement, Humidity AS Value
FROM weather_data
ORDER BY ID, Year, Measurement;Reshape data using built-in spreadsheet features without any code
=ARRAYFORMULA({
{"ID","Year","Measurement","Value";
FLATTEN(IF({1,1},A2:A5)),
FLATTEN(IF({1,1},B2:B5)),
FLATTEN(IF(ROW(C1:D1),C1:D1)),
FLATTEN(C2:D5)}
})Reshape, pivot, melt, and unpivot your data between long (tidy) and wide formats. Upload a CSV or Excel file, or paste your data directly. Equivalent to pandas melt()/pivot()/pivot_table(), tidyr pivot_longer()/pivot_wider(), and SQL PIVOT/UNPIVOT.
Not sure about data formats? Check out the examples in the Learn More section below. Save your data when you are done because this tool does not save your data anywhere.
Try it out with sample data:
Each row is a single observation. Variables are stacked into key-value pairs. Also known as "melted" or "unpivoted" data.
ID,Year,Measurement,Value 1,2020,Temperature,18.5 1,2020,Humidity,30 1,2021,Temperature,19.0 1,2021,Humidity,32 2,2020,Temperature,17.0 2,2020,Humidity,40 2,2021,Temperature,16.5 2,2021,Humidity,42
Each variable gets its own column. More compact and easier to read. Also known as "pivoted" or "spread" data.
ID,Year,Temperature,Humidity 1,2020,18.5,30 1,2021,19.0,32 2,2020,17.0,40 2,2021,16.5,42
| ID | Year | Measurement | Value |
|---|---|---|---|
| 1 | 2020 | Temperature | 18.5 |
| 1 | 2020 | Humidity | 30 |
| 1 | 2021 | Temperature | 19 |
| 1 | 2021 | Humidity | 32 |
| 2 | 2020 | Temperature | 17 |
| 2 | 2020 | Humidity | 40 |
| 2 | 2021 | Temperature | 16.5 |
| 2 | 2021 | Humidity | 42 |
Select these columns:
ID Columns:
Value Columns:
| ID | Year | Temperature | Humidity |
|---|---|---|---|
| 1 | 2020 | 18.5 | 30 |
| 1 | 2021 | 19 | 32 |
| 2 | 2020 | 17 | 40 |
| 2 | 2021 | 16.5 | 42 |
| ID | Year | Temperature | Humidity |
|---|---|---|---|
| 1 | 2020 | 18.5 | 30 |
| 1 | 2021 | 19 | 32 |
| 2 | 2020 | 17 | 40 |
| 2 | 2021 | 16.5 | 42 |
Select these columns:
ID Columns:
Value Columns:
This will create two new columns: "Measurement" (containing "Temperature" or "Humidity") and "Value" (containing the corresponding numbers)
| ID | Year | Measurement | Value |
|---|---|---|---|
| 1 | 2020 | Temperature | 18.5 |
| 1 | 2020 | Humidity | 30 |
| 1 | 2021 | Temperature | 19 |
| 1 | 2021 | Humidity | 32 |
| 2 | 2020 | Temperature | 17 |
| 2 | 2020 | Humidity | 40 |
| 2 | 2021 | Temperature | 16.5 |
| 2 | 2021 | Humidity | 42 |
Reshape data using pandas — the most popular Python library for data manipulation
import pandas as pd
# create wide format data
wide_df = pd.DataFrame({
'ID': [1, 1, 2, 2],
'Year': [2020, 2021, 2020, 2021],
'Temperature': [18.5, 19.0, 17.0, 16.5],
'Humidity': [30, 32, 40, 42]
})
print(wide_df)
# Convert wide to long format (melt / unpivot)
long_df = pd.melt(
wide_df,
id_vars=['ID', 'Year'],
value_vars=['Temperature', 'Humidity'],
var_name='Measurement',
value_name='Value'
)
print(long_df)
# Convert back to wide format (pivot)
wide_df = long_df.pivot_table(
index=['ID', 'Year'],
columns='Measurement',
values='Value'
).reset_index()
print(wide_df)Reshape data using tidyr from the tidyverse — the modern replacement for reshape2
library(tidyverse)
# wide format data
wide_data <- data.frame(
ID = c(1, 1, 2, 2),
Year = c(2020, 2021, 2020, 2021),
Temperature = c(18.5, 19.0, 17.0, 16.5),
Humidity = c(30, 32, 40, 42)
)
print(wide_data)
# Convert wide to long format (pivot_longer / melt)
long_data <- wide_data |>
pivot_longer(
cols = c(Temperature, Humidity),
names_to = "Measurement",
values_to = "Value"
)
print(long_data)
# Convert long back to wide format (pivot_wider / spread)
wide_data <- long_data |>
pivot_wider(
id_cols = c(ID, Year),
names_from = Measurement,
values_from = Value
)
print(wide_data)Reshape data directly in your database using SQL PIVOT/UNPIVOT or conditional aggregation
-- Long to Wide: PIVOT (SQL Server / Oracle)
SELECT ID, Year, Temperature, Humidity
FROM measurements
PIVOT (
MAX(Value)
FOR Measurement IN (Temperature, Humidity)
) AS pivoted;-- Long to Wide: conditional aggregation (works in all databases)
SELECT
ID,
Year,
MAX(CASE WHEN Measurement = 'Temperature' THEN Value END) AS Temperature,
MAX(CASE WHEN Measurement = 'Humidity' THEN Value END) AS Humidity
FROM measurements
GROUP BY ID, Year
ORDER BY ID, Year;-- Wide to Long: UNPIVOT (SQL Server / Oracle)
SELECT ID, Year, Measurement, Value
FROM weather_data
UNPIVOT (
Value FOR Measurement IN (Temperature, Humidity)
) AS unpivoted;-- Wide to Long: UNION ALL (works in all databases)
SELECT ID, Year, 'Temperature' AS Measurement, Temperature AS Value
FROM weather_data
UNION ALL
SELECT ID, Year, 'Humidity' AS Measurement, Humidity AS Value
FROM weather_data
ORDER BY ID, Year, Measurement;Reshape data using built-in spreadsheet features without any code
=ARRAYFORMULA({
{"ID","Year","Measurement","Value";
FLATTEN(IF({1,1},A2:A5)),
FLATTEN(IF({1,1},B2:B5)),
FLATTEN(IF(ROW(C1:D1),C1:D1)),
FLATTEN(C2:D5)}
})