{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[this doc on github](https://github.com/dotnet/interactive/tree/main/samples/notebooks/powershell)\n", "\n", "# Charts with XPlot using constructors \n", "Charts can be rendered using [Xplot.Plotly](https://fslab.org/XPlot/). \n", "We will cover some example on how to use XPlot in a notebook with .NET Interactive.\n", "\n", "> NOTE: This and \"Plotting with Xplot using type accelerators\" produce the same output. They're just using different scripting mechanisms." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" } }, "outputs": [], "source": [ "#!csharp\r\n", "#r \"nuget: XPlot.Plotly.Interactive, 4.0.6\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Rendering Scatter plots\n", "One of the most commonly used type of chart to explore data set. Use the type `Graph.Scatter`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openSeries = [Graph.Scatter]::new()\n", "$openSeries.name = \"Open\"\n", "$openSeries.x = @(1, 2, 3, 4)\n", "$openSeries.y = @(10, 15, 13, 17)\n", "\n", "$closeSeries = [Graph.Scatter]::new()\n", "$closeSeries.name = \"Close\"\n", "$closeSeries.x = @(2, 3, 4, 5)\n", "$closeSeries.y = @(16, 5, 11, 9)\n", "\n", "$chart = @($openSeries, $closeSeries) | New-PlotlyChart -Title \"Open vs Close\"\n", "Out-Display $chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's change it to be markers style, so more like a scatter plot." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openSeries.mode = \"markers\";\n", "$closeSeries.mode = \"markers\";\n", "\n", "$chart = @($openSeries, $closeSeries) | New-PlotlyChart -Title \"Open vs Close\"\n", "Out-Display $chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Scatter` can also produce polar charts by setting the radial property `r` and angular proeprty `t`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openSeries = [Graph.Scatter]::new()\n", "$openSeries.name = \"Open\"\n", "$openSeries.r = @(1, 2, 3, 4)\n", "$openSeries.t = @(45, 100, 150, 290)\n", "\n", "$closeSeries = [Graph.Scatter]::new()\n", "$closeSeries.name = \"Close\"\n", "$closeSeries.r = @(2, 3, 4, 5)\n", "$closeSeries.t = @(16, 45, 118, 90)\n", "\n", "$layout = [Layout]::new()\n", "$layout.title = \"Open vs Close\"\n", "$layout.orientation = -90\n", "\n", "$chart = @($openSeries, $closeSeries) | New-PlotlyChart -Layout $layout\n", "$chart | Out-Display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Large scatter plots and performance\n", "It is not uncommon to have scatter plots with a large dataset, it is a common scenario at the beginning of a data exploration process. Using the default `svg` based rendering will create performace issues as the dom will become very large.\n", "We can then use `web-gl` support to address the problem." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "#!time\n", "$series = 1..10 | ForEach-Object {\n", " $trace = [Graph.Scattergl]::new()\n", " $trace.name = \"Series $_\"\n", " $trace.mode = \"markers\"\n", " $trace.x = [double[]](Get-Random -Count 100000 -Minimum -100000 -Maximum 100000)\n", " $trace.y = [double[]](Get-Random -Count 100000 -Minimum -100000 -Maximum 100000)\n", "\n", " $trace\n", "}\n", "\n", "New-PlotlyChart -Title \"Large Dataset\" -Trace $series | Out-Display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can provide custom marker `colour`, `size` and `colorscale` to display even more information to the user." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$series | ForEach-Object {\n", " [int[]] $sizes = Get-Random -Count 100 -Minimum 0.0 -Maximum 1.0 |\n", " ForEach-Object { $_ -lt 0.75 ? (Get-Random -Minimum 1 -Maximum 5) : (Get-Random -Minimum 10 -Maximum 15) }\n", " $temperatures = $sizes | ForEach-Object { ($_ * 10) - 100 }\n", "\n", " $_.x = [double[]](Get-Random -Count 100000 -Minimum -100000 -Maximum 100000)\n", " $_.y = [double[]](Get-Random -Count 100000 -Minimum -100000 -Maximum 100000)\n", " $_.marker = [XPlot.Plotly.Marker]::new()\n", " $_.marker.size = $sizes\n", " $_.marker.color = $temperatures\n", " $_.marker.colorscale = \"hot\"\n", "}\n", "\n", "New-PlotlyChart -Title \"Large Dataset\" -Trace $series | Out-Display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotly pvoides some additional `color scales` to use." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "foreach ($trace in $series) {\n", " $trace.marker.colorscale = \"Viridis\"\n", "}\n", "\n", "New-PlotlyChart -Title \"Viridis scale\" -Trace $series | Out-Display\n", "\n", "foreach ($trace in $series) {\n", " $trace.marker.colorscale = \"Hot\"\n", "}\n", "\n", "New-PlotlyChart -Title \"Hot scale\" -Trace $series | Out-Display\n", "\n", "foreach ($trace in $series) {\n", " $trace.marker.colorscale = \"Jet\"\n", "}\n", "\n", "New-PlotlyChart -Title \"Jet scale\" -Trace $series | Out-Display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Rendering Histograms\n", "Let's have a look at using histograms, the next cell sets up some generators." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$count = 20\n", "[datetime[]] $dates = 1..$count | ForEach-Object { (Get-Date).AddMinutes((Get-Random -Minimum $_ -Maximum ($_+30))) }" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's define histogram traces:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openByTime = [Graph.Histogram]::new()\n", "$openByTime.name = \"Open\"\n", "$openByTime.x = $dates\n", "$openByTime.y = [double[]](Get-Random -Count $count -Minimum 0 -Maximum 200)\n", "\n", "$closeByTime = [Graph.Histogram]::new()\n", "$closeByTime.name = \"Close\"\n", "$closeByTime.x = $dates\n", "$closeByTime.y = [double[]](Get-Random -Count $count -Minimum 0 -Maximum 200)\n", "\n", "New-PlotlyChart -Trace @($openByTime, $closeByTime) | Out-Display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Histogram generator will automatically count the number of items per bin. \n", "\n", "Setting `histfunc` to `\"sum\"` we can now add up all the values contained in each bin.\n", "Note that we are creatng bin using the `x` data point and we are using bydefault autobinx" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openByTime.histfunc = 'sum'\n", "$closeByTime.histfunc = 'sum'\n", "\n", "(New-PlotlyChart -Trace @($openByTime, $closeByTime)) | Out-Display" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Area chart and Polar Area chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By populating hte property `fill` of a `Scatter` trace the chart will render as area chart.\n", "\n", "Here is set to `\"tozeroy\"` which will create a fill zone underneath the line reachin to the 0 of the y axis." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openSeries = [Graph.Scatter]::new()\n", "$openSeries.name = \"Open\"\n", "$openSeries.x = @(1, 2, 3, 4)\n", "$openSeries.y = @(10, 15, 13, 17)\n", "$openSeries.fill = \"tozeroy\"\n", "$openSeries.mode = \"lines\"\n", "\n", "$closeSeries = [Graph.Scatter]::new()\n", "$closeSeries.name = \"Close\"\n", "$closeSeries.x = @(1, 2, 3, 4)\n", "$closeSeries.y = @(3, 5, 11, 9)\n", "$closeSeries.fill = \"tozeroy\"\n", "$closeSeries.mode = \"lines\"\n", "\n", "$chart = @($openSeries, $closeSeries) | New-PlotlyChart -Title \"Open vs Close\"\n", "Out-Display $chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With one `fill` set to `\"tonexty\"` the cahrt will fill the aread between traces." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$openSeries.fill = $null;\n", "$closeSeries.fill = \"tonexty\";\n", "\n", "$chart = @($openSeries, $closeSeries) | New-PlotlyChart -Title \"Open vs Close\"\n", "Out-Display $chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using `Area` traces we can generate radial area chart. In this example we are using cardinal points to xpress angular values.\n", "The array `{\"North\", \"N-E\", \"East\", \"S-E\", \"South\", \"S-W\", \"West\", \"N-W\"}` will be autoimatically translated to angular values." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [], "source": [ "$areaTrace1 = [Graph.Area]::new()\n", "$areaTrace1.r = @(77.5, 72.5, 70.0, 45.0, 22.5, 42.5, 40.0, 62.5)\n", "$areaTrace1.t = @(\"North\", \"N-E\", \"East\", \"S-E\", \"South\", \"S-W\", \"West\", \"N-W\")\n", "$areaTrace1.name = \"11-14 m/s\"\n", "$areaTrace1.marker = [XPlot.Plotly.Marker]::new()\n", "$areaTrace1.marker.color = \"rgb(106,81,163)\"\n", "\n", "$areaTrace2 = [Graph.Area]::new()\n", "$areaTrace2.r = @(57.49999999999999, 50.0, 45.0, 35.0, 20.0, 22.5, 37.5, 55.00000000000001)\n", "$areaTrace2.t = @(\"North\", \"N-E\", \"East\", \"S-E\", \"South\", \"S-W\", \"West\", \"N-W\")\n", "$areaTrace2.name = \"8-11 m/s\"\n", "$areaTrace2.marker = [XPlot.Plotly.Marker]::new()\n", "$areaTrace2.marker.color = \"rgb(158,154,200)\"\n", "\n", "$areaTrace3 = [Graph.Area]::new()\n", "$areaTrace3.r = @(40.0, 30.0, 30.0, 35.0, 7.5, 7.5, 32.5, 40.0)\n", "$areaTrace3.t = @(\"North\", \"N-E\", \"East\", \"S-E\", \"South\", \"S-W\", \"West\", \"N-W\")\n", "$areaTrace3.name = \"5-8 m/s\"\n", "$areaTrace3.marker = [XPlot.Plotly.Marker]::new()\n", "$areaTrace3.marker.color = \"rgb(203,201,226)\"\n", "\n", "$areaTrace4 = [Graph.Area]::new()\n", "$areaTrace4.r = @(20.0, 7.5, 15.0, 22.5, 2.5, 2.5, 12.5, 22.5)\n", "$areaTrace4.t = @(\"North\", \"N-E\", \"East\", \"S-E\", \"South\", \"S-W\", \"West\", \"N-W\")\n", "$areaTrace4.name = \"< 5 m/s\"\n", "$areaTrace4.marker = [XPlot.Plotly.Marker]::new()\n", "$areaTrace4.marker.color = \"rgb(242,240,247)\"\n", "\n", "$areaLayout = [Layout]::new()\n", "$areaLayout.title = \"Wind Speed Distribution in Laurel, NE\"\n", "$areaLayout.font = [XPlot.Plotly.Font]::new()\n", "$areaLayout.font.size = 16\n", "$areaLayout.legend = [XPlot.Plotly.Legend]::new()\n", "$areaLayout.legend.font = [XPlot.Plotly.Font]::new()\n", "$areaLayout.legend.font.size = 16\n", "$areaLayout.radialaxis = [XPlot.Plotly.Radialaxis]::new()\n", "$areaLayout.radialaxis.ticksuffix = \"%\"\n", "$areaLayout.orientation = 270\n", "\n", "New-PlotlyChart -Layout $areaLayout -Trace @($areaTrace1, $areaTrace2, $areaTrace3, $areaTrace4) | Out-Display" ] } ], "metadata": { "kernelspec": { "display_name": ".NET (PowerShell)", "language": "PowerShell", "name": ".net-powershell" }, "language_info": { "file_extension": ".ps1", "mimetype": "text/x-powershell", "name": "PowerShell", "pygments_lexer": "powershell", "version": "7.0" } }, "nbformat": 4, "nbformat_minor": 4 }