0

I have below code, which is to add annonation for each column in the sankey chart.

library("plotly")
library("ggplot2")
library("dplyr")
library("xml2")
library("htmlwidgets")

a <- read.csv(header = TRUE, text = "date,Data Center,Customer,companyID,source,target,value 
")

node_names <- union(a$source, a$target)

node_names <- node_names[order(sub('.*_', '', node_names))]
nodes <- data.frame(name = node_names)
links <- data.frame(source = match(a$source, node_names) - 1,
                    target = match(a$target, node_names) - 1,
                    value = a$value)


definePosition <- function(nodeList){
  #  nodeList = node_names
  # unique name endings
  endings = unique(sub('.*_', '', nodeList))
  # define intervals
  steps = 1/length(endings)
  # x-values for each unique name ending
  # for input as node position
  nodes_x = {}
  xVal = 0
  for (e in endings) {
    nodes_x[e] = xVal
    xVal = xVal + steps
    
  }
  # x and y values in list form
  x_values <- 0
  y_values <- 0
  i =1
  for (n in nodeList) {
    last = sub('.*_', '', n)
    x_values[i] = nodes_x[last]
    y_values[i] = 0.001 * length(x_values)
    i = i + 1
  }
  
  return(list(x_values, y_values))
  
}

position = definePosition(node_names)
node_x = position[[1L]]
node_y = position[[2L]]

#Plot
plot_ly(type='sankey',
             orientation = "h",
             arrangement = "snap",
             node = list (
               label = node_names,
               x = node_x,
               y = node_y,
               color = "steelblue",
               pad = 15,
               thinkness = 15,
               line = list(color = "black", width = 0.5)),
               link = list(source = links$source, target = links$target, value = links$value, color = "gainsboro")) %>%
  
add_annotations(x=unique(node_x)[1],y=1,xref = "x",yref = "paper",text = "<b>step1</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[2],y=1,xref = "x",yref = "paper",text = "<b>step2</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[3],y=1,xref = "x",yref = "paper",text = "<b>step3</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[4],y=1,xref = "x",yref = "paper",text = "<b>step4</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[5],y=1,xref = "x",yref = "paper",text = "<b>step5</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[6],y=1,xref = "x",yref = "paper",text = "<b>step6</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[7],y=1,xref = "x",yref = "paper",text = "<b>step7</b>",xanchor = 'left',showarrow = F, align = "center") %>%
add_annotations(x=unique(node_x)[8],y=1,xref = "x",yref = "paper",text = "<b>step8</b>",xanchor = 'left',showarrow = F, align = "center") %>%



layout(
  title = "<b>Opportunity Marketing User Behavior Monitor(Prod environment)</b>",
  font = list(
    size = 10,
    color = 'grey'
  ),
  margin = list(
    l = 30,
    r = 50,
    b = 50,
    t = 100,
    pad = 20
  ),
  xaxis = list(showgrid = F, zeroline = F, visiable = F, showticklabels = F),
  yaxis = list(showgrid = F, zeroline = F, visiable = F, showticklabels = F)
)

but after running the code, the annonation added is not aligned with each column. My thought is to get the x-axis position for each column, and then assign to x parameters for each add_annonation. But how to know the x-axis value for each column??

peace
  • 299
  • 2
  • 16
  • Hi, I've also wrestled with plotly sankey graphs and would love to look at this further. Could you revise your question to provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) with sample data? – even_of_the_hour Feb 24 '22 at 13:06
  • hi even_of_the_hour - thank you for looking into this. I have add some sample data in the post. In add_annonation function, I also update the x parameter value from hardcoded number to a reference of the x axis's position for 8 layers. But the added 8 texts are still not aligned with 8 sankey columns as expected. – peace Feb 25 '22 at 02:44

1 Answers1

1

It appears that your definePosition() function is putting your node labels in the expected places. It is doing its job. However, it is the nodes that are not appearing where they should.

You are attempting to fix the node positions using calculated node_x and node_y vectors. However, plotly's handling of manual node positions is finicky and a bit opaque. In some cases it appears to override manual positions. I have found that in your situation, omitting one or both of the arguments x or y in node will align your nodes where expected. For example:

plot_ly(type='sankey',
        orientation = "h",
        arrangement = "snap",
        node = list (
          label = node_names,
          # x = node_x, # No longer setting node.x manually
          y = node_y,
          color = "steelblue",
          pad = 15,
          thinkness = 15,
          line = list(color = "black", width = 0.5)),
        link = list(source = links$source, target = links$target, value = links$value, color = "gainsboro")) %>%
  
  add_annotations(x=unique(node_x)[1],y=1,xref = "x",yref = "paper",text = "<b>step1</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[2],y=1,xref = "x",yref = "paper",text = "<b>step2</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[3],y=1,xref = "x",yref = "paper",text = "<b>step3</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[4],y=1,xref = "x",yref = "paper",text = "<b>step4</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[5],y=1,xref = "x",yref = "paper",text = "<b>step5</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[6],y=1,xref = "x",yref = "paper",text = "<b>step6</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[7],y=1,xref = "x",yref = "paper",text = "<b>step7</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  add_annotations(x=unique(node_x)[8],y=1,xref = "x",yref = "paper",text = "<b>step8</b>",xanchor = 'right',showarrow = F, align = "center") %>%
  
  
  
  layout(
    title = "<b>Opportunity Marketing User Behavior Monitor(Prod environment)</b>",
    font = list(
      size = 10,
      color = 'grey'
    ),
    margin = list(
      l = 30,
      r = 50,
      b = 50,
      t = 100,
      pad = 20
    ),
    xaxis = list(showgrid = F, zeroline = F, visiable = F, showticklabels = F),
    yaxis = list(showgrid = F, zeroline = F, visiable = F, showticklabels = F)
  )

This issue bugs me a lot; I ran into something similar before which was why your question interested me (Why are fixed positions for nodes in a plotly sankey graph being overridden or ignored?). I've opened an issue about it on the plotly.r github as well.

  • hello even_of_the_hout - thank you very much for the investigation. i tried your suggestion and it works. Originally, I tried to fix the node position by node_x and node_y, but i assigned the node_x value to the 'x' parameters as ell when adding annonations . so i thought from x-axis perspective, the added text and column they are positioned in same x axis position by the node-x value. but actual result is they're not. really strange behavior. – peace Feb 26 '22 at 05:26