1

I started using plotly to draw sankey charts. I want to display a multi year series with birth and death year by year.

The current code looks like: `

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 = ["v11","v21","v31","v41","out21","out31","out41","in21","in31","in41", "v12", "v22"],
      color = "blue"
    ),
    link = dict(
      source = [0, 7, 0, 1, 8, 1, 2, 9, 2, 10], # 
      target = [1, 1, 4, 2, 2, 5, 3, 3, 6,11],
      value = [1000, 100, 100, 1000, 150, 50, 1000, 120, 80, 800]
  ))])

fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)
fig.show()

`

which produces something like: Sankey

All birth nodes are attached to the left side and the out nodes to the right side. It should however look like this:

Sankey manually rearranged

Is there a way to pin the x-axis? Or any d3 example, which does the trick?

Thanks for any hint, Carl

PS: With the following question I got one step further [https://stackoverflow.com/questions/61152889/plotly-how-to-set-node-positions-in-a-sankey-diagram]. The look like this now:

import plotly.graph_objects as go

unique_list = ["c0_v_2021","c0_v_2022","c0_v_2023","c0_v_2024","c0_o_2022","c0_o_2023","c0_o_2024","c0_i_2022","c0_i_2023","c0_i_2024"]
title_list = ["Vol 2021","Vol 2022","Vol 2023","Vol 2024","Out 2022","Out 2023","Out 2024","In 2022","In 2023","In 2024"]
sources = [0, 7, 0, 1, 8, 1, 2, 9, 2]
targets = [1, 1, 4, 2, 2, 5, 3, 3, 6]
values = [1000, 100, 100, 1000, 150, 50, 1000, 120, 80]

## correction based on type
def my_corr(node_corr, steps):
    x_corr = []
    y_corr = []
    for ftype in node_corr:
        xcorr = 0 
        ycorr = 0
        if ftype == 'i':
            xcorr = - steps/3
            ycorr = -0.2

        x_corr.append(xcorr) 
        y_corr.append(ycorr) 
          
    return x_corr   , y_corr
def my_nodify (node_names):
    # node_names = unique_list.copy()
    # unique name endings 
    ## get year
    ends = sorted(list(set([e[-4:] for e in node_names])))
    ## get type
    corr = (list(([e[-6] for e in node_names])))
    min, max = ends[0], ends[-1]
    #intervals 
    steps = 1/((int(max)-int(min)))
    x_corr, y_corr = my_corr(corr, steps)


    # x-values for each unique name ending for input as node position 
    nodes_x = {}
    xVal = 0
    for e in ends: 
        nodes_x[str(e)] = xVal
        xVal += steps 
    #x and y values in list form
    x_values = [nodes_x[n[-4:]] for n in node_names]
    ## apply x adjustments
    x_values_c = [x_values[i] + x_corr[i] for i in range(len(x_corr))]
    y_values = []
    y_val = 0
    for n in node_names:
        y_values.append(y_val)
        y_val+=.001
    y_values.append(y_val)    
    ## apply y adjustments
    y_values_c = [y_values[i] + y_corr[i] for i in range(len(y_corr))]    
#    y_values_c = y_values
    return x_values_c, y_values_c     
nodified = my_nodify(unique_list)
# plotly setup
fig = go.Figure(data=[go.Sankey(
      arrangement='snap',
#      arrangement='perpendicular',
      node = dict(
      pad = 5,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = title_list,
      color = "blue",
      x=nodified[0],      y=nodified[1]


    ),
    link = dict(
      source = sources,
      target = targets,
      value = values
  ))])

fig.update_layout(
    hovermode = 'x',
    title="Some Flow",
    font=dict(size = 10, color = 'white'),
    plot_bgcolor='black',
    paper_bgcolor='black'
)
fig.show()

and produces almost what I want although the In-nodes overlapp and the sorting of link is inconsistent. New Plot

How can I influence this behaviour?

Carl Brenz
  • 11
  • 3
  • With the help of [https://stackoverflow.com/questions/61152889/plotly-how-to-set-node-positions-in-a-sankey-diagram] I got a step further. – Carl Brenz Dec 27 '22 at 17:26

0 Answers0