如何对齐Plotly冰柱图texttemplate中的文本?
问题描述
我有一个带自定义texttemplate的Plotly冰柱图,想要实现文本的正确对齐(用真正的制表位而非 ),或者直接显示表格。我发现texttemplate支持<br>、 、<span style=...>这类HTML元素,但因为设置了textposition="middle center",文本始终无法对齐。
fig.update_traces( texttemplate=..., textposition="middle center" )
如何让texttemplate内的文本正确对齐?
已尝试方案
- HTML表格:尝试用HTML表格,但所有标签都被当作纯字符串显示(直接打印
<table>文本)。 - 统计字符加间隔符:统计字符串长度后为每行生成间隔,但
texttemplate不支持Series乘法操作。 - 格式化字符串对齐:尝试了以下字符串对齐方式:
'{:<20}{:>20}'.format('column1', 'column2') + "<br>" + '{:<20}{:>20}'.format('column123', 'column234') + "<br>"
但无效,文本还是没对齐。注:这段代码在Jupyter Notebook里能正确对齐文本。
完整代码
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', 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*" " + df.spouse + "<br>" + "Cause of death: " + 10*" " + 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" ) fig.update_layout( margin = dict(t=10, l=10, r=10, b=10), coloraxis=dict(colorbar=dict(orientation='h', y=-0.3)), ) fig.show()
当前输出效果
当前图表中文本未对齐,各列内容无法整齐排列。
解决方案
方法1:等宽字体+字符串格式化
Plotly默认用非等宽字体,导致字符串格式化对齐失效。给文本模板设置等宽字体,配合逐行格式化即可解决:
fig.update_traces( texttemplate= "<span style='font-size:15pt; font-family: Courier New, monospace'>" + "<span style='font-size:18pt'>" + df.people + "</span>" + "<br><br>" + # 逐行格式化出生地与年份 df.apply(lambda row: '{:<20}{:>10}'.format(row["Place of birth"], row["Year of birth"]), axis=1) + "<br>" + # 逐行格式化死亡地与年份 df.apply(lambda row: '{:<20}{:>10}'.format(row["Place of death"], row["Year of death"]), axis=1) + "<br>" + # 配偶行格式化 df.apply(lambda row: '{:<20}{}'.format("Spouse:", row["spouse"]), axis=1) + "<br>" + # 死因行格式化 df.apply(lambda row: '{:<20}{}'.format("Cause of death:", row["Cause of death"]), axis=1) + "</span>", textposition="middle center" )
说明:
- 用
df.apply(axis=1)逐行生成格式化字符串,避开Series操作限制。 - 等宽字体下,
{:<20}这类语法能保证固定宽度,实现列对齐。
方法2:HTML固定宽度容器(非等宽字体适用)
给每列文本设置inline-block类型的固定宽度容器,强制对齐:
fig.update_traces( texttemplate= "<span style='font-size:15pt'>" + "<span style='font-size:18pt'>" + df.people + "</span>" + "<br><br>" + # 出生地列固定宽度200px df.apply(lambda row: f"<span style='display: inline-block; width: 200px'>{row['Place of birth']}</span><span>{row['Year of birth']}</span>", axis=1) + "<br>" + df.apply(lambda row: f"<span style='display: inline-block; width: 200px'>{row['Place of death']}</span><span>{row['Year of death']}</span>", axis=1) + "<br>" + df.apply(lambda row: f"<span style='display: inline-block; width: 200px'>Spouse:</span><span>{row['spouse']}</span>", axis=1) + "<br>" + df.apply(lambda row: f"<span style='display: inline-block; width: 200px'>Cause of death:</span><span>{row['Cause of death']}</span>", axis=1) + "</span>", textposition="middle center" )
说明:
display: inline-block让<span>可设置宽度且不换行。- 固定宽度容器确保每列对齐,无需依赖等宽字体。
内容的提问来源于stack exchange,提问作者Xtiaan
相关产品推荐
相关产品推荐

