Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to align trace text to center in a stacked horizontal bar chart

Tags:

python

plotly

I have a stacked horizontal bar and I want text defined for each trace to be placed at the center of the corresponding bar. I can't find an attribute that sets this without using anotations, but I'd like to use "text" for each trace and just be able to align it.

I'm using Plotly 3.4.1 with Jupyter (Plotly offline). Couldn't find any documentation about how to do this except trying to do this with annotations, which look like a more suitable solution if I want to pinpoint an explicit coordinate. What I want is a much simpler (something like "align": "center"), but couldn't find any attribute for this under go.Bar

Just want the "80", "20" to appear at the center instead of aligned to the right

from plotly.offline import iplot, plot, init_notebook_mode
import plotly.graph_objs as go

def getStackedSentimentHbar():
    trace0 = go.Bar(
        y=["A","B"],
        x=[20,80],
        orientation = 'h',
        text=["20","80"],
        textposition="inside",
        hoverinfo = "none",
    )
    trace1 = go.Bar(
        y=["A","B"],
        x=[80,20],
        orientation = 'h',
        text=["80","20"],
        textposition="inside",
        hoverinfo = "none",
    )
    data = [trace0,trace1]
    layout = go.Layout(
        barmode='stack',
        showlegend=False,
        xaxis=dict(
            showgrid=False,
            zeroline=False,
            showline=False,
            ticks='',
            showticklabels=False
        ),
        yaxis=dict(
            showgrid=False,
            zeroline=False,
            showline=False,
            ticks='',
            showticklabels=True
        ),
        margin = dict(
            l = 200, 
            r = 50, 
            b = 50, 
            t = 50, 
            pad = 10
        ),
        font=dict(
            family='Heebo', 
            size=18, 
            color='#000000'
        )
    )
    fig = go.Figure(data=data, layout=layout)
    return fig

init_notebook_mode()
fig = getStackedSentimentHbar()
iplot(fig)
like image 914
Polina Sklyarevsky Avatar asked Nov 18 '25 16:11

Polina Sklyarevsky


2 Answers

As far as I know there is no such parameter in Plotly but we can always hack to Plotly :)

Let's just duplicate all x- and y-values but leave the text as it is.

In the code below there are two functions, getStackedSentimentHbar and getStackedSentimentHbarCentered. The first one returns the original graph, the second returns the graph with the (almost) centered labels.

enter image description here

from plotly.offline import iplot, plot, init_notebook_mode
import plotly.graph_objs as go

LAYOUT = go.Layout(
        barmode='stack',
        showlegend=False,
        xaxis=dict(
            showgrid=False,
            zeroline=False,
            showline=False,
            ticks='',
            showticklabels=False
        ),
        yaxis=dict(
            showgrid=False,
            zeroline=False,
            showline=False,
            ticks='',
            showticklabels=True
        ),
        margin = dict(
            l = 200, 
            r = 50, 
            b = 50, 
            t = 50, 
            pad = 10
        ),
        font=dict(
            family='Heebo', 
            size=18, 
            color='#000000'
        )
    )

def getStackedSentimentHbar(values):

    data = []
    for i, x in enumerate(values['x']):
        trace = go.Bar(
            x=x,
            y=values['y'][i],
            orientation='h',
            text=x,
            textposition='inside',
            hoverinfo = 'none',
        )
        data.append(trace)

    fig = go.Figure(data=data, layout=LAYOUT)
    return fig

def getStackedSentimentHbarCentered(values):

    data = []
    for i, x in enumerate(values['x']):

        trace = go.Bar(
            x=[int(i / 2) for i in x * 2],
            y=values['y'][i] * 2,
            orientation = 'h',
            text=x,
            textposition='inside',
            hoverinfo = 'none'
        )
        data.append(trace)

    fig = go.Figure(data=data, layout=LAYOUT)
    return fig

values = {'x': [[20, 80], [80, 20]],
          'y': [['A', 'B'], ['A', 'B']]}

init_notebook_mode()
fig = getStackedSentimentHbarCentered(values)
iplot(fig)
like image 155
Maximilian Peters Avatar answered Nov 20 '25 06:11

Maximilian Peters


A better approach - use separate annotations.

enter image description here

var x1A = 20;
var x1B = 80;
var x2A = 80;
var x2B = 20;
var trace1 = {
  y: ['A', 'B'],
  x: [x1A, x1B],
  type: 'bar',
  orientation: 'h',
};

var trace2 = {
  y: ['A', 'B'],
  x: [x2A, x2B],
  type: 'bar',
  orientation: 'h',
};

var data = [trace1, trace2];

var layout = {
  barmode: 'stack',
  annotations: [
    { x: x1A / 2, y: 'A', text: '20', showarrow: false },
    { x: x1A + x2A / 2, y: 'A', text: '80', showarrow: false },
    { x: x1B / 2, y: 'B', text: '80', showarrow: false },
    { x: x1B + x2B / 2, y: 'B', text: '20', showarrow: false },
  ],
};

Plotly.newPlot('myDiv', data, layout);
<head>
    <!-- Load plotly.js into the DOM -->
    <script src='https://cdn.plot.ly/plotly-2.0.0.min.js'></script>
</head>

<body>
    <div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>
</body>

Here is an example from the official Plotly documentation: https://plotly.com/python/horizontal-bar-charts/#color-palette-for-bar-chart

like image 21
David Avsajanishvili Avatar answered Nov 20 '25 07:11

David Avsajanishvili



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!