2025, Dec 31 12:02
Перевёрнутые биты 0/1 в Plotly и pandas: причина и решение
График двоичного потока в Plotly и pandas переворачивает 0/1 из‑за строковых типов. Объясняем причину и фикс: приводим столбцы к числовым и получаем ось y.
При построении графика двоичного потока обычно ожидаешь, что 0 будет внизу оси y, а 1 — наверху. Однако иногда отдельные ряды оказываются перевёрнутыми: 1 рисуется внизу, а 0 — наверху. Это особенно сбивает с толку, когда так ведут себя лишь некоторые столбцы, а остальные выглядят правильно. Ниже — минимальный пример того, как такое происходит при работе с Plotly и pandas.
Постановка задачи
Процедура построения проста: на каждый столбец — по одному трейсу, отображаем серии ступенчатыми линиями. Для части столбцов визуализация переворачивается.
import plotly.graph_objects as go
# bits_df — DataFrame с двоичными значениями в каждом столбце
chart = go.Figure()
for series_name in bits_df.columns:
chart.add_trace(
go.Scatter(
x=bits_df.index,
y=bits_df[series_name],
name=series_name,
visible="legendonly",
line_shape='hv')
)
chart.update_layout(
autosize=False,
width=1550,
height=800,
xaxis_title=bits_df.index.name,
yaxis_title="State",
yaxis=dict(range=[0, 1])
)
chart.show()Что на самом деле происходит
Проблема не в рендерере Plotly и не в настройках фигуры. Причина — в типах данных. В некоторых столбцах значения хранятся как текст, а не как числа. То есть вместо чисел 0 и 1 в строках лежат строки "0" и "1". Получив текст по оси y, Plotly трактует его как категории. Порядок категорий на оси y определяется порядком первых встреченных меток в каждом трейсе. Если первым значением в столбце окажется "1", эта метка может расположиться перед "0" в категориальном порядке, из‑за чего уровни бита визуально меняются местами. Столбцы с настоящими числовыми значениями строятся корректно, с ожидаемым поведением числовой оси.
Решение
Перед построением преобразуйте серии к числовым типам. Когда данные становятся числами, Plotly использует числовую ось y, и уровни бита будут стабильно отображаться: 0 — внизу, 1 — наверху, во всех столбцах.
import pandas as pd
import plotly.graph_objects as go
# Убедитесь, что все нужные столбцы имеют числовой тип
bits_num = bits_df.apply(pd.to_numeric)
chart = go.Figure()
for series_name in bits_num.columns:
chart.add_trace(
go.Scatter(
x=bits_num.index,
y=bits_num[series_name],
name=series_name,
visible="legendonly",
line_shape='hv')
)
chart.update_layout(
autosize=False,
width=1550,
height=800,
xaxis_title=bits_num.index.name,
yaxis_title="State",
yaxis=dict(range=[0, 1])
)
chart.show()Почему это важно
В бинарной телеметрии, при анализе протоколов и визуализации цифровых сигналов важно соблюдение привычного правила: более высокий логический уровень расположен выше по оси. Смешение типов данных (dtypes) внутри DataFrame может незаметно нарушить это допущение во время разведочного анализа и привести к неверной интерпретации переходов битов. Единообразные числовые типы исключают влияние категориального упорядочивания на задуманное представление.
Итоги
Перед построением двоичных данных в Plotly убедитесь, что столбцы не хранятся как текст. Преобразуйте их в числовые типы, чтобы получить корректную числовую ось y и предсказуемое расположение 0/1. Если делитесь проблемой для разбора, прикладывайте небольшой воспроизводимый пример данных, а не изображения — так поведение быстрее воспроизвести и проверить.