2025, Dec 11 13:00

Why some Plotly binary series plot upside down, and how to fix it by converting 0/1 strings to numbers

Learn why Plotly flips some binary traces when 0/1 are strings, how pandas dtypes force a categorical y-axis, and the fix: convert columns to numeric.

When plotting a binary bit stream, you expect 0 at the bottom and 1 at the top of the y-axis. Yet sometimes individual series appear inverted: 1 is rendered at the bottom and 0 at the top. This is especially confusing if only some columns behave that way while the rest look correct. Below is a minimal example of how that happens when working with Plotly and pandas.

Problem setup

The plotting routine is straightforward: add a trace per column and display the series as step lines. The render flips for a subset of columns.

import plotly.graph_objects as go

# bits_df is a DataFrame with binary values per column
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()

What’s really going on

The culprit is not Plotly’s rendering engine or the figure settings. The root cause is data type. Some columns contain values as text, not numbers. In other words, the entries are "0" and "1" strings instead of numeric 0 and 1. When Plotly receives text values for the y-axis, it treats them as categories. Category order on a y-axis follows the first-seen label order per trace. If the first value in a column is "1", that label can appear before "0" in the category ordering, which visually flips the bit levels. Columns stored as actual numbers plot correctly with the expected numeric axis behavior.

Fix

Convert the series to numeric types before plotting. Once the data are numbers, Plotly uses a numeric y-axis and the bit levels will be rendered with 0 at the bottom and 1 at the top, consistently across all columns.

import pandas as pd
import plotly.graph_objects as go

# Ensure numeric types for all relevant columns
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()

Why this matters

Binary telemetry, protocol analysis and digital signal plotting often rely on the visual convention that higher logical states appear higher on the axis. Mixed dtypes inside a DataFrame can undermine that assumption in subtle ways that are easy to miss during exploratory analysis, and can lead to incorrect interpretations of bit transitions. Ensuring consistent numeric types prevents category ordering from interfering with the intended view.

Takeaways

Before plotting binary data in Plotly, verify that columns are not stored as text. Convert them to numeric to force a proper numeric y-axis and predictable 0/1 positioning. When sharing issues for troubleshooting, include a small, reproducible data sample rather than images so the behavior can be reproduced and validated quickly.