How to align text in a plotly figure?

Problem

I have a plotly icicle figure with a custom texttemplate. I want to either show a table or properly aligned text (i.e. with true tabs and not &nbsp;). I noticed that texttemplate accepts arguments such as <br>, nbsp; , <span style=...> but I also have the argument textposition="middle center" such that the alignment is not correct.

fig.update_traces(
    texttemplate=...,
    textposition="middle center"
)

How can I align the text inside texttemplate?


What I tried

html table
I tried a html table, but it simply showed all the tags as strings (i.e. it printed <table> as text).

counting chars and using a spacer
I also tried counting the number of strings and creating a spacer for each line, but texttemplate did not accept multiplication by a series.

formatted string alignment
And I also tried string alignment such as

'{:<20}{:>20}'.format('column1', 'column2') + "<br>" +
'{:<20}{:>20}'.format('column123', 'column234') + "<br>"

but it also did not work because the text is not aligned. Note that when this code is used in a jupyter notebook, the text is aligned correctly:

enter image description here


Full code

import plotly.express as px
import pandas as pd

df = pd.DataFrame({
    "people":           ["First",       "Anne",        "Bob",          "Chris",        "Damian",       "Eve",          "Faith",        "Gabriel",      "Hester",       "Ivy",          "Jacob"],
    "parent":           ["",            "First",       "First",        "First",        "Anne",         "Bob",          "Bob",          "Chris",        "Chris",        "Eve",          "Hester"],
    "Year of birth":    [1900,           1920,          1924,           1929,           1958,           1963,           1967,           1971,           1972,           2000,           2001],
    "Year of death":    [1900,           1933,          1932,           1931,           1958,           1963,           1967,           1971,           1972,           2000,           2001],
    "Place of birth":   ["Amsterdam",   "Rotterdam",   "Den haag",     "Flevoland",    "Almere",       "Groningen",    "Apeldoorn",    "Zaandam",      "Flevoland",    "Assen",         "Amsterdam",],
    "Place of death":   ["New York",    "LA",          "Washington",   "Texas",        "FLorida",      "New Jersey",   "Cansas",       "Wyoming",      "Georgia",      "New York",      "Nabraska",],
    "spouse":           ["Mario",       "Luigi",       "Peach",        "Bowser",       "Toad",         "Toadette",     "-",             "-",           "-",            "-",             "-",],    
    "Cause of death":   ["Fireball",    "0 lives",     "Chupa",        "Spikes",       "Gravity",      "Teammate",     "-",             "-",           "-",            "-",             "-",],    
})



df = df.sort_values("Year of birth")
df['spacer'] = (df["Place of birth"] + df['Place of death']).str.len()


fig = px.icicle(
    df,
    names='people',
    parents='parent',
    # title="Title goes here",
    width=1000,
    height=1000,
    color="Year of birth",
    color_continuous_scale="YlGnBu_r",
)

fig.update_traces(    
    texttemplate= 
    "<span style='font-size:15pt'>" + df.people + "</span>" + 
    "<br><br>" + 
    df["Place of birth"] + 30*" " + " " + list(map(str, df["Year of birth"])) + "<br>" +
    df["Place of death"] + 30*" " + " " + list(map(str, df["Year of death"])) + "<br>" +
    "Spouse: " + 21*"&nbsp;" + df.spouse + "<br>" +
    "Cause of death: "  + 10*"&nbsp;" + df['Cause of death'] + "<br>" +
    
    f"{'Aaaa' : <20}" + f"{'Bbbbbbbbbb' : <20}" + "<br>" +
    f"{'Aaaaaa' : <20}" + f"{'Bbbbbbbb' : <20}" + "<br>" +
    f"{'Aaaaaaa' : <20}" + f"{'Bbbbbbbbbbbbbbb' : <20}" + "<br>" +
    f"{'A' : <30}" + f"{'Bb' : <20}" + "<br>" +
    
    '{:<20}{:>20}'.format('column1', 'column2') + "<br>" +
    '{:<20}{:>20}'.format('column123', 'column234') + "<br>" +
    '{:<20}{:>20}'.format('c1', 'c2')
    ,
    
    
    textposition="middle center", # text position relavtive to the rectangle

)

fig.update_layout(
    margin = dict(t=10, l=10, r=10, b=10),
    coloraxis=dict(colorbar=dict(orientation='h', y=-0.3)),
)


fig.show()

Current output:

enter image description here

Hi @theOneAndOnly !
Welcome on the Forum! :tada:

Itโ€™s a tricky one!

I guess itโ€™s because of the font, you need to use a monospace font.
The default font of Plotly is not a monespace one, so for each line, 20 characters will not have necessarily the same width (high probability they wonโ€™t)

Thatโ€™s why I suppose that works in Jupyter notebook, the default font must be a monospace type.

Try to add in .update_traces():

textfont=dict(
        family="monospace",
         size=18,
),

Let me know how that goes :slightly_smiling_face:

1 Like