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:
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.
How can I influence this behaviour?