Skip to main content
MahiDev — Learn. Build. Become AI-ready.

Lesson 02

Tidy Data for Seaborn

See why Seaborn wants long-form data, one row per observation and one column per variable, and reshape wide tables with pandas melt before you plot.

Intermediate25 min
Tidy Data for Seaborn hero Module 26 Lesson 2Tidy Data for Seaborn hero Module 26 Lesson 2

Seaborn works best with long-form, or tidy, data: each row is one observation and each column is one variable. Spreadsheets are often wide instead, with one column per group. A single melt call turns wide into long, and then every column is something you can hand to x, y, or hue.

A wide table with one column per track melted into a long table with a track columnA wide table with one column per track melted into a long table with a track column

Wide and long

This table records practice minutes per week, with a column for each track. It is easy to read, but the track name lives in the column headers, so there is no track column to colour by.

python
import pandas as pd

wide = pd.DataFrame({
    "week": [1, 2, 3],
    "Python": [40, 55, 62],
    "Data": [35, 48, 58],
    "Web": [50, 46, 60],
})
print(wide)
print(list(wide.columns))

Output:

text
   week  Python  Data  Web
0     1      40    35   50
1     2      55    48   46
2     3      62    58   60
['week', 'Python', 'Data', 'Web']

melt turns columns into rows

melt keeps the id_vars columns as they are and stacks the others. var_name names the new column that holds the old headers, and value_name names the column that holds the numbers. Three rows by three tracks become nine rows.

python
import pandas as pd

wide = pd.DataFrame({
    "week": [1, 2, 3],
    "Python": [40, 55, 62],
    "Data": [35, 48, 58],
    "Web": [50, 46, 60],
})
long = wide.melt(id_vars="week", var_name="track", value_name="minutes")
print(long)
print(long.shape)

Output:

text
   week   track  minutes
0     1  Python       40
1     2  Python       55
2     3  Python       62
3     1    Data       35
4     2    Data       48
5     3    Data       58
6     1     Web       50
7     2     Web       46
8     3     Web       60
(9, 3)

Plot the long table

Now each idea has its own column, so the chart is just a matter of naming them: week on x, minutes on y, and track as the colour.

python
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

wide = pd.DataFrame({
    "week": [1, 2, 3],
    "Python": [40, 55, 62],
    "Data": [35, 48, 58],
    "Web": [50, 46, 60],
})
long = wide.melt(id_vars="week", var_name="track", value_name="minutes")

sns.lineplot(data=long, x="week", y="minutes", hue="track", marker="o")
plt.show()

print(long.groupby("track")["minutes"].max())

Output:

text
track
Data      58
Python    62
Web       60
Name: minutes, dtype: int64

Wide data works, with less control

Pass a wide table on its own and Seaborn draws one line per numeric column, using the index as x. It is quick, but you cannot choose which column drives colour or style, and the legend has no title.

python
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

wide = pd.DataFrame({
    "week": [1, 2, 3],
    "Python": [40, 55, 62],
    "Data": [35, 48, 58],
    "Web": [50, 46, 60],
}).set_index("week")

ax = sns.lineplot(data=wide)
plt.show()

print([text.get_text() for text in ax.get_legend().get_texts()])
print(repr(ax.get_legend().get_title().get_text()))

Output:

text
['Python', 'Data', 'Web']
''

Back to wide with pivot

Some charts, such as heatmaps, want a grid instead. pivot is the opposite of melt: one column becomes the index, one becomes the headers, and one fills the cells.

python
import pandas as pd

long = pd.DataFrame({
    "week": [1, 2, 1, 2],
    "track": ["Python", "Python", "Data", "Data"],
    "minutes": [40, 55, 35, 48],
})
grid = long.pivot(index="week", columns="track", values="minutes")
print(grid)

Output:

text
track  Data  Python
week               
1        35      40
2        48      55

Key takeaways

  • Long-form data has one row per observation and one column per variable

  • melt stacks wide columns into rows; id_vars stay as they are

  • Once data is long, every column can drive x, y, or hue

  • pivot turns long data back into a grid, which heatmaps need

  • Next: Scatter Plots with hue, size, and style

  • Previous: What Is Seaborn

Loading playground…

Check your understanding

Tidy Data for Seaborn Quiz

What is long-form data?

1 / 10