Sankey Diagram in F#

How to make sankey charts in F# with Plotly.


In [1]:
#r "nuget: Plotly.NET,2.0.0-preview.8"
#r "nuget: Plotly.NET.Interactive,2.0.0-preview.8"
#r "nuget: FSharp.Data"
Installed Packages
  • FSharp.Data, 4.2.4
  • Plotly.NET, 2.0.0-preview.8
  • Plotly.NET.Interactive, 2.0.0-preview.8

Loading extensions from Plotly.NET.Interactive.dll

Added Kernel Extension including formatters for Plotly.NET charts.

A Sankey diagram is a flow diagram, in which the width of arrows is proportional to the flow quantity.

Basic Sankey Diagram

Sankey diagrams visualize the contributions to a flow by defining source to represent the source node, target for the target node, value to set the flow volume, and label that shows the node name.

In [2]:
open Plotly.NET

let nodes =
    [| Node.Create("A1")
       Node.Create("A2")
       Node.Create("B1")
       Node.Create("B2")
       Node.Create("C1")
       Node.Create("C2") |]

Chart.Sankey(
    nodePadding = 15.,
    nodeColor = "blue",
    nodeThickness = 20.0,
    nodeLineWidth = 0.5,
    nodes = (nodes |> Seq.ofArray),
    links =
        [ Link.Create(src = nodes.[0], tgt = nodes.[2], value = 8.)
          Link.Create(src = nodes.[1], tgt = nodes.[3], value = 4.)
          Link.Create(src = nodes.[0], tgt = nodes.[3], value = 3.)
          Link.Create(src = nodes.[2], tgt = nodes.[4], value = 8.)
          Link.Create(src = nodes.[3], tgt = nodes.[4], value = 4.)
          Link.Create(src = nodes.[3], tgt = nodes.[5], value = 2.) ]
)
|> Chart.withLayout (Layout.init (Title = Title.init ("Basic Sankey Diagram"), Font = Font.init (Size = 10.)))
Out[2]:

More complex Sankey diagram with colored links

In [3]:
open FSharp.Data

type remoteData =
    JsonProvider<"https://raw.githubusercontent.com/plotly/plotly.js/master/test/image/mocks/sankey_energy.json">

let data =
    remoteData.Load("https://raw.githubusercontent.com/plotly/plotly.js/master/test/image/mocks/sankey_energy.json")

let node = data.Data.[0].Node
let node_labels = data.Data.[0].Node.Label
let node_color = data.Data.[0].Node.Color
let source = data.Data.[0].Link.Source
let target = data.Data.[0].Link.Target
let values = data.Data.[0].Link.Value

let nodes =
    [ for i in 0 .. node_labels.Length - 1 -> Node.Create(label = node_labels.[i], color = node_color.[i]) ]

let links =
    [ for i in 0 .. source.Length - 1 ->
          Link.Create(src = nodes.[source.[i]], tgt = nodes.[target.[i]], value = float values.[i]) ]

let title =
    "Energy forecast for 2050<br>Source: Department of Energy & Climate Change, Tom Counsell via <a href='https://bost.ocks.org/mike/sankey/'>Mike Bostock</a>"

Chart.Sankey(nodes = nodes, links = links, nodePadding = float node.Pad, nodeThickness = float node.Thickness)

|> Chart.withLayout (Layout.init (Width = 1000, Font = Font.init (Size = 10.), Title = Title.init (title)))
Out[3]:

Style Sankey Diagram

This example also uses hovermode to enable multiple tooltips.

In [4]:
open FSharp.Data

type remoteData =
    JsonProvider<"https://raw.githubusercontent.com/plotly/plotly.js/master/test/image/mocks/sankey_energy.json">

let data =
    remoteData.Load("https://raw.githubusercontent.com/plotly/plotly.js/master/test/image/mocks/sankey_energy.json")

let node = data.Data.[0].Node
let node_labels = data.Data.[0].Node.Label
let node_color = data.Data.[0].Node.Color
let source = data.Data.[0].Link.Source
let target = data.Data.[0].Link.Target
let values = data.Data.[0].Link.Value

let nodes =
    [ for i in 0 .. node_labels.Length - 1 -> Node.Create(label = node_labels.[i], color = node_color.[i]) ]

let links =
    [ for i in 0 .. source.Length - 1 ->
          Link.Create(src = nodes.[source.[i]], tgt = nodes.[target.[i]], value = float values.[i]) ]

let title =
    "Energy forecast for 2050<br>Source: Department of Energy & Climate Change, Tom Counsell via <a href='https://bost.ocks.org/mike/sankey/'>Mike Bostock</a>"

Chart.Sankey(nodes = nodes, links = links, nodePadding = float node.Pad, nodeThickness = float node.Thickness)

|> Chart.withLayout (
    Layout.init (
        Width = 1000,
        Font = Font.init (Size = 10., Color = Color.fromString "white"),
        Title = Title.init (title),
        PlotBGColor = Color.fromString "gray",
        PaperBGColor = Color.fromString "gray",
        HoverMode = StyleParam.HoverMode.X
    )
)
Out[4]:

Hovertemplate and customdata of Sankey diagrams (Missing Abstractions-Not finished)

Define Node Position (Missing Abstractions-Not finished)