Repository navigation
Explicit node coordinates (x/y positions) not fully respected in Sankey diagram #7758
Copy link
Copy link
Open
plotly/plotly.py
#5548Labels
P3backlogbacklogbugsomething brokensomething brokengood first issuesuitable for newcomerssuitable for newcomers
Description
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")Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P3backlogbacklogbugsomething brokensomething brokengood first issuesuitable for newcomerssuitable for newcomers
Activity
[-]Explicit coordinates (x/y positions) not fully respected in Sankey diagram[/-][+]Explicit node coordinates (x/y positions) not fully respected in Sankey diagram[/+]FredericoMendes10 commentedon Mar 16, 2026
I'm working on it!
plotly#5381
Fix #5381: right_a node ignores assigned coordinates when rendering g…
Fix #5381: right_a node ignores assigned coordinates when rendering g…
Fix #5381: right_a node ignores assigned coordinates when rendering g…
Fix #5381: right_a node ignores assigned coordinates
Fix #5381: right_a ignores assigned coordinates when rendering
Fix plotly#5381: wrong x/y positions in Sankey with isolated nodes
Fix plotly#5381: wrong x/y positions in Sankey with isolated nodes
FredericoMendes10 commentedon Apr 17, 2026
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':Isolated nodes: Plotly.js excludes nodes with no valid links from its internal
b.nodesarray, then appliesi.node.x[p]tob.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.Phantom nodes: Out-of-bounds source/target indices cause Plotly.js to compute
_ = max(sources + targets) + 1, inflatingb.nodeswith 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.
emilykl commentedon Apr 17, 2026
Thanks for looking into this issue, @FredericoMendes10 ! Since the root cause lies in Plotly.js, I'm going to transfer the issue there.