0

I'd like to add some annotations to Plotly Sankey diagram.
And I want to draw them right over the blocks of sankey nodes (with the same x-position) but couldn't find the way to do it, or even to find the X coordinates of nodes. (Think it would be better to get them and not to add manually, because number of sankey levels could change)

If we'll take this basic example, I want to add "A" "B" and "C" labels over corresponding nodes

import plotly.graph_objects as go

fig = go.Figure(data=[go.Sankey(
    node = dict(
      pad = 15,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = ["A1", "A2", "B1", "B2", "C1", "C2"],
      color = "blue"
    ),
    link = dict(
      source = [0, 1, 0, 2, 3, 3], # indices correspond to labels, eg A1, A2, A1, B1, ...
      target = [2, 3, 3, 4, 4, 5],
      value = [8, 4, 2, 8, 4, 2]
  ))])

fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)
fig.show()
Denis Ka
  • 137
  • 1
  • 1
  • 10

2 Answers2

3

You can use fig.add_annotation() in this case. Add the following lines below line with fig.update_layout()

fig.add_annotation(dict(font=dict(color="black",size=12), x=0, y=1.06, showarrow=False, text='<b>A</b>'))
fig.add_annotation(dict(font=dict(color="black",size=12), x=0.5, y=1.06, showarrow=False, text='<b>B</b>'))
fig.add_annotation(dict(font=dict(color="black",size=12), x=1, y=1.06, showarrow=False, text='<b>C</b>'))

You will get the figure as follows. You can modify the code depending on your requirement. enter image description here

hbstha123
  • 1,260
  • 11
  • 23
  • it's good, but label positions added manualy (x and y) . Is there any way to automate their detection to make them depended on sankey nodes? – Denis Ka Oct 27 '21 at 09:49
  • I think it should be evenly distributed between 0 and 1. As you have 3 set of nodes here (A, B and C), the x position is 0, 1/2, 1. If there is fourth set say D, the x-position should be 0, 1/3, 2/3, 1. – hbstha123 Oct 27 '21 at 10:39
  • oh! think it's a good idea, will try it, thanks. – Denis Ka Oct 27 '21 at 13:44
1

Here's an unnecessary expansion of a previous answer.

If we start with the basic diagram:

import plotly.graph_objects as go

fig = go.Figure(data=[go.Sankey(
    node = dict(
      pad = 15,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = ["A1", "A2", "B1", "B2", "C1", "C2"],
      color = "blue"
    ),
    link = dict(
      source = [0, 1, 0, 2, 3, 3], # indices correspond to labels, eg A1, A2, A1, B1, ...
      target = [2, 3, 3, 4, 4, 5],
      value = [8, 4, 2, 8, 4, 2]
  ))])
fig.write_image("fig1.png")
fig.show()

Then add annotations. If we don't specify the location it will be in the middle of the plot.

fig.add_annotation(text='<b>DEFAULT</b>',font_color="red") # unspecified position

We can specify locations using x,y coordinates:

fig.add_annotation(x=0, y=0, text='<b>(0,0)</b>', font_color="red")
fig.add_annotation(x=1, y=1, text='<b>(1,1)</b>', font_color="red")

Now fig.show() gives us this: locations of (1,1) and (0,0) on plot

Now that we know the layout we can put the desired labels into a list and use that to position them automatically as follows:

lab_list = ['<b>A</b>','<b>B</b>','<b>C</b>']
for i, text in enumerate(lab_list):
    x_val = i / (len(lab_list)-1)
    fig.add_annotation(
        x=x_val, 
        y=1.06, 
        text=text,
        showarrow=False
    )

Now fig.show() yields the plot with the properly positioned annotations. enter image description here

Arthur Morris
  • 1,253
  • 1
  • 15
  • 21