How can i middle the y ticks of a horizontal bar chart?

Hey guys
This is an example of a code:

import plotly.graph_objs as go

# Define data to be plotted
data = [go.Bar(
    y=['long text', 'B', 'short', 'well'],
    x=[10, 20, 30, 40],
    orientation='h'
)]

# Create a Figure object
fig = go.Figure(data=data)

# Show the figure
fig.show()

I want to center the y ticks to be below each other in the middle how can I achieve this?


Sorry for the bad picture, hopefully it conveys what I am trying to achieve.

Hi @Matan ,

something like this?

I added this line to your code:

fig.update_yaxes(ticks = "outside", tickcolor='black', ticklen=10, tickwidth = 0.5)

@AIMPED,

I think he is wanting to align the text all the same, instead of what seems to be right justified. :slight_smile:

Haha, you might be correct looking at the image again :rofl:

At first sight, this could be possible using the argument tickformat where this is the syntax of the format

1 Like

How would you go about doing it with the tickformat argument?

Hi @Matan ,

I did not figure out how to format strings, which is your case since you use categorical data on the y-axis. I am not sure, if it’s even possible with strings, but I did not invest too much time, honestly.

For numeric data this is an example, even if the result is not perfectly aligned:

import plotly.graph_objs as go

# Define data to be plotted
data = [go.Bar(
    # y=['long text', 'B', 'short', 'well'],
    y=[1000, 200, 90, 9],
    x=[10, 20, 30, 40],
    orientation='h'
)]

# Create a Figure object
fig = go.Figure(data=data)

# Show the figure
fig.update_layout(yaxis={'tickformat': '.^20'})
# ^^ this centers the number, and fills right  & left with '.' up to a total width of 20 characters

creates:
newplot (48)

1 Like

Seems like it’s not automatique in plotly. So you juste have to play with your ylist so that every element of the list have same length. You can create a simple function for that.

2 Likes

very cool! can you share the code you created the graph with?

import plotly.graph_objs as go

# Define data to be plotted
data = [go.Bar(
    y=['long text', '     B     ', '   short   ', '   well    '],
    x=[10, 20, 30, 40],
    orientation='h'
)]
fig = go.Figure(data=data)
fig.update_yaxes(ticks = "outside", tickcolor='black', ticklen=10, tickwidth = 0.5)
fig

I did not share before because it’s an ugly code :sweat_smile:. It just something like that

Nice @AbdelAnlah.

I’d like to add this little quick and dirty function:

import plotly.graph_objs as go

def center_text(iterable):
    max_len = max((map(len, iterable)))
    return [item.center(max_len, ' ') for item in iterable]
    

# Define data to be plotted
data = [go.Bar(
    y=center_text(['long text', 'B', 'short', 'well']),
    x=[10, 20, 30, 40],
    orientation='h'
)]

# Create a Figure object
fig = go.Figure(data=data)

# Show the figure
fig.update_yaxes(ticks = "outside", tickcolor='black', ticklen=10, tickwidth = 0.5)
1 Like

@AIMPED @AbdelAnlah Hi guys sorry for answering in such a delay!
First thanks for the answers!
I did notice it doesn’t always work. because letters have different sizes so depending on the letters the size of the ytick g element changes
Using what you guys sent me I have one element that is 15 pixels bigger than the other elements. which causes them not to be aligned.
So it works in some cases but sadly not in my case.
If you have any other ideas please do let me know!

Do you have a sample code? I don’t quite understand what you are describing.

Hello @AIMPED,

He is saying that no two characters are created equal. Haha.

Basically, ‘I’ takes up less space than ‘B’.

While len works, it counts these two as equal, which breaks it.

1 Like

OK, I noticed this before. So one would need to break it down to pixel level…

But not just the pixel level, the same for the fonts too haha.

It would be nice if the ticktext argument accepted a html Div.

I noticed, that some html tags work on it, such as <b> and <a>.

text = ['long text', 'B', 'short', 'well']

test = [f'<a href="www.google.com">{item}</a>' for item in text]
test = [f'<b>{item}</b>' for item in text]
# ^^ works

test = [f'<center>{item}</center>' for item in text]
# ^^ does not work
1 Like

best explanation :grin:

1 Like

that would be awesome