Reputation: 93
I am drawing a a sankey diagram where values go from 1 start node to 5 notes (A, B, C, D and E). I would like the nodes to be plotted in alphabetical order and I thought this could be achieved by my code but this is not the case as you can see from running my code - how can I make sure that A is followed by B, and B followed by C etc.?
I have Python 3.9 and updated plotly to version 4.12.0 but it did not help. I run the code in both Jupyter notebook and in Spyder (4.15) but the order of the nodes is off - can you advice how I can specify the order within the code?
import plotly.graph_objects as go
import plotly.express as px
source = [0, 0, 0, 0, 0]
target = [1, 2, 3, 4, 5]
value = [356, 16, 39, 6, 88]
label = ['Start', 'A', 'B', 'C', 'D', 'E']
color_node = ['#EBBAB5',
'#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD']
color_link = ['#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD',
'#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD','#EBBAB5', '#FEF3C7', '#A6E3D7','#98FB98', '#DDA0DD']
link = dict(source=source, target=target, value = value, color = color_link)
node = dict(label = label, pad=30, thickness=5, color = color_node)
data = go.Sankey(link = link, node = node)
fig = go.Figure(data)
fig.show()
Upvotes: 2
Views: 4758
Reputation: 143
You can make use of this feature.
For example, this does the trick, although it's fairly manual:
n = 1/4
link = dict(source=source, target=target, value = value, color = color_link)
node = dict(label = label,
x = [0, 1, 1, 1, 1, 1],
y = [0, 0*n, 1*n, 2*n, 3*n, 4*n],
pad=30,
thickness=5,
color = color_node)
data = go.Sankey(
link = link,
node = node,
arrangement = "snap",
)
fig = go.Figure(data)
fig.show()
What I did is just specify the position of the nodes: x==0
for the first column and x==1
for the second. For the y
's I used even spacing between 0 and 1 for the nodes in the second column. I expected some overlapping of nodes, but it seems the logic in plotly.js solves that for you.
You can do the trick programmatically by specifying two lists of labels:
label_l = ['Start', ]
label_r = [ 'A', 'B', 'C', 'D', 'E']
...
node = dict(label = label_l + label_r,
x = [0, ]*len(label_l) + [1,]*len(label_r),
y = list(np.linspace(0,1,len(label_l))) + list(np.linspace(0,1,len(label_r))),
pad=30,
thickness=5,
color = color_node)
However, I don't guarantee it works for more complex cases.
Upvotes: 4