How to change the plot order of the categorical x-axis

Question:

I got a dataframe which looks like below:

df:

Time of Day Season  value
Day        Shoulder 30.581606
Day        Summer   25.865560
Day        Winter   42.644530
Evening    Shoulder 39.954759
Evening    Summer   32.053458
Evening    Winter   53.678297
Morning    Shoulder 32.171245
Morning    Summer   25.070815
Morning    Winter   42.876667
Night      Shoulder 22.082042
Night      Summer   17.510290
Night      Winter   33.262356

I am plotting the values in line plot using seaborn using following code:

g = sns.lineplot(x='Time of Day',y='value',data=df,hue='Season')

it generates the following graph:

enter image description here

The problem with the graph is that order of the x-axis is not in the desired order. I want to change the order of a-axis value to [‘Morning’, ‘Day’,’Evening’,’Night’]. I tried to change it with the following command:

g.set_xticklabels(['Morning','Day','Evening','Night'])

But this command only changes the label of the x-axis, not the order of data points. Could anyone help me in fixing the issue?

Asked By: user2293224

||

Answers:

  • Use pandas.Categorical to set the categorical order of 'Time of Day' in the df.
  • Tested in python 3.11, pandas 1.5.3, matplotlib 3.7.1, seaborn 0.12.2
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

data = {'Time of Day': ['Day', 'Day', 'Day', 'Evening', 'Evening', 'Evening', 'Morning', 'Morning', 'Morning', 'Night', 'Night', 'Night'],
        'Season': ['Shoulder', 'Summer', 'Winter', 'Shoulder', 'Summer', 'Winter', 'Shoulder', 'Summer', 'Winter', 'Shoulder', 'Summer', 'Winter'],
        'value': [30.581606, 25.865560000000002, 42.644529999999996, 39.954759, 32.053458, 53.678297, 32.171245, 25.070815, 42.876667, 22.082042, 17.510289999999998, 33.262356]}

# create dataframe
df = pd.DataFrame(data)

# set categorical order
df['Time of Day'] = pd.Categorical(df['Time of Day'],
                                   categories=['Morning', 'Day', 'Evening', 'Night'],
                                   ordered=True)

# plot
ax = sns.lineplot(x='Time of Day', y='value', data=df, hue='Season')
sns.move_legend(ax, bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)

enter image description here

Answered By: Trenton McKinney

If you don’t want to change it to categorical column and do the ordered plotting?!

# here dictionary value in map() will decide which value should be first and next
df_sort = df.sort_values('Time of Day'
                         , key=lambda col: col.map(
                                 { 'Morning':10
                                  ,'Evening':3
                                  ,'Day':2
                                  ,'Night':4}))
sns.lineplot(x='Time of Day', y='value', data=df_sort, hue='Season');

enter image description here

Answered By: arun
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.