I’m currently learning about data visualization using seaborn, and I came across a problem that I couldn’t find a solution to.
JavaScript
x
5
1
import pandas as pd
2
import matplotlib.pyplot as plt
3
import seaborn as sns
4
%matplotlib inline
5
So I have this data
index | col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 |
---|---|---|---|---|---|---|---|---|
1990 | 0 | 4 | 7 | 3 | 7 | 0 | 6 | 6 |
1991 | 1 | 7 | 5 | 0 | 8 | 1 | 8 | 4 |
1992 | 0 | 5 | 0 | 1 | 9 | 1 | 7 | 2 |
1993 | 2 | 7 | 0 | 0 | 6 | 1 | 2 | 7 |
1994 | 4 | 1 | 5 | 5 | 8 | 1 | 6 | 3 |
1995 | 7 | 0 | 6 | 4 | 8 | 0 | 5 | 7 |
1996 | 5 | 1 | 1 | 4 | 6 | 1 | 7 | 4 |
1997 | 0 | 4 | 7 | 5 | 5 | 1 | 8 | 5 |
1998 | 1 | 3 | 7 | 0 | 7 | 0 | 7 | 1 |
1999 | 5 | 7 | 1 | 1 | 6 | 0 | 8 | 5 |
2000 | 3 | 8 | 5 | 0 | 3 | 0 | 6 | 3 |
2001 | 6 | 0 | 4 | 1 | 7 | 1 | 2 | 7 |
I want to make barplots/histplots with col1, col2 .. col8 as one column and 1990 values as one column so like 1990;
col? | val |
---|---|
col1 | 0 |
col2 | 4 |
col3 | 7 |
col4 | 3 |
col5 | 7 |
col6 | 0 |
col7 | 6 |
col8 | 6 |
and plot them for each year from 1990 to 2001.
JavaScript
1
3
1
g = sns.FacetGrid(df, col=df.index.value_counts())
2
g.map(sns.histplot, df.columns)
3
This is the code that I’ve written I looked at facetgrid but could get it working for my case, any feedback is appreciated.
Advertisement
Answer
Imports and Test DataFrame
- Tested with
pandas 1.3.0
,matplotlib 3.4.2
, andseaborn 0.11.1
JavaScript
1
15
15
1
import pandas as pd
2
import seaborn as sns
3
4
# sample dataframe
5
data = {1990: {'col1': 0, 'col2': 4, 'col3': 7, 'col4': 3, 'col5': 7, 'col6': 0, 'col7': 6, 'col8': 6}, 1991: {'col1': 1, 'col2': 7, 'col3': 5, 'col4': 0, 'col5': 8, 'col6': 1, 'col7': 8, 'col8': 4}, 1992: {'col1': 0, 'col2': 5, 'col3': 0, 'col4': 1, 'col5': 9, 'col6': 1, 'col7': 7, 'col8': 2}, 1993: {'col1': 2, 'col2': 7, 'col3': 0, 'col4': 0, 'col5': 6, 'col6': 1, 'col7': 2, 'col8': 7}, 1994: {'col1': 4, 'col2': 1, 'col3': 5, 'col4': 5, 'col5': 8, 'col6': 1, 'col7': 6, 'col8': 3}, 1995: {'col1': 7, 'col2': 0, 'col3': 6, 'col4': 4, 'col5': 8, 'col6': 0, 'col7': 5, 'col8': 7}, 1996: {'col1': 5, 'col2': 1, 'col3': 1, 'col4': 4, 'col5': 6, 'col6': 1, 'col7': 7, 'col8': 4}, 1997: {'col1': 0, 'col2': 4, 'col3': 7, 'col4': 5, 'col5': 5, 'col6': 1, 'col7': 8, 'col8': 5}, 1998: {'col1': 1, 'col2': 3, 'col3': 7, 'col4': 0, 'col5': 7, 'col6': 0, 'col7': 7, 'col8': 1}, 1999: {'col1': 5, 'col2': 7, 'col3': 1, 'col4': 1, 'col5': 6, 'col6': 0, 'col7': 8, 'col8': 5}, 2000: {'col1': 3, 'col2': 8, 'col3': 5, 'col4': 0, 'col5': 3, 'col6': 0, 'col7': 6, 'col8': 3}, 2001: {'col1': 6, 'col2': 0, 'col3': 4, 'col4': 1, 'col5': 7, 'col6': 1, 'col7': 2, 'col8': 7}}
6
df = pd.DataFrame.from_dict(data, orient='index')
7
8
# display(df.head())
9
col1 col2 col3 col4 col5 col6 col7 col8
10
1990 0 4 7 3 7 0 6 6
11
1991 1 7 5 0 8 1 8 4
12
1992 0 5 0 1 9 1 7 2
13
1993 2 7 0 0 6 1 2 7
14
1994 4 1 5 5 8 1 6 3
15
Plotting with seaborn.catplot
- Using
seaborn 0.11.1
, the correct way to create abarplot
FacetGrid (per the documentation), is withsns.catplot
andkind='bar'
. - It is required to convert the dataframe from a wide to long form, which is easily done by resetting the index, and then using
pandas.DataFrame.melt()
- A
catplot
is a figure-level interface for drawing categorical plots onto a FacetGrid.g.set_xticklabels(rotation=90)
can be used to rotate the xticklabels.- See How to rotate xticklabels in a seaborn catplot or How to set rotation for seaborn FacetGrid and figure-level xtick labels
JavaScript
1
20
20
1
# convert the wide dataframe to a long format with melt
2
dfm = df.reset_index().melt(id_vars='index', var_name='variable', value_name='value')
3
4
# display(dfm.head())
5
index variable value
6
0 1990 col1 0
7
1 1991 col1 1
8
2 1992 col1 0
9
3 1993 col1 2
10
4 1994 col1 4
11
12
# plot with catplot and kind='bar'
13
g = sns.catplot(data=dfm, kind='bar', col='index', col_wrap=4, x='variable', y='value', height=3)
14
15
# change the ticklabel rotation if needed
16
g.set_xticklabels(rotation=90)
17
18
# change ylim if needed
19
g.set(ylim=(0, 30))
20
Plotting with pandas.DataFrame.plot
- While you have asked about
seaborn
, given the dataframe in the OP with all the years in the index, the easiest way to plot the data is transpose the dataframe with.T
, and then usepandas.DataFrame.plot
JavaScript
1
15
15
1
# display(df.T.head())
2
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001
3
col1 0 1 0 2 4 7 5 0 1 5 3 6
4
col2 4 7 5 7 1 0 1 4 3 7 8 0
5
col3 7 5 0 0 5 6 1 7 7 1 5 4
6
col4 3 0 1 0 5 4 4 5 0 1 0 1
7
col5 7 8 9 6 8 8 6 5 7 6 3 7
8
9
# transpose and plot
10
axes = df.T.plot(kind='bar', subplots=True, layout=[3, 4], figsize=(15, 7), legend=False, rot=0)
11
12
# to change ylim of the subplots, if needed
13
for ax in axes.flatten():
14
ax.set_ylim(0, 30)
15