Pandas How to Convert Wide to Long Format Easily
pandas.melt() to convert a wide DataFrame to long format by specifying the id_vars (columns to keep) and value_vars (columns to unpivot), like pd.melt(df, id_vars=['id'], value_vars=['A', 'B']).Examples
How to Think About It
Algorithm
Code
import pandas as pd df = pd.DataFrame({'id': [1, 2], 'A': [10, 20], 'B': [30, 40]}) long_df = pd.melt(df, id_vars=['id'], value_vars=['A', 'B'], var_name='variable', value_name='value') print(long_df)
Dry Run
Let's trace the example DataFrame through the melt function.
Original DataFrame
id: [1, 2], A: [10, 20], B: [30, 40]
Identify id_vars and value_vars
id_vars = ['id'], value_vars = ['A', 'B']
Melt operation
Rows created for each id and each variable in A and B with their values
| id | variable | value |
|---|---|---|
| 1 | A | 10 |
| 2 | A | 20 |
| 1 | B | 30 |
| 2 | B | 40 |
Why This Works
Step 1: Keep id_vars fixed
The columns in id_vars stay the same for each row in the long format.
Step 2: Unpivot value_vars
Columns in value_vars are turned into two columns: one for the variable name and one for its value.
Step 3: Create longer DataFrame
This reshaping increases rows but reduces columns, making data easier to analyze in some cases.
Alternative Approaches
import pandas as pd df = pd.DataFrame({'id': [1, 2], 'A': [10, 20], 'B': [30, 40]}) long_df = df.set_index('id').stack().reset_index(name='value').rename(columns={'level_1': 'variable'}) print(long_df)
import pandas as pd df = pd.DataFrame({'id': [1, 2], 'A_2019': [10, 20], 'A_2020': [15, 25]}) long_df = pd.wide_to_long(df, stubnames='A', i='id', j='year', sep='_').reset_index() print(long_df)
Complexity: O(n*m) time, O(n*m) space
Time Complexity
The melt operation processes each cell in the value_vars columns, so time grows with number of rows (n) times number of columns to unpivot (m).
Space Complexity
The output DataFrame has more rows, roughly n*m, so space grows accordingly.
Which Approach is Fastest?
pd.melt is optimized and usually faster and simpler than stack or wide_to_long for general wide-to-long reshaping.
| Approach | Time | Space | Best For |
|---|---|---|---|
| pd.melt | O(n*m) | O(n*m) | General wide to long conversion |
| stack | O(n*m) | O(n*m) | When index setting is convenient |
| wide_to_long | O(n*m) | O(n*m) | Columns with common prefixes/suffixes |
pd.melt() with id_vars to keep columns fixed and value_vars to unpivot others.id_vars causes all columns to be unpivoted, losing important identifiers.