Plotly.NET

BinderScriptNotebook

Plotly.NET provides functions for generating and rendering plotly.js charts in .NET programming languages 📈🚀.

Table of contents

Installation

Plotly.NET will be available as 2.0.0 version of its predecessor FSharp.Plotly. The feature roadmap can be seen here. Contributions are very welcome!

Old packages up until version 1.2.2 can be accessed via the old package name FSharp.Plotly here

For applications and libraries

A preview version of Plotly.NET 2.0.0 is available on nuget to plug into your favorite package manager.

You can find all available package versions on the nuget page.

  • dotnet CLI

    dotnet add package Plotly.NET --version 2.0.0-preview.6
    
  • paket CLI

    paket add Plotly.NET --version 2.0.0-preview.6
    
  • package manager

    Install-Package Plotly.NET -Version 2.0.0-preview.6
    

    Or add the package reference directly to your .*proj file:

    <PackageReference Include="Plotly.NET" Version="2.0.0-preview.6" />
    

For scripting

You can include the package via an inline package reference:

#r "nuget: Plotly.NET, 2.0.0-preview.6"

For dotnet interactive notebooks

You can use the same inline package reference as in script, but as an additional goodie, the interactive extensions for dotnet interactive have you covered for seamless chart rendering:

#r "nuget: Plotly.NET, 2.0.0-preview.6"
#r "nuget: Plotly.NET.Interactive, 2.0.0-preview.6"

Note:

due to the currently fast development cycles of Dotnet Interactive, there might be increments in their versioning that renders the current version of Plotly.NET.Interactive incompatible (example here).

If the interactive extension does not work, please file an issue and we will try to get it running again as soon as possible.

A possible fix for this is the inclusion of Dotnet.Interactive preview package sources. To use these, add the following lines before referencning Plotly.NET.Interactive:

# "nuget:https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json"
# "nuget:https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json"

Overview

Basics

The general design philosophy of Plotly.NET implements the following visualization flow:

  • initialize a GenericChart object from the data you want to visualize by using the respective Chart.* function, optionally setting some specific style parameters
  • further style the chart with fine-grained control, e.g. by setting axis titles, tick intervals, etc.
  • display (in the browser or as cell result in a notebook) or save the chart

Initializing a chart

The Chart module contains a lot of functions named after the type of chart they will create, e.g. Chart.Point will create a point chart, Chart.Scatter3d wil create a 3D scatter chart, and so on.

The respective functions all contain specific arguments, but they all have in common that the first mandatory arguments are the data to visualize.

Example: The first two arguments of the Chart.Point function are the x and y data. You can therefore initialize a point chart like this:

open Plotly.NET
let xData = [0. .. 10.]
let yData = [0. .. 10.]
let myFirstChart = Chart.Point(xData,yData)

Styling a chart

Styling functions are generally the Chart.with* naming convention. The following styling example does:

  • set the chart title via Chart.withTitle
  • set the x axis title and removes the gridline from the axis via Chart.withX_AxisStyle
  • set the y axis title and removes the gridline from the axis via Chart.withY_AxisStyle
let myFirstStyledChart =
    Chart.Point(xData,yData)
    |> Chart.withTitle "Hello world!"
    |> Chart.withX_AxisStyle ("xAxis", Showgrid=false)
    |> Chart.withY_AxisStyle ("yAxis", Showgrid=false)

Attention: Styling functions mutate 😈 the input chart, therefore possibly affecting bindings to intermediary results. We recommend creating a single chart for each workflow to prevent unexpected results

Displaying a chart in the browser

The Chart.Show function will open a browser window and render the input chart there. When working in a notebook context, after referencing Plotly.NET.Interactive, the function is not necessary, just end the cell with the value of the chart.

myFirstChart
|> Chart.Show

Should render this chart in your brower:

myFirstStyledChart
|> Chart.Show

And here is what happened after applying the styles from above:

Displaying a chart in a notbook cell output

In a notebook context you usually have (at leat when running on a jupyter server like binder) no access to the browser on the machine where plotly runs on. That's why you can render charts directly in the cell output. Just end the cell with the chart value:

let xData' = [0. .. 10.]
let yData' = [0. .. 10.]
Chart.Point(xData',yData')

Here is the styled chart:

Chart.Point(xData,yData)
|> Chart.withTitle "Hello world!"
|> Chart.withX_AxisStyle ("xAxis", Showgrid=false)
|> Chart.withY_AxisStyle ("yAxis", Showgrid=false)

Comparison: Usage in F# and C#

One of the main design points of Plotly.NET it is to provide support for multiple flavors of chart generation. Here are 2 examples in different styles and languages that create an equivalent chart:

Functional pipeline style in F#:

[(1,5);(2,10)]
|> Chart.Point
|> Chart.withTraceName("Hello from F#",Showlegend=true)
|> Chart.withY_AxisStyle("xAxis",Showgrid= false, Showline=true)
|> Chart.withX_AxisStyle("yAxis",Showgrid= false, Showline=true)

Fluent interface style in C#:

static void Main(string[] args)
{
    double[] x = new double[] { 1, 2 };
    double[] y = new double[] { 5, 10 };
    GenericChart.GenericChart chart = Chart.Point(x: x, y: y);
    chart
        .WithTraceName("Hello from C#", true)
        .WithX_AxisStyle(title: "xAxis", Showgrid: false, Showline: true)
        .WithY_AxisStyle(title: "yAxis", Showgrid: false, Showline: true)
        .Show();
}

Declarative style in F# using the underlying DynamicObj:

let xAxis = 
    let tmp = Axis.LinearAxis()
    tmp?title <- "xAxis"
    tmp?showgrid <- false
    tmp?showline <- true    
    tmp

let yAxis =
    let tmp = Axis.LinearAxis()
    tmp?title <- "yAxis"
    tmp?showgrid <- false
    tmp?showline <- true    
    tmp

let layout =
    let tmp = Layout()
    tmp?xaxis <- xAxis
    tmp?yaxis <- yAxis
    tmp?showlegend <- true
    tmp

let trace = 
    let tmp = Trace("scatter")
    tmp?x <- [1;2]
    tmp?y <- [5;10]
    tmp?mode <- "markers"
    tmp?name <- "Hello from F#"
    tmp

GenericChart.ofTraceObject(trace)
|> GenericChart.setLayout layout

Declarative style in C# using the underlying DynamicObj:

static void Main(string[] args)
{
    double[] x = new double[] { 1, 2 };
    double[] y = new double[] { 5, 10 };

    Axis.LinearAxis xAxis = new Axis.LinearAxis();
    xAxis.SetValue("title", "xAxis");
    xAxis.SetValue("showgrid", false);
    xAxis.SetValue("showline", true);

    Axis.LinearAxis yAxis = new Axis.LinearAxis();
    yAxis.SetValue("title", "yAxis");
    yAxis.SetValue("showgrid", false);
    yAxis.SetValue("showline", true);

    Layout layout = new Layout();
    layout.SetValue("xaxis", xAxis);
    layout.SetValue("yaxis", yAxis);
    layout.SetValue("showlegend", true);

    Trace trace = new Trace("scatter");
    trace.SetValue("x", x);
    trace.SetValue("y", y);
    trace.SetValue("mode", "markers");
    trace.SetValue("name", "Hello from C#");

    GenericChart
        .ofTraceObject(trace)
        .WithLayout(layout)
        .Show();
}

Contributing and copyright

The project is hosted on GitHub where you can report issues, fork the project and submit pull requests. If you're adding a new public API, please also consider adding samples that can be turned into a documentation. You might also want to read the library design notes to understand how it works.

The library is available under Public Domain license, which allows modification and redistribution for both commercial and non-commercial purposes. For more information see the License file in the GitHub repository.

namespace Plotly
namespace Plotly.NET
val xData : float list
val yData : float list
val myFirstChart : GenericChart.GenericChart
type Chart =
  static member Area : x:seq<#IConvertible> * y:seq<#IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Dash:DrawingStyle * ?Width:float -> GenericChart + 1 overload
  static member Bar : keys:seq<#IConvertible> * values:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:string * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart + 1 overload
  static member BoxPlot : ?x:'a0 * ?y:'a1 * ?Name:string * ?Showlegend:bool * ?Color:string * ?Fillcolor:'a2 * ?Opacity:float * ?Whiskerwidth:'a3 * ?Boxpoints:Boxpoints * ?Boxmean:BoxMean * ?Jitter:'a4 * ?Pointpos:'a5 * ?Orientation:Orientation * ?Marker:Marker * ?Line:Line * ?Alignmentgroup:'a6 * ?Offsetgroup:'a7 * ?Notched:bool * ?NotchWidth:float * ?QuartileMethod:QuartileMethod -> GenericChart + 1 overload
  static member Bubble : x:seq<#IConvertible> * y:seq<#IConvertible> * sizes:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:Orientation * ?GroupNorm:GroupNorm * ?UseWebGL:bool -> GenericChart + 1 overload
  static member Candlestick : open:seq<#IConvertible> * high:seq<#IConvertible> * low:seq<#IConvertible> * close:seq<#IConvertible> * x:seq<#IConvertible> * ?Increasing:Line * ?Decreasing:Line * ?WhiskerWidth:float * ?Line:Line * ?XCalendar:Calendar -> GenericChart + 1 overload
  static member ChoroplethMap : locations:seq<string> * z:seq<#IConvertible> * ?Text:seq<#IConvertible> * ?Locationmode:LocationFormat * ?Autocolorscale:bool * ?Colorscale:Colorscale * ?Colorbar:Colorbar * ?Marker:Marker * ?GeoJson:'a2 * ?FeatureIdKey:string * ?Zmin:float * ?Zmax:float -> GenericChart
  static member ChoroplethMapbox : locations:seq<#IConvertible> * z:seq<#IConvertible> * geoJson:'a2 * ?FeatureIdKey:string * ?Text:seq<#IConvertible> * ?Below:string * ?Colorscale:Colorscale * ?Colorbar:Colorbar * ?ZAuto:bool * ?ZMin:float * ?ZMid:float * ?ZMax:float -> GenericChart
  static member Column : keys:seq<#IConvertible> * values:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:string * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart + 1 overload
  static member Contour : data:seq<#seq<'a1>> * ?X:seq<#IConvertible> * ?Y:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?Opacity:float * ?Colorscale:Colorscale * ?Showscale:'a4 * ?zSmooth:SmoothAlg * ?Colorbar:'a5 -> GenericChart (requires 'a1 :> IConvertible)
  static member DensityMapbox : lon:seq<#IConvertible> * lat:seq<#IConvertible> * ?Z:seq<#IConvertible> * ?Radius:float * ?Opacity:float * ?Text:seq<#IConvertible> * ?Below:string * ?Colorscale:Colorscale * ?Colorbar:Colorbar * ?Showscale:bool * ?ZAuto:bool * ?ZMin:float * ?ZMid:float * ?ZMax:float -> GenericChart + 1 overload
  ...
static member Chart.Point : xy:seq<#System.IConvertible * #System.IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:StyleParam.Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<#System.IConvertible> * ?TextPosition:StyleParam.TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:StyleParam.Orientation * ?GroupNorm:StyleParam.GroupNorm * ?UseWebGL:bool -> GenericChart.GenericChart
static member Chart.Point : x:seq<#System.IConvertible> * y:seq<#System.IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:StyleParam.Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<#System.IConvertible> * ?TextPosition:StyleParam.TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:StyleParam.Orientation * ?GroupNorm:StyleParam.GroupNorm * ?UseWebGL:bool -> GenericChart.GenericChart
val myFirstStyledChart : GenericChart.GenericChart
static member Chart.withTitle : title:string * ?Titlefont:Font -> (GenericChart.GenericChart -> GenericChart.GenericChart)
static member Chart.withX_AxisStyle : title:string * ?MinMax:(float * float) * ?Showgrid:bool * ?Showline:bool * ?Side:StyleParam.Side * ?Overlaying:StyleParam.AxisAnchorId * ?Id:int * ?Domain:(float * float) * ?Position:float * ?Zeroline:bool * ?Anchor:StyleParam.AxisAnchorId -> (GenericChart.GenericChart -> GenericChart.GenericChart)
static member Chart.withY_AxisStyle : title:string * ?MinMax:(float * float) * ?Showgrid:bool * ?Showline:bool * ?Side:StyleParam.Side * ?Overlaying:StyleParam.AxisAnchorId * ?Id:int * ?Domain:(float * float) * ?Position:float * ?Zeroline:bool * ?Anchor:StyleParam.AxisAnchorId -> (GenericChart.GenericChart -> GenericChart.GenericChart)
static member Chart.Show : ch:GenericChart.GenericChart -> unit
module GenericChart

from Plotly.NET
val toChartHTML : gChart:GenericChart.GenericChart -> string
val xData' : float list
val yData' : float list
static member Chart.withTraceName : ?Name:string * ?Showlegend:bool * ?Legendgroup:string * ?Visible:StyleParam.Visible -> (GenericChart.GenericChart -> GenericChart.GenericChart)
Multiple items
val string : value:'T -> string

--------------------
type string = System.String
Multiple items
val double : value:'T -> double (requires member op_Explicit)

--------------------
[<Struct>]
type double = System.Double

--------------------
type double<'Measure> = float<'Measure>
val xAxis : Axis.LinearAxis
val tmp : Axis.LinearAxis
module Axis

from Plotly.NET
Multiple items
type LinearAxis =
  inherit DynamicObj
  new : unit -> LinearAxis
  static member init : ?AxisType:AxisType * ?Title:string * ?Titlefont:Font * ?Autorange:AutoRange * ?Rangemode:RangeMode * ?Range:Range * ?RangeSlider:RangeSlider * ?Fixedrange:bool * ?Tickmode:TickMode * ?nTicks:int * ?Tick0:#IConvertible * ?dTick:#IConvertible * ?Tickvals:seq<#IConvertible> * ?Ticktext:seq<#IConvertible> * ?Ticks:TickOptions * ?Mirror:Mirror * ?Ticklen:float * ?Tickwidth:float * ?Tickcolor:string * ?Showticklabels:bool * ?Tickfont:Font * ?Tickangle:int * ?Tickprefix:string * ?Showtickprefix:ShowTickOption * ?Ticksuffix:string * ?Showticksuffix:ShowTickOption * ?Showexponent:ShowExponent * ?Exponentformat:ExponentFormat * ?Tickformat:string * ?Hoverformat:string * ?Showline:bool * ?Linecolor:string * ?Linewidth:float * ?Showgrid:bool * ?Gridcolor:string * ?Gridwidth:float * ?Zeroline:bool * ?Zerolinecolor:string * ?Zerolinewidth:float * ?Anchor:AxisAnchorId * ?Side:Side * ?Overlaying:AxisAnchorId * ?Domain:Range * ?Position:float * ?IsSubplotObj:bool * ?Showspikes:bool * ?Spikethickness:float * ?Spikecolor:string * ?Showbackground:bool * ?Backgroundcolor:string * ?Showaxeslabels:bool * ?Visible:bool * ?CategoryOrder:CategoryOrder * ?CategoryArray:seq<#IConvertible> -> LinearAxis
  static member initCategorical : categoryOrder:CategoryOrder * ?Title:string * ?Titlefont:Font * ?Autorange:AutoRange * ?Rangemode:RangeMode * ?Range:Range * ?RangeSlider:RangeSlider * ?Fixedrange:bool * ?Tickmode:TickMode * ?nTicks:int * ?Tick0:#IConvertible * ?dTick:#IConvertible * ?Tickvals:seq<#IConvertible> * ?Ticktext:seq<#IConvertible> * ?Ticks:TickOptions * ?Mirror:Mirror * ?Ticklen:float * ?Tickwidth:float * ?Tickcolor:string * ?Showticklabels:bool * ?Tickfont:Font * ?Tickangle:int * ?Tickprefix:string * ?Showtickprefix:ShowTickOption * ?Ticksuffix:string * ?Showticksuffix:ShowTickOption * ?Showexponent:ShowExponent * ?Exponentformat:ExponentFormat * ?Tickformat:string * ?Hoverformat:string * ?Showline:bool * ?Linecolor:string * ?Linewidth:float * ?Showgrid:bool * ?Gridcolor:string * ?Gridwidth:float * ?Zeroline:bool * ?Zerolinecolor:string * ?Zerolinewidth:float * ?Anchor:AxisAnchorId * ?Side:Side * ?Overlaying:AxisAnchorId * ?Domain:Range * ?Position:float * ?IsSubplotObj:bool * ?Showspikes:bool * ?Spikethickness:float * ?Spikecolor:string * ?Showbackground:bool * ?Backgroundcolor:string * ?Showaxeslabels:bool * ?Visible:bool * ?CategoryArray:seq<#IConvertible> -> LinearAxis
  static member style : ?AxisType:AxisType * ?Title:string * ?Titlefont:Font * ?Autorange:AutoRange * ?Rangemode:RangeMode * ?Range:Range * ?RangeSlider:RangeSlider * ?Fixedrange:bool * ?Tickmode:TickMode * ?nTicks:int * ?Tick0:#IConvertible * ?dTick:#IConvertible * ?Tickvals:seq<#IConvertible> * ?Ticktext:seq<#IConvertible> * ?Ticks:TickOptions * ?Mirror:Mirror * ?Ticklen:float * ?Tickwidth:float * ?Tickcolor:string * ?Showticklabels:bool * ?Tickfont:Font * ?Tickangle:int * ?Tickprefix:string * ?Showtickprefix:ShowTickOption * ?Ticksuffix:string * ?Showticksuffix:ShowTickOption * ?Showexponent:ShowExponent * ?Exponentformat:ExponentFormat * ?Tickformat:string * ?Hoverformat:string * ?Showline:bool * ?Linecolor:string * ?Linewidth:float * ?Showgrid:bool * ?Gridcolor:string * ?Gridwidth:float * ?Zeroline:bool * ?Zerolinecolor:string * ?Zerolinewidth:float * ?Anchor:AxisAnchorId * ?Side:Side * ?Overlaying:AxisAnchorId * ?Domain:Range * ?Position:float * ?IsSubplotObj:bool * ?Showspikes:bool * ?Spikethickness:float * ?Spikecolor:string * ?Showbackground:bool * ?Backgroundcolor:string * ?Showaxeslabels:bool * ?Visible:bool * ?CategoryOrder:CategoryOrder * ?CategoryArray:seq<#IConvertible> -> (LinearAxis -> LinearAxis)

--------------------
new : unit -> Axis.LinearAxis
val yAxis : Axis.LinearAxis
val layout : Layout
val tmp : Layout
Multiple items
type Layout =
  inherit DynamicObj
  new : unit -> Layout
  static member AddLinearAxis : id:AxisId * axis:LinearAxis -> (Layout -> Layout)
  static member AddMap : id:int * map:Geo -> (Layout -> Layout)
  static member AddScene : name:string * scene:Scene -> (Layout -> Layout)
  static member GetLayoutGrid : grid:LayoutGrid -> (Layout -> Layout)
  static member SetLayoutGrid : grid:LayoutGrid -> (Layout -> Layout)
  static member UpdateLinearAxisById : id:AxisId * axis:LinearAxis -> (Layout -> Layout)
  static member UpdateMapById : id:int * map:Geo -> (Layout -> Layout)
  static member UpdateMapboxById : id:int * mapbox:Mapbox -> (Layout -> Layout)
  ...

--------------------
new : unit -> Layout
val trace : Trace
val tmp : Trace
Multiple items
module Trace

from Plotly.NET

--------------------
type Trace =
  inherit DynamicObj
  new : traceTypeName:string -> Trace
  member type : string

--------------------
new : traceTypeName:string -> Trace
val ofTraceObject : trace:Trace -> GenericChart.GenericChart
val setLayout : layout:Layout -> gChart:GenericChart.GenericChart -> GenericChart.GenericChart