Search code examples
pythondataframedatetimeplotlyaxis

Re-order axis in Plotly graph


I have data of ~3 years organised by month and year. I want to plot this data as a bar chart by month and year, with the month as the x-axis and the year as a trace. The problem is that the data starts in September 2018, so the first month to be plotted is September, but I want it to be January. I've tried to do that but then the years are in decreasing order, which I don't want either. Here is a code example.

import datetime
import pandas as pd
import plotly.graph_objects as go
import random

df = pd.DataFrame({})
numdays = 1000
base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]
price = [random.randint(1,10) for i in range(numdays)]
df['price'] = price
df.index = date_list
df = df.resample('MS').sum()
df['month'] = df.index.month_name()
df['month number'] = df.index.month
df['year'] = df.index.year
year_list = df['year'].unique().tolist()
fig = go.Figure()

for year in year_list:
    df_aux = df[df.year==year]
    df_aux = df_aux.sort_values(by=['month number'])
    fig.add_trace(go.Bar(x=df_aux.month, y=df_aux['price'], \
                          name=year))

fig.show()

This is what I get, but it starts in September and I want it to be January:

This is what I get, but it starts in September and I want it to be January


Solution

  • Using this reference for categorical axes from plotly, I was able to use the categoryorder and set the catergoryarray, which allows you to set the list of the order that you want to use for your axis.

    From the documentation/reference:

    Whether using Plotly Express or not, categories can be sorted alphabetically or by value using the categoryorder attribute:

    and also:

    This example shows how to control category order when using plotly.graph_objects by defining categoryorder to "array" to derive the ordering from the attribute categoryarray.

    The line of code that I added was:

    fig.update_xaxes(categoryorder='array', categoryarray= ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'])
    

    and this gave an output which looked like this:

    enter image description here

    The complete code:

    import datetime
    import pandas as pd
    import plotly.graph_objects as go
    import random
    
    df = pd.DataFrame({})
    numdays = 1000
    base = datetime.datetime.today()
    date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]
    price = [random.randint(1,10) for i in range(numdays)]
    df['price'] = price
    df.index = date_list
    df = df.resample('MS').sum()
    df['month'] = df.index.month_name()
    df['month number'] = df.index.month
    df['year'] = df.index.year
    year_list = df['year'].unique().tolist()
    
    fig = go.Figure()
    
    for year in year_list:
        df_aux = df[df.year==year]
        df_aux = df_aux.sort_values(by=['month number'])
        fig.add_trace(go.Bar(x=df_aux.month, y=df_aux['price'], \
                              name=year))
    
    fig.update_xaxes(categoryorder='array', categoryarray= ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'])
    
    fig.show()