2025, Dec 31 03:02
Выборочное жирное начертание подписей в Plotly через HTML-теги
Как сделать часть подписей жирными в Plotly для точечной диаграммы: используем HTML-теги без дробления трасс. Простой пример кода на Python. С пояснениями.
Сделать несколько подписей жирными в точечной диаграмме Plotly кажется простой доработкой интерфейса, но базовый API оформления применяет настройки ко всей трассе, а не к отдельным точкам. Если попытаться передать стиль шрифта построчно в данных, ничего не произойдет. К счастью, Plotly поддерживает небольшой поднабор HTML внутри текстовых полей, что позволяет точно и надежно выделять жирным только нужные подписи.
Постановка задачи
Следующий код строит точечный график с подписями, размерами, цветами и настроенными осями. Требуется сделать жирными только три подписи, а остальные оставить обычной толщины.
import plotly.express as px
import pandas as pd
payload = {
"label_txt": ["test 98lop1", "test9665 opp1", "test QSDFR1", "test ABBE1", "testtest21", "test23"],
"xv": [12.6, 10.8, -1, -15.2, -10.4, 1.6],
"yv": [15, 5, 44, -11, -35, -19],
"bubble_s": [375, 112.5, 60, 210, 202.5, 195],
"hue": ["green", "green", "green", "red", "red", "red"],
"weight_flag": ["normal", "normal", "normal", "bold", "bold", "bold"],
}
frame = pd.DataFrame(payload)
chart = px.scatter(
frame,
x="xv",
y="yv",
color="hue",
size="bubble_s",
text="label_txt",
hover_name="label_txt",
color_discrete_map={"red": "red", "green": "green"},
title="chart",
)
chart.update_traces(
textposition="middle right",
textfont_size=14,
textfont_color="black",
textfont_family="Inter",
hoverinfo="skip",
)
legend_names = {"red": "red title", "green": "green title"}
chart.update_layout(
{
"yaxis": {
"range": [-200, 200],
"zerolinewidth": 2,
"zerolinecolor": "red",
"tick0": -200,
"dtick": 45,
},
"xaxis": {
"range": [-200, 200],
"zerolinewidth": 2,
"zerolinecolor": "gray",
"tick0": -200,
"dtick": 45,
},
"height": 800,
}
)
chart.add_scatter(
x=[0, 0, -200, -200],
y=[0, 200, 200, 0],
fill="toself",
fillcolor="gray",
zorder=-1,
mode="markers",
marker_color="rgba(0,0,0,0)",
showlegend=False,
hoverinfo="skip",
)
chart.add_scatter(
x=[0, 0, 200, 200],
y=[0, -200, -200, 0],
fill="toself",
fillcolor="yellow",
zorder=-1,
mode="markers",
marker_color="rgba(0,0,0,0)",
showlegend=False,
hoverinfo="skip",
)
chart.update_layout(paper_bgcolor="#F1F2F6")
chart.show()
Что происходит на самом деле
Оформление текста, переданное на уровне трассы — размер, гарнитура, цвет — применяется одинаково ко всем точкам этой трассы. Иными словами, отдельного переключателя font-weight для каждой точки здесь нет. Зато текстовые поля в Plotly принимают ограниченный набор HTML, позволяя вставлять встроенную разметку прямо в строки с подписями.
Chart Studio использует поднабор HTML-тегов для таких вещей, как перенос строки (<br>), жирное начертание (<b></b>), курсив (<i></i>) и гиперссылки (<a href=’…’></a>). Также поддерживаются теги <em>, <sup> и <sub>.
Этот поднабор работает и в текстовом содержимом Plotly, поэтому достаточно обернуть нужные подписи в <b>…</b>, чтобы получить желаемый результат.
Решение: встроенный HTML для выборочного жирного начертания
Самый простой прием — предварительно обработать подписи и обернуть <b>…</b> вокруг тех, что нужно выделить. Ниже подписи преобразуются перед созданием DataFrame, сопоставляя каждое значение с его “weight_flag”.
import plotly.express as px
import pandas as pd
payload = {
"label_txt": ["test 98lop1", "test9665 opp1", "test QSDFR1", "test ABBE1", "testtest21", "test23"],
"xv": [12.6, 10.8, -1, -15.2, -10.4, 1.6],
"yv": [15, 5, 44, -11, -35, -19],
"bubble_s": [375, 112.5, 60, 210, 202.5, 195],
"hue": ["green", "green", "green", "red", "red", "red"],
"weight_flag": ["normal", "normal", "normal", "bold", "bold", "bold"],
}
payload["label_txt"] = [
(f"{txt}" if w == "bold" else txt)
for txt, w in zip(payload["label_txt"], payload["weight_flag"])
]
frame = pd.DataFrame(payload)
chart = px.scatter(
frame,
x="xv",
y="yv",
color="hue",
size="bubble_s",
text="label_txt",
hover_name="label_txt",
color_discrete_map={"red": "red", "green": "green"},
title="chart",
)
chart.update_traces(
textposition="middle right",
textfont_size=14,
textfont_color="black",
textfont_family="Inter",
hoverinfo="skip",
)
legend_names = {"red": "red title", "green": "green title"}
chart.update_layout(
{
"yaxis": {
"range": [-200, 200],
"zerolinewidth": 2,
"zerolinecolor": "red",
"tick0": -200,
"dtick": 45,
},
"xaxis": {
"range": [-200, 200],
"zerolinewidth": 2,
"zerolinecolor": "gray",
"tick0": -200,
"dtick": 45,
},
"height": 800,
}
)
chart.add_scatter(
x=[0, 0, -200, -200],
y=[0, 200, 200, 0],
fill="toself",
fillcolor="gray",
zorder=-1,
mode="markers",
marker_color="rgba(0,0,0,0)",
showlegend=False,
hoverinfo="skip",
)
chart.add_scatter(
x=[0, 0, 200, 200],
y=[0, -200, -200, 0],
fill="toself",
fillcolor="yellow",
zorder=-1,
mode="markers",
marker_color="rgba(0,0,0,0)",
showlegend=False,
hoverinfo="skip",
)
chart.update_layout(paper_bgcolor="#F1F2F6")
chart.show()
Так сохраняется вся логика оформления, а жирным становятся только нужные элементы.
Зачем это держать под рукой
Выделение текста на уровне отдельных точек помогает направлять внимание без дробления данных на несколько трасс и без постобработки фигуры. Встроенный HTML — решение минималистичное, явное и удобное для ревью кода. К тому же оно не меняет структуру графика и легенду, что упрощает последующие интеграции.
Вывод
Когда требуется выборочно выделить текст в Plotly, вставляйте поддерживаемые HTML‑теги прямо в строки подписей. Это небольшое изменение дает большой выигрыш: точный контроль над акцентами, неизменная логика построения и результат, который остается верным данным. Подход подходит для жирного, курсива, верхних и нижних индексов, а остальное оформление оставляйте на уровне трассы.