Using Python to draw a mosaic/marimekko plot in plotly bar gap issue

112 Views Asked by At

I would like to use plotly to generate a mosaic plot in python. I followed this answer, but there's a gap between the bar charts I can't get rid of. I've tried using fig.update_layout(bargap=0) but that doesn't fix it. Is there a way to fix this so that the bars touch or are at least closer to one another?

Plot with gap between bars

Plot with gap between bars

Code and data I'm using

# Dataframe creation/formatting
df = pd.DataFrame(
    [
        [5755, 6221, 5424, 7261, 1158, 7075, 6780],
        [6103, 3143, 7094, 9212, 3175, 9956, 9655],
        [2810, 3047, 5938, 2067, 2189, 8892, 2380],
    ],
    columns=['X1','X2','X3','X4','X5','X6','X7']
)

df = df.T

labels = ['Group1','Group2','Group3']

df.columns = labels

for c in df.columns:
    df[c + '_%'] = df[c].apply(lambda x: (x/df.loc[:,c].sum()) * 100)
    

widths = np.array([sum(df['Group1']),sum(df['Group2']),sum(df['Group3'])])

marker_colors = {
    'X1':'darkblue',
    'X2':'darkgreen',
    'X3':'crimson',
    'X4':'green',
    'X5':'blue',
    'X6':'red',
    'X7':'orange'
}


fig1 = go.Figure()

for idx in df.index:
    dff = df.filter(items=[idx], axis=0)
    fig1.add_trace(go.Bar(
        x=np.cumsum(widths) - widths,
        y=dff[dff.columns[3:]].values[0],
        width=widths,
        marker_color=marker_colors[idx],
        text=['{:.2f}%'.format(x) for x in dff[dff.columns[3:]].values[0]],
        name=idx
    )
)

fig1.update_xaxes(
    tickvals=np.cumsum(widths)-widths,
    ticktext= ["%s<br>%d" % (l, w) for l, w in zip(labels, widths)]
)

fig1.update_xaxes(range=[0, widths])
fig1.update_yaxes(range=[0, 100])

fig1.update_layout(barmode='stack')

#fig1.write_image('test_1.png')
fig1.show() 

I tried to create a mosaic plot in plotly following a guide posted in another thread. The resulting plot has gaps between the bars that I cannot remove. I've tried using fig.update_layout(bargap=0) but that doesn't fix it.

1

There are 1 best solutions below

0
On

There are 2 things to fix :

  • Set offset=0 to every bar traces.
  • Fix the xaxis range and tickvals accordingly (see below).
fig1 = go.Figure()

for idx in df.index:
    dff = df.filter(items=[idx], axis=0)
    fig1.add_trace(go.Bar(
        x=np.cumsum(widths) - widths,
        y=dff[dff.columns[3:]].values[0],
        width=widths,
        marker_color=marker_colors[idx],
        text=['{:.2f}%'.format(x) for x in dff[dff.columns[3:]].values[0]],
        name=idx,
        offset=0
    )
)

fig1.update_yaxes(range=[0, 100])
fig1.update_xaxes(
    range=[0, np.sum(widths)],
    tickvals=np.cumsum(widths) - widths/2,
    ticktext= ["%s<br>%d" % (l, w) for l, w in zip(labels, widths)]
)

fig1.update_layout(barmode='stack')

fig1.show()

output