2D Histograms in F#

How to make 2D Histograms in F# with Plotly.


In [1]:
#r "nuget: Newtonsoft.Json, 12.0.3"
#r "nuget: Plotly.NET, 2.0.0-preview.9"
#r "nuget: Plotly.NET.Interactive, 2.0.0-preview.9"
#r "nuget: Deedle"
#r "nuget: FSharp.Data"
#r "nuget: FSharp.Stats"
Installed Packages
  • Deedle, 2.4.3
  • FSharp.Data, 4.2.4
  • FSharp.Stats, 0.4.2
  • Newtonsoft.Json, 12.0.3
  • Plotly.NET, 2.0.0-preview.9
  • Plotly.NET.Interactive, 2.0.0-preview.9

Loading extensions from Plotly.NET.Interactive.dll

Added Kernel Extension including formatters for Plotly.NET charts.

2D Histograms or Density Heatmaps

A 2D histogram, also known as a density heatmap, is the 2-dimensional generalization of a histogram which resembles a heatmap but is computed by grouping a set of points specified by their x and y coordinates into bins, and applying an aggregation function such as count or sum (if z is provided) to compute the color of the tile representing the bin. This kind of visualization (and the related 2D histogram contour, or density contour) is often used to manage over-plotting, or situations where showing large data sets as scatter plots would result in points overlapping each other and hiding patterns.

In [2]:
open Plotly.NET
open Deedle
open FSharp.Data

let data=
    Http.RequestString "https://raw.githubusercontent.com/plotly/datasets/master/tips.csv"
    |> fun csv -> Frame.ReadCsvString(csv,true,separators=",")
    

let getColumnData column=
        data
        |> Frame.getCol column
        |> Series.values
        |> Array.ofSeq

let y:float[] = getColumnData "tip"
let x:float[] = getColumnData "total_bill"

Chart.Histogram2d(x,y,Showscale=true)
Out[2]:

The number of bins can be controlled with nBinsx and nBinsy and the color scale with colorscale.

In [3]:
open Plotly.NET
open Deedle
open FSharp.Data

let data=
    Http.RequestString "https://raw.githubusercontent.com/plotly/datasets/master/tips.csv"
    |> fun csv -> Frame.ReadCsvString(csv,true,separators=",")
    

let getColumnData column=
        data
        |> Frame.getCol column
        |> Series.values
        |> Array.ofSeq

let y:float[] = getColumnData "tip"
let x:float[] = getColumnData "total_bill"

Chart.Histogram2d(x,y,Showscale=true,nBinsx=20,nBinsy=20,Colorscale=StyleParam.Colorscale.Viridis)
Out[3]:

2D Histogram of a Bivariate Normal Distribution

In [4]:
open FSharp.Stats.Distributions

let n  = 20

let xs = 
    let normal = Continuous.normal 500. 20.
    [300..700]|> Seq.map (fun x -> normal.Sample())

let ys = 
    let normal = Continuous.normal 500. 20.
    [300..700]|> Seq.map (fun x -> normal.Sample())

Chart.Histogram2d(x=xs,y=ys,nBinsx=n,nBinsy=n)
Out[4]:

2D Histogram Binning and Styling Options

In [5]:
open FSharp.Stats.Distributions
open Plotly.NET.TraceObjects

let n  = 20

let xs = 
    let normal = Continuous.normal 500. 20.
    [300..700]|> Seq.map (fun x -> normal.Sample())

let ys = 
    let normal = Continuous.normal 500. 20.
    [300..700]|> Seq.map (fun x -> normal.Sample())

let customColorscale =
    StyleParam.Colorscale.Custom [ (0.0, "rgb(12,51,131)")
                                   (0.25, "rgb(10,136,186)")
                                   (0.5, "rgb(242,211,56)")
                                   (0.75, "rgb(242,143,56)")
                                   (1.0, "rgb(217,30,30)") ]


Chart.Histogram2d(
    x = xs,
    y = ys,
    xBins = Bins.init (StartBins = 440., EndBins = 570., Size = 5.),
    yBins = Bins.init (StartBins = 440., EndBins = 570., Size = 5.),
    HistNorm = StyleParam.HistNorm.Probability,
    Colorscale= customColorscale
)
Out[5]:

2D Histogram Overlaid with a Scatter Chart

In [6]:
open System

let rand = new Random()

let x0 = [for i in 1..100 -> rand.NextDouble()]
let y0 = [for i in 1..100 -> rand.NextDouble()]

let x1 = [for i in 1..50 -> rand.NextDouble()]
let y1 = [for i in 1..50 -> rand.NextDouble()]

let x = x0 @ x1
let y =  y0 @ y1

let chart1 =
    Chart.Scatter(x = x0, y = y0, mode = StyleParam.Mode.Markers, ShowLegend = false)
    |> Chart.withMarkerStyle (
        Size = 8,
        Color = Color.fromString "white",
        Opacity = 0.7,
        Outline = Line.init (Width = 1.),
        Symbol = StyleParam.MarkerSymbol.X
    )

let chart2 =
    Chart.Scatter(x = x1, y = y1, mode = StyleParam.Mode.Markers, ShowLegend = false)
    |> Chart.withMarkerStyle (
        Size = 8,
        Color = Color.fromString "white",
        Opacity = 0.7,
        Outline = Line.init (Width = 1.)
    )

let histogra2D =
    Chart.Histogram2d(x, y, Colorscale = StyleParam.Colorscale.YIGnBu)

[ chart1; chart2; histogra2D ]
|> Chart.combine
|> Chart.withXAxisStyle (title = "", ShowGrid = false, Zeroline = false)
|> Chart.withYAxisStyle (title = "", ShowGrid = false, ZeroLine = false)
Out[6]: