Skip to content

Explicit node coordinates (x/y positions) not fully respected in Sankey diagram #7758

Open
plotly/plotly.py
#5548

Description

@DanielYang59

We (@janosh) are trying to generate a Sankey diagram but for some reason the explicit coordinates are not fully respected. The "right_a" node has a coordinate of (0.9, 0.05) (top right), but for some reason shows at bottom left.

plotly 6.3.1, macos 26.0.1

import plotly.graph_objects as go


labels = ["left_a", "left_b", "left_c", "left_d", "left_e", "left_f", "left_g", "left_h", "left_i", "left_j", "left_k", "left_l", "left_m",
    "left_n", "left_o", "left_p", "left_q", "left_r",
    "right_a", "right_b", "right_c", "right_d", "right_e", "right_f", "right_g", "right_h", "right_i", "right_j", "right_k", "right_l"]

node_pos = {
    "left_a": (0.1, 0.1), "left_b": (0.1, 0.14), "left_c": (0.1, 0.18), "left_d": (0.1, 0.23),
    "left_e": (0.1, 0.27), "left_f": (0.1, 0.31), "left_g": (0.1, 0.35),
    "left_h": (0.1, 0.40), "left_i": (0.1, 0.44), "left_j": (0.1, 0.48),
    "left_k": (0.1, 0.52), "left_l": (0.1, 0.56), "left_m": (0.1, 0.61),
    "left_n": (0.1, 0.65), "left_o": (0.1, 0.69), "left_p": (0.1, 0.73),
    "left_q": (0.1, 0.77), "left_r": (0.1, 0.82),
    "right_a": (0.9, 0.05),
    "right_b": (0.9, 0.15), "right_c": (0.9, 0.25), "right_d": (0.9, 0.35), "right_e": (0.9, 0.45), "right_f": (0.9, 0.55), "right_g": (0.9, 0.65),
    "right_h": (0.9, 0.75), "right_i": (0.9, 0.85), "right_j": (0.9, 0.93), "right_k": (0.9, 0.97), "right_l": (0.9, 0.99)}

sources = [0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10,
    10, 10, 11, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 18, 18, 18, 19, 19, 19, 19, ]

targets = [23, 21, 20, 26, 30, 20, 24, 22, 21, 20, 20, 25, 29, 22, 22, 29, 20, 20, 22, 25, 24, 29, 20, 22, 29, 21, 21, 20, 24, 30, 22,
    20, 20, 21, 25, 22, 30, 28, 24, 29, 20, 21, 24, 20, 20, 22, 20, 23, 21, 24, 31, 25, 21, 22, 20, 23, 30, 27, 26, 24, 21, 20, 22,
    23, 30, 25, 20, 21, 22, 20, 21, 25, 20, 22, 21, 24, ]
values = [1 for _ in targets]
assert len(sources) == len(targets) == len(values)

x_positions: list[float] = [node_pos[lbl][0] for lbl in labels]
y_positions: list[float] = [node_pos[lbl][1] for lbl in labels]

fig = go.Figure(
    go.Sankey(
        arrangement="fixed",
        node=dict(
            label=labels,
            x=x_positions,
            y=y_positions,
        ),
        link=dict(
            source=sources,
            target=targets,
            value=values,
        ),
    )
)

# fig.show()

fig.write_image("debug.svg", format="svg")

Image

Activity

  1. changed the title [-]Explicit coordinates (x/y positions) not fully respected in Sankey diagram[/-] [+]Explicit node coordinates (x/y positions) not fully respected in Sankey diagram[/+] on Oct 25, 2025
  2. FredericoMendes10 commented on Mar 16, 2026

    @FredericoMendes10

    I'm working on it!

  3. FredericoMendes10 commented on Apr 17, 2026

    @FredericoMendes10

    After digging into this issue, I found two related root causes that explain why x/y positions are misapplied in Sankey diagrams with arrangement='fixed':

    1. Isolated nodes: Plotly.js excludes nodes with no valid links from its internal b.nodes array, then applies i.node.x[p] to b.nodes[p] assuming a 1:1 index correspondence. When isolated nodes appear before connected nodes in the original array, this correspondence breaks and positions are applied to the wrong nodes.

    2. Phantom nodes: Out-of-bounds source/target indices cause Plotly.js to compute _ = max(sources + targets) + 1, inflating b.nodes with unlabelled entries that further misalign the index mapping.

    I submitted PR plotly/plotly.py#5548 which works around both issues on the plotly.py side by reordering per-node arrays before rendering (so isolated nodes appear last), but as noted in the PR review, this only fixes static image export via Kaleido. The underlying fix should live in plotly.js itself.

    I'd be happy to explore a plotly.js fix at some point, though I can't take it on right now.

  4. emilykl commented on Apr 17, 2026

    @emilykl
    Contributor

    Thanks for looking into this issue, @FredericoMendes10 ! Since the root cause lies in Plotly.js, I'm going to transfer the issue there.

  5. transferred this issue fromplotly/plotly.pyon Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3backlogbugsomething brokengood first issuesuitable for newcomers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions