Search code examples
pythonchartsplotlydata-visualizationplotly-python

How to create Plotly benchmarking bar chart with average value as base axis


I want to develop a kind of cool benchmark chart that will show on the Y-axis some categories (in my case companies), on the X-axis there will be some numeric values representing a given measurement e.g. daily number of sold products.

And I want present it in a way that somewhere in the middle of the X-axis I will show a long straight line which will represent the average of my measurement - and then I want to use it as my base axis. And for each category, I will show a bar chart that will have a 0 (start) value at the average line, and the end will be the difference between the measurement of the given category and the average (category measurement - average). Below is an example that I draw in PowerPoint. I hope it will give you a short overview of what I want to achieve.

enter image description here

To be honest I don't know if it's possible with Plotly library. My initial idea is that I need to put the average line as a separate element on the given chart, and then I need to somehow dynamically calculate the start, and end of the given category bar chart and put it on the chart. But don't know if it makes sense.

Could you help me with this case?


Solution

  • Assume you have some data,

    import pandas as pd
    import plotly.graph_objects as go
    
    data = pd.DataFrame({
        'companies': ['Comp1', 'Comp2', 'Comp3', 'Comp4'], 
        'performance': [26, 37, 54, 19]
    })
    
    # if you want a manual benchmark
    benchmark_value = 40
    
    # or in case the average
    benchmark_value = data['performance'].mean()
    
    data['benchmark_score'] = data['performance'] - benchmark_value
    
    fig = go.Figure(
        go.Bar(
            y=data['companies'],
            x=data['benchmark_score'],
            marker=dict(color=['red' if score < 0 else 'green' for score in data['benchmark_score']]),
            orientation='h',
            text=data['benchmark_score'],
        )
    )
    
    # add vertical line at 0 but with benchmark value as annotation
    fig.add_vline(x=0, line_width=2, line_dash="dash", annotation_text=benchmark_value)
    
    fig.show()
    

    Output:

    enter image description here

    You can customize a bit on some attributes such as bar colors and text annotation.