Smallest Example

The absolute minimum needed to create a Sankey diagram is a links data frame with one row per link and columns that define the source and target as 0-based integer values. By default, all links will be of width 1.

links <- data.frame(
  source = c(0, 0, 0, 1, 2),
  target = c(1, 2, 3, 4, 4)
)

sankeyNetwork(
  Links = links,
  Source = "source",
  Target = "target"
)

Labels and Values

One may also provide

  • a nodes data frame to e.g. have proper labels for each node.
  • values in the links data frame that define the width of each link.
  • a unit within sankeyNetwork() which is only visible when hovering over a link or node in the resulting diagram.

We will from now on create tibbles via tribble() instead of data.frames() for better readability.

links <- tribble(
  ~source, ~target, ~value,
  0,       1,       3.7,
  0,       2,       22.9,
  0,       3,       57.7,
  1,       4,       3.7,
  2,       4,       22.9
)

nodes <- tribble(
  ~id, ~label,
  0,   "German residents",
  1,   "Berlin Residents",
  2,   "Other cities (>100k)",
  3,   "Non-Metropolitans",
  4,   "Metropolitans (>100k)"
)

sankeyNetwork(
  Links = links,
  Source = "source",
  Target = "target",
  Value = "value",
  units = "mio. people",
  Nodes = nodes,
  NodeID = "label"
)

You can have link-specific colors and node-specific colors:

links <- tribble(
  ~source, ~target, ~value, ~linkcolor,
  0,       1,       3.7,    "#e56b6f",
  0,       2,       22.9,   "#e56b6f",
  0,       3,       57.7,   "#355070",
  1,       4,       3.7,    "#e56b6f",
  2,       4,       22.9,   "#e56b6f"
)

nodes <- tribble(
  ~id, ~label,                  ~nodecolor,
  0,   "German residents",      "#6d597a",
  1,   "Berlin Residents",      "#eaac8b",
  2,   "Other cities (>100k)",  "#b56576",
  3,   "Non-Metropolitans",     "#355070",
  4,   "Metropolitans (>100k)", "#e56b6f"
)

sankeyNetwork(
  Links = links,
  Source = "source",
  Target = "target",
  Value = "value",
  linkColor = "linkcolor",
  Nodes = nodes,
  NodeID = "label",
  NodeColor = "nodecolor",
  units = "mio. people",
)

Vertical Node Positioning

You can enforce the vertical order of nodes via NodePosY.

links <- tribble(
  ~source, ~target, ~value,
  0,       1,       3.7,
  0,       2,       22.9,
  0,       3,       57.7,
  1,       4,       3.7,
  2,       4,       22.9
)

nodes <- tribble(
  ~id, ~label,                  ~yorder,
  0,   "German residents",      1,      
  1,   "Berlin Residents",      1,      
  2,   "Other cities (>100k)",  3,       
  3,   "Non-Metropolitans",     2,      
  4,   "Metropolitans (>100k)", 1    
)

sankeyNetwork(
  Links = links,
  Source = "source",
  Target = "target",
  Value = "value",
  units = "mio. people",
  Nodes = nodes,
  NodeID = "label",
  NodePosY = "yorder"
)

Horizontal Node Positioning

You can enforce a node’s horizontal position via NodePosX and label the x-Axis via xAxisDomain. However, as pointed out in this issue, changing fontSize unfortunately does not affect xAxisDomain.

links <- tribble(
  ~source, ~target, ~value,
  0,       1,       3.7,
  0,       2,       22.9,
  0,       3,       57.7,
  1,       4,       3.7,
  2,       4,       22.9
)

nodes <- tribble(
  ~id, ~label,                  ~xpos,
  0,   "German residents",      0,
  1,   "Berlin Residents",      1,
  2,   "Other cities (>100k)",  1,
  3,   "Non-Metropolitans",     2,
  4,   "Metropolitans (>100k)", 2     
)

sankeyNetwork(
  Links = links,
  Source = "source",
  Target = "target",
  Value = "value",
  units = "mio. people",
  Nodes = nodes,
  NodeID = "label",
  NodePosX = "xpos",
  xAxisDomain = c("Germany", "Berlin vs. other cities", "City vs. rural")
)