How to set custom labels for x axis in a bar chart?

Hey guys!!!

I’m stuck trying to implement a customized bar chart and as I’m not finding references about how to implement it;

The problem:
I need to set a custom value to each of my x-axes, as shown in the image below:

But as shown below in my version of the chart, I’m not setting the x correctly.
image


I would like to know if someone has already implemented this type of chart and could tell me how to set it correctly. Below I set a minimal reproducible code to be easier for to someone reproduce it... Any help will be really appreciated

Data:

data={'period': ['2019_1', '2019_1', '2020_1', '2020_1', '2019_2', '2019_2', '2020_2', '2020_2', 
                 '2019_3', '2019_3', '2020_3', '2020_3', '2019_4', '2019_4', '2020_4', '2020_4'], 
      'indicator': ['metric1', 'metric0', 'metric1', 'metric0', 'metric1', 'metric0', 'metric1', 
                    'metric0', 'metric1', 'metric0', 'metric1', 'metric0', 'metric1', 'metric0', 
                    'metric1', 'metric0'], 
      'value_plot': [467.2, 1453.6, 468.13, 1521.29, 490.08, 1500.02, 518.69, 1599.33,
                     480.01, 1473.12, 510.53, 1556.38, 532.57, 1751.75, 563.62, 1877.21], 
      'qtr': ['Q1', 'Q1', 'Q1', 'Q1', 'Q2', 'Q2', 'Q2', 'Q2', 'Q3',
              'Q3', 'Q3', 'Q3', 'Q4', 'Q4', 'Q4', 'Q4'], 
      'year': ['2019', '2019', '2020', '2020', '2019', '2019', '2020', 
               '2020', '2019', '2019', '2020', '2020', '2019', 
               '2019', '2020', '2020']}

code:

import plotly.graph_objects as go
import pandas as pd
import plotly_express as px
import numpy as np

plot_df=pd.DataFrame.from_dict(data)

bargap=.3
past_rev_color="red"
current_rev_color="blue"

current_year_mask=np.where(plot_df.year==2020, True, False)
metric0_mask=plot_df.indicator.str.endswith("metric0")

metric0_table=plot_df[metric0_mask]

fig=px.bar(metric0_table, 
           x="qtr", y="value_plot", 
           color="year", barmode="group",
            color_discrete_map={"2019": past_rev_color, 
                                "2020": current_rev_color},
           custom_data=[metric0_table["year"]])


fig.layout.xaxis2 = go.layout.XAxis(overlaying="x", 
                                    range=[0, 4], showticklabels=False)
fig.layout.yaxis2 = go.layout.YAxis(overlaying="y", side="right")

metric1_table=plot_df[np.logical_not(metric0_mask)]
metric1_curr_yr_mask=np.where(metric1_table["year"]=="2020", True, False)

fig.add_scatter(
    x=[i + (bargap / 2 + (1 - bargap) / 4) for i in range(4)],
    y=[metric1_table[metric1_curr_yr_mask].value_plot.iloc[i] for i in range(4)],
    xaxis="x2",
    yaxis="y2",
    name="previous")


fig.add_scatter(
    x=[i + (1 - bargap / 2 - (1 - bargap) / 4) for i in range(4)],
    y=[metric1_table[np.logical_not(metric1_curr_yr_mask)].value_plot.iloc[i] for i in range(4)],
    xaxis="x2",
    yaxis="y2",
    name="current")

fig.update_layout(showlegend=False)

fig

Thank you all guys!!

Hey guys, I did receive an answer on my Stackoverflow topic.

The solution to this problem is:


yy = plot_df.year.unique()
labels = [[q+' '+str(yy[0])+' '+q+' '+str(yy[1])] for q in plot_df.qtr.unique()]
fig.update_xaxes(tickvals=np.arange(4), ticktext=labels)

Hope it can be helpful to other people too.

REgards,
Leonardo

2 Likes