Michael K
Michael K

Reputation: 355

bi-directional bar chart with annotation in python plotly

I have a pandas dataset with a toy version that can be created with this

#creating a toy pandas dataframe
s1 = pd.Series(['dont have a mortgage',-31.8,'have mortgage',15.65])
s2 = pd.Series(['have utility bill arrears',-21.45,'',0])
s3 = pd.Series(['have interest only mortgage',-19.59,'',0])
s4 = pd.Series(['bank with challenger bank',-19.24,'bank with a traditional bank',32.71])

df = pd.DataFrame([list(s1),list(s2),list(s3),list(s4)], columns = ['label1','value1','label2','value2'])

I want to create a bar chart that looks like this version I hacked together in excel

enter image description here

I want to be able to supply RGB values to customise the two colours for the left and right bars (currently blue and orange)

I tried different versions using “fig.add_trace(go.Bar” but am brand new to plotly and cant get anything to work with different coloured bars on one row with annotation under each bar.

All help greatly appreciated!

thanks

Upvotes: 2

Views: 2760

Answers (1)

Pascalco
Pascalco

Reputation: 2826

To create a double-sided bar chart, you can create two subplots with shared x- and y-axis. Each subplot is a horizontal bar chart with a specified marker color

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# define data set
s1 = pd.Series(['dont have a mortgage',-31.8,'have mortgage',15.65])
s2 = pd.Series(['have utility bill arrears',-21.45,'',0])
s3 = pd.Series(['have interest only mortgage',-19.59,'',0])
s4 = pd.Series(['bank with challenger bank',-19.24,'bank with a traditional bank',32.71])
df = pd.DataFrame([list(s1),list(s2),list(s3),list(s4)], columns = ['label1','value1','label2','value2'])

# create subplots
fig = make_subplots(rows=1, cols=2, specs=[[{}, {}]], shared_xaxes=True,
                    shared_yaxes=True, horizontal_spacing=0)

fig.append_trace(go.Bar(y=df.index, x=df.value1, orientation='h', width=0.4, showlegend=False, marker_color='#4472c4'), 1, 1)
fig.append_trace(go.Bar(y=df.index, x=df.value2, orientation='h', width=0.4, showlegend=False, marker_color='#ed7d31'), 1, 2)
fig.update_yaxes(showticklabels=False) # hide all yticks

The annotations need to be added separately:

annotations = []
for i, row in df.iterrows():
    if row.label1 != '':
        annotations.append({
            'xref': 'x1',
            'yref': 'y1',
            'y': i,
            'x': row.value1,
            'text': row.value1,
            'xanchor': 'right',
            'showarrow': False})
        annotations.append({
            'xref': 'x1',
            'yref': 'y1',
            'y': i-0.3,
            'x': -1,
            'text': row.label1,
            'xanchor': 'right',
            'showarrow': False})            
    if row.label2 != '':
        annotations.append({
            'xref': 'x2',
            'yref': 'y2',
            'y': i,
            'x': row.value2,
            'text': row.value2,
            'xanchor': 'left',
            'showarrow': False})  
        annotations.append({
            'xref': 'x2',
            'yref': 'y2',
            'y': i-0.3,
            'x': 1,
            'text': row.label2,
            'xanchor': 'left',
            'showarrow': False})

fig.update_layout(annotations=annotations)
fig.show()

Upvotes: 2

Related Questions