vestland
vestland

Reputation: 61204

Plotly: How to customize xaxis tick labels using plotly express?

I'm trying to display a horizontal bar chart with dates on the x-axis, but can't seem a way to do that although the x-values are dates of type string. As you can see below, the numbers that occur as ticklabels have to be a summation of some sort, but I'm not sure exactly what. How can you change the example below to get dates as ticklabels?

Plot 1:

enter image description here

Code:

# imports
import numpy as np
import pandas as pd
import plotly.express as px
from datetime import datetime

# data
np.random.seed(1)
cols=list('ABCDE')
df = pd.DataFrame(np.random.randint(0,2,size=(5, len(cols))), columns=cols)
drng=pd.date_range(datetime(2020, 1, 1).strftime('%Y-%m-%d'), periods=df.shape[0]).tolist()
df['date']=[d.strftime('%Y-%m-%d') for d in drng]
dfm=pd.melt(df, id_vars=['date'], value_vars=df.columns[:-1])

# plotly express
fig = px.bar(dfm, x="date", y="variable", color='value', orientation='h',
             hover_data=["date"],
             height=400,
             color_continuous_scale=['blue', 'teal'],
             title='Custom date ticklabels for vertical bar plot',
             template='plotly_white',
            )

fig.update_traces(showlegend=False)
fig.update(layout_coloraxis_showscale=False)
fig.show()

What I've tried:

I've tried different combinations for tickmode, tickvals and ticktext for xaxis=dict() in fig.update_layout, alas with completely useless results.

Attempt 2: ticktext

Set tickvals=df['date']

fig.update_layout(yaxis=dict(title=''),
                  xaxis=dict(title='',
                  gridcolor='grey',
                  #tickmode= 'array',
                  #tickmode= 'linear',
                  #tick0= 2220,
                  #dtick=200,
                  #tickvals= [2020, 2040],
                  ticktext = df['date'])
                 )

Plot 2:

Same as before:

enter image description here

Attempt 3: ticktext & dtick

To my amazement, setting dtick to some arbitrary value gives you the plot below.

fig.update_layout(yaxis=dict(title=''),
                  xaxis=dict(title='',
                  gridcolor='grey',
                  #tickmode= 'array',
                  #tickmode= 'linear',
                  tick0= 2050,
                  dtick=2,
                  #tickvals= [2020, 2040],
                  ticktext = df['date'])
                 )

Plot 3:

enter image description here

Still amazingly useless, but now the ticks at least looks like dates, although we're looking at a value that represents a timestamp in 2008 and the source data is 2020...

Attempt 4: tickvals and ticktext

fig.update_layout(yaxis=dict(title=''),
                  xaxis=dict(title='',
                  gridcolor='grey',
                  #tickmode= 'array',
                  #tickmode= 'linear',
                  tick0= 2050,
                  #dtick=2,
                  tickvals= [2050, 2100, 2150, 2200],
                  ticktext = df['date'])
                 )

Plot 4:

From the looks of if, this is exactly what I'm looking for:

enter image description here

But this is equally useless like the other attempts, since we have to specify tickvals= [2050, 2100, 2150, 2200]. If we change the period, these values will have to be re-specified, and that's not very flexible. Of course, if we somehow could retrieve the default tickvalues used by plotly, we could easily replace them with the dates in the dataset. But that seems to still be impossible according to the answer to the post Plotly: How to retrieve values for major ticks and gridlines?

I'm at a complete loss here, and baffled by the uselessness of my attempts, so any other suggestions would be great!

Upvotes: 3

Views: 17028

Answers (2)

Fra
Fra

Reputation: 11

You have to set programmatically both the ticks values and labels. Suppose to have a dataset having Date and Timestamp and that you want only 10 ticks in the x axis to be shown, then:

        tickvals=[df["Timestamp"][j] for j in range(0,len(df["Timestamp"]),int(len(df["Timestamp"])/10))]
        ticktext=[df["Date"][j] for j in range(0,len(df["Date"]),int(len(df["Date"])/10))]



        fig.update_layout(
            xaxis = dict(
                tickmode = 'array',
                tickvals = tickvals,
                ticktext = ticktext,
            )
        )

Note: remember to sort dates before generating timestamps!

Upvotes: 0

Alberto Vales Alonso
Alberto Vales Alonso

Reputation: 41

You must activate tickmode to 'array' and then define tickvals and ticktext, like:

tickmode = 'array',
tickvals = [2050, 2100, 2150, 2200],
ticktext = df['date'])

Upvotes: 4

Related Questions