Search code examples
pythonpandasmatplotlibformatplotly

Python Plotly: Percentage Axis Formatter


I want to create a diagram from a pandas dataframe where the axes ticks should be percentages.

With matplotlib there is a nice axes formatter which automatically calculates the percentage ticks based on the given maximum value:

Example:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame( { 'images': np.arange(0, 355, 5) } )      # 70 items in total, max is 350

ax = df.plot()
ax.yaxis.set_major_formatter(pltticker.PercentFormatter(xmax=350))
loc = pltticker.MultipleLocator(base=50)     # locator puts ticks at regular intervals
ax.yaxis.set_major_locator(loc)

enter image description here


Since the usage of matplotlib is rather tedious, I want to do the same with Plotly. I only found the option to format the tick labels as percentages - but no 'auto formatter' who calculates the ticks and percentages for me. Is there a way to use automatic percentage ticks or do I have to calculate them everytime by hand (urgh)?

import plotly.express as px
import pandas as pd

fig = px.line(df, x=df.index, y=df.images, labels={'index':'num of users', '0':'num of img'})
fig.layout.yaxis.tickformat = ',.0%'         # does not help
fig.show()

enter image description here

Thank you for any hints.


Solution

  • I'm not sure there's an axes option for percent, BUT it's relatively easy to get there by dividing y by it's max, y = df.y/df.y.max(). These types calculations, performed right inside the plot call, are really handy and I use them all of the time.

    NOTE: if you have the possibility of negative values it does get more complicated (and ugly). Something like y=(df.y-df.y.min())/(df.y.max()-df.y.min()) may be necessary and a more general solution.

    Full example:

    import plotly.express as px
    import pandas as pd
    
    data = {'x': [0, 1, 2, 3, 4], 'y': [0, 1, 4, 9, 16]}
    df = pd.DataFrame.from_dict(data)
    
    fig = px.line(df, x=df.x, y=df.y/df.y.max())
    #or# fig = px.line(df, x=df.x, y=(df.y-df.y.min())/(df.y.max()-df.y.min()))
    fig.layout.yaxis.tickformat = ',.0%'
    fig.show()
    

    enter image description here