diff --git a/apache-toree/Readme.md b/apache-toree/Readme.md new file mode 100644 index 0000000..f668c95 --- /dev/null +++ b/apache-toree/Readme.md @@ -0,0 +1,6 @@ +# Integration of scala-plotly library into Apache Toree Jupyter kernel + +## build + +sbt apache-toree/assembly + diff --git a/apache-toree/etc/Apache Toree - scala-plotly integration.ipynb b/apache-toree/etc/Apache Toree - scala-plotly integration.ipynb new file mode 100644 index 0000000..1bc1687 --- /dev/null +++ b/apache-toree/etc/Apache Toree - scala-plotly integration.ipynb @@ -0,0 +1,1204 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Apache Toree: plotly-scala integration" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Based on: https://github.com/alexarchambault/plotly-scala\n", + "\n", + "- Modified by: [ansotoPhd](https://github.com/ansotoPhd)\n", + "\n", + "- PR: https://github.com/alexarchambault/plotly-scala/pull/18" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Examples extracted from:\n", + "\n", + "https://alexarchambault.github.io/plotly-scala/#line-and-scatter-plot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialization" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ] + }, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import plotly._\n", + "import plotly.element._\n", + "import plotly.layout._\n", + "import plotly.ApacheToree._\n", + "\n", + "plotly.ApacheToree.init()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Line Charts" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "trace1 = Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(10.0, 15.0, 13.0, 17.0))),None,None,None,None,None,None,None,None,None,None,None,None,None,None)\n", + "trace2 = Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(16.0, 5.0, 11.0, 9.0))),None,None,None,None,None,None,None,None,None,None,None,None,None,None)\n", + "data = List(Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(10.0, 15.0, 13.0, 17.0))),None,None,None,None,None,None,None,None,None,None,None,None,None,None), Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(16.0, 5.0, 11.0, 9.0))),None,None,None,None,None,None,None,None,None,None,None,None,None,None))\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "plot-38179836" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import plotly._\n", + "import plotly.element._\n", + " \n", + "val trace1 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(10, 15, 13, 17)\n", + ")\n", + "\n", + "val trace2 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(16, 5, 11, 9)\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2)\n", + "\n", + "plotly.ApacheToree.plot(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Line and scatterplot" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "trace1 = Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(10.0, 15.0, 13.0, 17.0))),None,Some(ScatterMode(Set(Markers))),None,None,None,None,None,None,None,None,None,None,None,None)\n", + "trace2 = Scatter(Some(Doubles(List(2.0, 3.0, 4.0, 5.0))),Some(Doubles(List(16.0, 5.0, 11.0, 9.0))),None,Some(ScatterMode(Set(Lines))),None,None,None,None,None,None,None,None,None,None,None,None)\n", + "trace3 = Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(12.0, 9.0, 15.0, 12.0))),None,Some(ScatterMode(Set(Lines, Markers))),None,None,None,None,None,None,None,None,None,None,None,None)\n", + "data = List(Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(10.0, 15.0, 13.0, 17.0))),None,Some(ScatterMode(Set...\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "List(Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(10.0, 15.0, 13.0, 17.0))),None,Some(ScatterMode(Set(Markers))),None,None,None,None,None,None,None,None,None,None,None,None), Scatter(Some(Doubles(List(2.0, 3.0, 4.0, 5.0))),Some(Doubles(List(16.0, 5.0, 11.0, 9.0))),None,Some(ScatterMode(Set(Lines))),None,None,None,None,None,None,None,None,None,None,None,None), Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(12.0, 9.0, 15.0, 12.0))),None,Some(ScatterMode(Set(Lines, Markers))),None,None,None,None,None,None,None,None,None,None,None,None))" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val trace1 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(10, 15, 13, 17),\n", + " mode = ScatterMode(ScatterMode.Markers)\n", + ")\n", + "\n", + "val trace2 = Scatter(\n", + " Seq(2, 3, 4, 5),\n", + " Seq(16, 5, 11, 9),\n", + " mode = ScatterMode(ScatterMode.Lines)\n", + ")\n", + "\n", + "val trace3 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(12, 9, 15, 12),\n", + " mode = ScatterMode(ScatterMode.Lines, ScatterMode.Markers)\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2, trace3)\n", + "\n", + "val layout = Layout(\n", + " title = \"Line and Scatter Plot\"\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data, layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Categorical dot plot" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "country = List(Switzerland (2011), Chile (2013), Japan (2014), United States (2012), Slovenia (2014), Canada (2011), Poland (2010), Estonia (2015), Luxembourg (2013), Portugal (2011))\n", + "votingPop = List(40.0, 45.7, 52.0, 53.6, 54.1, 54.2, 54.5, 54.7, 55.1, 56.6)\n", + "regVoters = List(49.1, 42.0, 52.7, 84.3, 51.7, 61.1, 55.3, 64.2, 91.1, 58.9)\n", + "trace1 = Scatter(Some(Doubles(List(40.0, 45.7, 52.0, 53.6, 54.1, 54.2, 54.5, 54.7, 55.1, 56.6))),Some(Strings(List(Switzerland (2011), Chile (2013), Japan (2014), United States (2012), Slovenia (2014), Canada (2011), Poland (2010), Estonia (2015), Luxembourg (2013), Portugal (2011)))),None,Some(ScatterMode(Set(Markers))),Some(Marker(Some(One(16)),Some(One(RGBA(156,165,196,0.95))),None,Some(Line(None,S...\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Scatter(Some(Doubles(List(40.0, 45.7, 52.0, 53.6, 54.1, 54.2, 54.5, 54.7, 55.1, 56.6))),Some(Strings(List(Switzerland (2011), Chile (2013), Japan (2014), United States (2012), Slovenia (2014), Canada (2011), Poland (2010), Estonia (2015), Luxembourg (2013), Portugal (2011)))),None,Some(ScatterMode(Set(Markers))),Some(Marker(Some(One(16)),Some(One(RGBA(156,165,196,0.95))),None,Some(Line(None,Some(One(RGBA(156,165,196,1.0))),Some(One(1.0)),None,None,None)),Some(One(Circle(false,false))),None,None,None,None)),None,None,None,Some(Percent of estimated voting age population),None,None,None,None,None,None,None)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val country = Seq(\n", + " \"Switzerland (2011)\",\n", + " \"Chile (2013)\",\n", + " \"Japan (2014)\",\n", + " \"United States (2012)\",\n", + " \"Slovenia (2014)\",\n", + " \"Canada (2011)\",\n", + " \"Poland (2010)\",\n", + " \"Estonia (2015)\",\n", + " \"Luxembourg (2013)\",\n", + " \"Portugal (2011)\"\n", + ")\n", + "\n", + "val votingPop = Seq(\n", + " 40.0, 45.7, 52.0, 53.6, 54.1, 54.2, 54.5, 54.7, 55.1, 56.6\n", + ")\n", + "\n", + "val regVoters = Seq(\n", + " 49.1, 42.0, 52.7, 84.3, 51.7, 61.1, 55.3, 64.2, 91.1, 58.9\n", + ")\n", + "\n", + "val trace1 = Scatter(\n", + " votingPop,\n", + " country,\n", + " mode = ScatterMode(ScatterMode.Markers),\n", + " name = \"Percent of estimated voting age population\",\n", + " marker = Marker(\n", + " color = Color.RGBA(156, 165, 196, 0.95),\n", + " line = Line(\n", + " color = Color.RGBA(156, 165, 196, 1.0),\n", + " width = 1.0\n", + " ),\n", + " symbol = Symbol.Circle(),\n", + " size = 16\n", + " )\n", + ")\n", + "\n", + "val trace2 = Scatter(\n", + " regVoters,\n", + " country,\n", + " mode = ScatterMode(ScatterMode.Markers),\n", + " name = \"Percent of estimated registered voters\",\n", + " marker = Marker(\n", + " color = Color.RGBA(204, 204, 204, 0.95),\n", + " line = Line(\n", + " color = Color.RGBA(217, 217, 217, 1.0),\n", + " width = 1.0\n", + " ),\n", + " symbol = Symbol.Circle(),\n", + " size = 16\n", + " )\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2)\n", + "\n", + "val layout = Layout(\n", + " title = \"Votes cast for ten lowest voting age population in OECD countries\",\n", + " xaxis = Axis(\n", + " showgrid = false,\n", + " showline = true,\n", + " linecolor = Color.RGB(102, 102, 102),\n", + " titlefont = Font(\n", + " color = Color.RGB(204, 204, 204)\n", + " ),\n", + " tickfont = Font(\n", + " color = Color.RGB(102, 102, 102)\n", + " ),\n", + " autotick = false,\n", + " dtick = 10.0,\n", + " ticks = Ticks.Outside,\n", + " tickcolor = Color.RGB(102, 102, 102)\n", + " ),\n", + " margin = Margin(\n", + " l = 140,\n", + " r = 40,\n", + " b = 50,\n", + " t = 80\n", + " ),\n", + " legend = Legend(\n", + " font = Font(\n", + " size = 10\n", + " ),\n", + " yanchor = Anchor.Middle,\n", + " xanchor = Anchor.Right\n", + " ),\n", + " width = 600,\n", + " height = 400,\n", + " paper_bgcolor = Color.RGB(254, 247, 234),\n", + " plot_bgcolor = Color.RGB(254, 247, 234),\n", + " hovermode = HoverMode.Closest\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data, layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic bar chart" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "data = List(Bar(Strings(List(giraffes, orangutans, monkeys)),Doubles(List(20.0, 14.0, 23.0)),None,None,None,None,None,None,None,None))\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "plot-637700945" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val data = Seq(\n", + " Bar(\n", + " Seq(\"giraffes\", \"orangutans\", \"monkeys\"),\n", + " Seq(20, 14, 23)\n", + " )\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Grouped bar chart" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "trace1 = Bar(Strings(List(giraffes, orangutans, monkeys)),Doubles(List(20.0, 14.0, 23.0)),Some(SF Zoo),None,None,None,None,None,None,None)\n", + "trace2 = Bar(Strings(List(giraffes, orangutans, monkeys)),Doubles(List(12.0, 18.0, 29.0)),Some(LA Zoo),None,None,None,None,None,None,None)\n", + "data = List(Bar(Strings(List(giraffes, orangutans, monkeys)),Doubles(List(20.0, 14.0, 23.0)),Some(SF Zoo),None,None,None,None,None,None,None), Bar(Strings(List(giraffes, orangutans, monkeys)),Doubles(List(12.0, 18.0, 29.0)),Some(LA Zoo),None,None,None,None,None,None,None))\n", + "layout = Layout(None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,Some(Group),None,None,None,None,None,None,None,None,None,None)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "plot-2069662835" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val trace1 = Bar(\n", + " Seq(\"giraffes\", \"orangutans\", \"monkeys\"),\n", + " Seq(20, 14, 23),\n", + " name = \"SF Zoo\"\n", + ")\n", + "\n", + "val trace2 = Bar(\n", + " Seq(\"giraffes\", \"orangutans\", \"monkeys\"),\n", + " Seq(12, 18, 29),\n", + " name = \"LA Zoo\"\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2)\n", + "\n", + "val layout = Layout( \n", + " barmode = BarMode.Group\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data,layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bar chart with labels" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "xValue = List(Product A, Product B, Product C)\n", + "yValue = List(20, 14, 23)\n", + "trace1 = Bar(Strings(List(Product A, Product B, Product C)),Doubles(List(20.0, 14.0, 23.0)),None,Some(List(27% market share, 24% market share, 19% market share)),Some(Marker(None,Some(One(RGB(158,202,225))),Some(One(0.6)),Some(Line(None,Some(One(RGB(8,48,107))),Some(One(1.5)),None,None,None)),None,None,None,None,None)),None,None,None,None,None)\n", + "data = List(Bar(Strings(List(Product A, Product B, Product C)),Doubles(List(20.0, 14.0, 23.0)),None,Some(List(27% market share, 24% market share, 19% market share)),Some(Marker(None,Some(One(RGB(158,202,225))),Some(One(0.6)),Some(Line(None,Some(One(RGB(8,48,107))),Some(One(1.5)),None,None,None)),None,None,None,None,None)),N...\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "List(Bar(Strings(List(Product A, Product B, Product C)),Doubles(List(20.0, 14.0, 23.0)),None,Some(List(27% market share, 24% market share, 19% market share)),Some(Marker(None,Some(One(RGB(158,202,225))),Some(One(0.6)),Some(Line(None,Some(One(RGB(8,48,107))),Some(One(1.5)),None,None,None)),None,None,None,None,None)),None,None,None,None,None))" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val xValue = Seq(\"Product A\", \"Product B\", \"Product C\")\n", + "\n", + "val yValue = Seq(20, 14, 23)\n", + "\n", + "val trace1 = Bar(\n", + " xValue,\n", + " yValue,\n", + " text = Seq(\"27% market share\", \"24% market share\", \"19% market share\"),\n", + " marker = Marker(\n", + " color = Color.RGB(158, 202, 225),\n", + " opacity = 0.6,\n", + " line = Line(\n", + " color = Color.RGB(8, 48, 107),\n", + " width = 1.5\n", + " )\n", + " )\n", + ")\n", + "\n", + "val data = Seq(trace1)\n", + "\n", + "val annotations = xValue.zip(yValue).map {\n", + " case (x, y) =>\n", + " Annotation(\n", + " x = x,\n", + " y = y,\n", + " text = y.toString,\n", + " xanchor = Anchor.Center,\n", + " yanchor = Anchor.Bottom,\n", + " showarrow = false\n", + " )\n", + "}\n", + "\n", + "val layout = Layout(\n", + " title = \"January 2013 Sales Report\",\n", + " annotations = annotations\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data,layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Customizing bar colors" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "defaultColor = RGBA(204,204,204,1.0)\n", + "highlightColor = RGBA(222,45,38,0.8)\n", + "trace1 = Bar(Strings(List(Feature A, Feature B, Feature C, Feature D, Feature E)),Doubles(List(20.0, 14.0, 23.0, 25.0, 22.0)),None,None,Some(Marker(None,Some(Sequence(List(RGBA(204,204,204,1.0), RGBA(222,45,38,0.8), RGBA(204,204,204,1.0), RGBA(204,204,204,1.0), RGBA(204,204,204,1.0)))),None,None,None,None,None,None,None)),None,None,None,None,None)\n", + "data = List(Bar(Strings(List(Feature A, Feature B, Feature C, Feature D, Feature E)),Doubles(List(20.0, 14.0, 23.0, 25.0, 22.0)),None,None,Some(Marker(None,Some(Sequence(List(RGBA(204,204,204,1.0), RGBA(222,45,38,0.8), RGBA(204,204,204,1.0), RGBA(204,204,204,1.0), RGBA(204,204,204,1.0)))),...\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "List(Bar(Strings(List(Feature A, Feature B, Feature C, Feature D, Feature E)),Doubles(List(20.0, 14.0, 23.0, 25.0, 22.0)),None,None,Some(Marker(None,Some(Sequence(List(RGBA(204,204,204,1.0), RGBA(222,45,38,0.8), RGBA(204,204,204,1.0), RGBA(204,204,204,1.0), RGBA(204,204,204,1.0)))),None,None,None,None,None,None,None)),None,None,None,None,None))" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val defaultColor = Color.RGBA(204,204,204,1)\n", + "val highlightColor = Color.RGBA(222,45,38,0.8)\n", + "\n", + "val trace1 = Bar(\n", + " Seq(\"Feature A\", \"Feature B\", \"Feature C\", \"Feature D\", \"Feature E\"),\n", + " Seq(20, 14, 23, 25, 22),\n", + " marker = Marker(\n", + " color = Seq(\n", + " defaultColor, highlightColor, defaultColor, defaultColor, defaultColor\n", + " )\n", + " )\n", + ")\n", + "\n", + "val data = Seq(trace1)\n", + "\n", + "val layout = Layout(\n", + " title = \"Least Used Feature\"\n", + ")\n", + "\n", + "data.plot(layout,\"\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Waterfall bar chart" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "xData = List(Product Revenue, Services Revenue, Total Revenue, Fixed Costs, Variable Costs, Total Costs, Total)\n", + "yData = List(400, 660, 660, 590, 400, 400, 340)\n", + "textList = List($430K, $260K, $690K, $-120K, $-200K, $-320K, $370K)\n", + "trace1 = Bar(Strings(List(Product Revenue, Services Revenue, Total Revenue, Fixed Costs, Variable Costs, Total Costs, Total)),Doubles(List(0.0, 430.0, 0.0, 570.0, 370.0, 370.0, 0.0)),None,None,Some(Marker(None,Some(One(RGBA(1,1,1,0.0))),None,None,None,None,None,None,None)),None,None,None,None,None)\n", + "trace2 = Bar(Strings(List(Product Revenue, Services Revenue, Total Revenue, Fixed Costs, Variable Costs, Total Costs, Total)),Doubles(List(430.0, 260.0, 690.0, 0.0, 0.0, 0.0, 0.0)),None,None,Some(Marker(None,S...\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Bar(Strings(List(Product Revenue, Services Revenue, Total Revenue, Fixed Costs, Variable Costs, Total Costs, Total)),Doubles(List(430.0, 260.0, 690.0, 0.0, 0.0, 0.0, 0.0)),None,None,Some(Marker(None,Some(One(RGBA(55,128,191,0.7))),None,Some(Line(None,Some(One(RGBA(55,128,191,1.0))),Some(One(2.0)),None,None,None)),None,None,None,None,None)),None,None,None,None,None)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val xData = Seq(\n", + " \"Product Revenue\",\n", + " \"Services Revenue\",\n", + " \"Total Revenue\",\n", + " \"Fixed Costs\",\n", + " \"Variable Costs\",\n", + " \"Total Costs\",\n", + " \"Total\"\n", + ")\n", + "\n", + "val yData = Seq(400, 660, 660, 590, 400, 400, 340)\n", + "\n", + "val textList = Seq(\"$430K\", \"$260K\", \"$690K\", \"$-120K\", \"$-200K\", \"$-320K\", \"$370K\")\n", + "\n", + "//Base\n", + "\n", + "val trace1 = Bar(\n", + " x = xData,\n", + " y = Seq(0, 430, 0, 570, 370, 370, 0),\n", + " marker = Marker(\n", + " color = Color.RGBA(1, 1, 1, 0.0)\n", + " )\n", + ")\n", + "\n", + "//Revenue\n", + "\n", + "val trace2 = Bar(\n", + " xData,\n", + " Seq(430, 260, 690, 0, 0, 0, 0),\n", + " marker = Marker(\n", + " color = Color.RGBA(55, 128, 191, 0.7),\n", + " line = Line(\n", + " color = Color.RGBA(55, 128, 191, 1.0),\n", + " width = 2.0\n", + " )\n", + " )\n", + ")\n", + "\n", + "//Cost\n", + "\n", + "val trace3 = Bar(\n", + " xData,\n", + " Seq(0, 0, 0, 120, 200, 320, 0),\n", + " marker = Marker(\n", + " color = Color.RGBA(219, 64, 82, 0.7),\n", + " line = Line(\n", + " color = Color.RGBA(219, 64, 82, 1.0),\n", + " width = 2.0\n", + " )\n", + " )\n", + ")\n", + "\n", + "//Profit\n", + "\n", + "val trace4 = Bar(\n", + " xData,\n", + " Seq(0, 0, 0, 0, 0, 0, 370),\n", + " marker = Marker(\n", + " color = Color.RGBA(50,171, 96, 0.7),\n", + " line = Line(\n", + " color = Color.RGBA(50, 171, 96, 1.0),\n", + " width = 2.0\n", + " )\n", + " )\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2, trace3, trace4)\n", + "\n", + "val annotations = xData.zip(yData).zip(textList).map {\n", + " case ((x, y), text) =>\n", + " Annotation(\n", + " x = x,\n", + " y = y,\n", + " text = text,\n", + " font = Font(\n", + " family = \"Arial\",\n", + " size = 14,\n", + " color = Color.RGBA(245, 246, 249, 1)\n", + " ),\n", + " showarrow = false\n", + " )\n", + "}\n", + "\n", + "val layout = Layout(\n", + " title = \"Annual Profit 2015\",\n", + " barmode = BarMode.Stack,\n", + " paper_bgcolor = Color.RGBA(245, 246, 249, 1),\n", + " plot_bgcolor = Color.RGBA(245, 246, 249, 1),\n", + " width = 600,\n", + " height = 400,\n", + " showlegend = false,\n", + " annotations = annotations\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data,layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Horizontal bar charts" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "data = List(Bar(Doubles(List(20.0, 14.0, 23.0)),Strings(List(giraffes, orangutans, monkeys)),None,None,None,Some(Horizontal),None,None,None,None))\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "plot-980672106" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val data = Seq(Bar(\n", + " Seq(20, 14, 23),\n", + " Seq(\"giraffes\", \"orangutans\", \"monkeys\"),\n", + " orientation = Orientation.Horizontal\n", + "))\n", + "\n", + "data.plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Colored bar chart" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "trace1 = Bar(Doubles(List(20.0, 14.0, 23.0)),Strings(List(giraffes, orangutans, monkeys)),Some(SF Zoo),None,Some(Marker(None,Some(One(RGBA(55,128,191,0.6))),None,None,None,None,None,None,Some(One(1)))),Some(Horizontal),None,None,None,None)\n", + "trace2 = Bar(Doubles(List(12.0, 18.0, 29.0)),Strings(List(giraffes, orangutans, monkeys)),Some(LA Zoo),None,Some(Marker(None,Some(One(RGBA(255,153,51,0.6))),None,None,None,None,None,None,Some(One(1)))),Some(Horizontal),None,None,None,None)\n", + "data = List(Bar(Doubles(List(20.0, 14.0, 23.0)),Strings(List(giraffes, orangutans, monkeys)),Some(SF Zoo),None,Some(Marker(None,Some(One(RGBA(55,128,191,0.6))),None,None,None,None,None,None,Some(One(1)))),Some(Horizontal),None,None,None,None), Bar(Doubles(List(12.0, 18.0, 29....\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "List(Bar(Doubles(List(20.0, 14.0, 23.0)),Strings(List(giraffes, orangutans, monkeys)),Some(SF Zoo),None,Some(Marker(None,Some(One(RGBA(55,128,191,0.6))),None,None,None,None,None,None,Some(One(1)))),Some(Horizontal),None,None,None,None), Bar(Doubles(List(12.0, 18.0, 29.0)),Strings(List(giraffes, orangutans, monkeys)),Some(LA Zoo),None,Some(Marker(None,Some(One(RGBA(255,153,51,0.6))),None,None,None,None,None,None,Some(One(1)))),Some(Horizontal),None,None,None,None))" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val trace1 = Bar(\n", + " Seq(20, 14, 23),\n", + " Seq(\"giraffes\", \"orangutans\", \"monkeys\"),\n", + " name = \"SF Zoo\",\n", + " orientation = Orientation.Horizontal,\n", + " marker = Marker(\n", + " color = Color.RGBA(55, 128, 191, 0.6),\n", + " width = 1\n", + " )\n", + ")\n", + "\n", + "val trace2 = Bar(\n", + " Seq(12, 18, 29),\n", + " Seq(\"giraffes\", \"orangutans\", \"monkeys\"),\n", + " name = \"LA Zoo\",\n", + " orientation = Orientation.Horizontal,\n", + " marker = Marker(\n", + " color = Color.RGBA(255, 153, 51, 0.6),\n", + " width = 1\n", + " )\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2)\n", + "\n", + "val layout = Layout(\n", + " title = \"Colored Bar Chart\",\n", + " barmode = BarMode.Stack\n", + ")\n", + "\n", + "plotly.ApacheToree.plot(data,layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Times series" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "data = List(Scatter(Some(Strings(List(2013-10-04 22:23:00, 2013-11-04 22:23:00, 2013-12-04 22:23:00))),Some(Doubles(List(1.0, 3.0, 6.0))),None,None,None,None,None,None,None,None,None,None,None,None,None,None))\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "plot-2037637131" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val data = Seq(\n", + " Scatter(\n", + " Seq(\"2013-10-04 22:23:00\", \"2013-11-04 22:23:00\", \"2013-12-04 22:23:00\"),\n", + " Seq(1, 3, 6)\n", + " )\n", + ")\n", + "\n", + "data.plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## hover-on-text-bubble-chart" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "trace1 = \n", + "data = \n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + " size = 100)),Some(ScatterMode(Set(Markers))),Some(Marker(Some(Sequence(List(40, 60, 80, 100))),Some(Sequence(List(RGB(93,164,214), RGB(255,144,14), RGB(44,160,10...\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "List(Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(10.0, 11.0, 12.0, 13.0))),Some(List(A\n", + " size = 40, B\n", + " size = 60, C\n", + " size = 80, D\n", + " size = 100)),Some(ScatterMode(Set(Markers))),Some(Marker(Some(Sequence(List(40, 60, 80, 100))),Some(Sequence(List(RGB(93,164,214), RGB(255,144,14), RGB(44,160,101), RGB(255,65,54)))),None,None,None,None,None,None,None)),None,None,None,None,None,None,None,None,None,None,None))" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val trace1 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(10, 11, 12, 13),\n", + " text = Seq(\"\"\"A\n", + " size = 40\"\"\", \"\"\"B\n", + " size = 60\"\"\", \"\"\"C\n", + " size = 80\"\"\", \"\"\"D\n", + " size = 100\"\"\"),\n", + " mode = ScatterMode(ScatterMode.Markers),\n", + " marker = Marker(\n", + " color = Seq(Color.RGB(93, 164, 214), Color.RGB(255, 144, 14), Color.RGB(44, 160, 101), Color.RGB(255, 65, 54)),\n", + " size = Seq(40, 60, 80, 100)\n", + " )\n", + ")\n", + "\n", + "val data = Seq(trace1)\n", + "\n", + "val layout = Layout(\n", + " title = \"Bubble Chart Hover Text\",\n", + " showlegend = false,\n", + " height = 400,\n", + " width = 600\n", + ")\n", + "\n", + "\n", + "plotly.ApacheToree.plot(data,layout)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## basic-overlaid-area-chart" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "trace1 = Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(0.0, 2.0, 3.0, 5.0))),None,None,None,None,None,None,None,None,None,None,Some(ToZeroY),None,None,None)\n", + "trace2 = Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(3.0, 5.0, 1.0, 7.0))),None,None,None,None,None,None,None,None,None,None,Some(ToNextY),None,None,None)\n", + "data = List(Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(0.0, 2.0, 3.0, 5.0))),None,None,None,None,None,None,None,None,None,None,Some(ToZeroY),None,None,None), Scatter(Some(Doubles(List(1.0, 2.0, 3.0, 4.0))),Some(Doubles(List(3.0, 5.0, 1.0, 7.0))),None,None,None,None,None,None,None,None,None,None,Some(ToNextY),None,None,None))\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "plot-1964245800" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "val trace1 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(0, 2, 3, 5),\n", + " fill = Fill.ToZeroY\n", + ")\n", + "\n", + "val trace2 = Scatter(\n", + " Seq(1, 2, 3, 4),\n", + " Seq(3, 5, 1, 7),\n", + " fill = Fill.ToNextY\n", + ")\n", + "\n", + "val data = Seq(trace1, trace2)\n", + "\n", + "data.plot()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Spark 2.1.0", + "language": "", + "name": "toree210" + }, + "language_info": { + "codemirror_mode": "text/x-scala", + "file_extension": ".scala", + "mimetype": "text/x-scala", + "name": "scala", + "pygments_lexer": "scala", + "version": "2.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/apache-toree/lib/toree-assembly-0.2.0.dev1-incubating-SNAPSHOT.jar b/apache-toree/lib/toree-assembly-0.2.0.dev1-incubating-SNAPSHOT.jar new file mode 100644 index 0000000..9c25d4c Binary files /dev/null and b/apache-toree/lib/toree-assembly-0.2.0.dev1-incubating-SNAPSHOT.jar differ diff --git a/apache-toree/src/main/scala/plotly/ApacheToree.scala b/apache-toree/src/main/scala/plotly/ApacheToree.scala new file mode 100644 index 0000000..cbbc390 --- /dev/null +++ b/apache-toree/src/main/scala/plotly/ApacheToree.scala @@ -0,0 +1,245 @@ +package plotly + +import java.lang.{Boolean => JBoolean, Double => JDouble, Integer => JInt} +import scala.util.Random +import plotly.element.{Color, _} +import plotly.layout.{Annotation, BoxMode, Font, HoverMode, _} +import org.apache.toree.kernel.api.KernelLike + + +object ApacheToree { + + def init(offline: Boolean = false)(implicit Kernel: KernelLike): Unit = { + + // offline mode like in plotly-python + + val requireInit = + if (offline) + s"""define('plotly', function(require, exports, module) { + | ${Plotly.plotlyMinJs} + |}); + """ + else + """require.config({ + | paths: { + | d3: 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min', + | plotly: 'https://cdn.plot.ly/plotly-1.12.0.min' + | }, + | + | shim: { + | plotly: { + | deps: ['d3', 'jquery'], + | exports: 'plotly' + | } + | } + |}); + """.stripMargin + + val html = s""" + + """ + + Kernel.display.html(html) + } + + def plotJs( + div: String, + data: Seq[Trace], + layout: Layout + )(implicit + Kernel: KernelLike + ): Unit = { + + val baseJs = Plotly.jsSnippet(div, data, layout) + + val js = + s"""requirejs(["plotly"], function(Plotly) { + | $baseJs + |}); + """.stripMargin + Kernel.display.javascript(js) + } + + def randomDiv() = "plot-" + math.abs(Random.nextInt().toLong) + + def plot( + data: Seq[Trace], + layout: Layout = Layout(), + div: String = "" + )(implicit + Kernel: KernelLike + ): String = { + + val div0 = + if (div.isEmpty) + randomDiv() + else + div + + if (div.isEmpty) + Kernel.display.html(s"""
""") + + plotJs(div0, data, layout) + + div0 + } + + implicit class DataOps(val data: Trace) extends AnyVal { + + def plot( + title: String = null, + legend: Legend = null, + width: JInt = null, + height: JInt = null, + showlegend: JBoolean = null, + xaxis: Axis = null, + yaxis: Axis = null, + xaxis1: Axis = null, + xaxis2: Axis = null, + xaxis3: Axis = null, + xaxis4: Axis = null, + yaxis1: Axis = null, + yaxis2: Axis = null, + yaxis3: Axis = null, + yaxis4: Axis = null, + barmode: BarMode = null, + autosize: JBoolean = null, + margin: Margin = null, + annotations: Seq[Annotation] = null, + plot_bgcolor: Color = null, + paper_bgcolor: Color = null, + font: Font = null, + bargap: JDouble = null, + bargroupgap: JDouble = null, + hovermode: HoverMode = null, + boxmode: BoxMode = null, + div: String = "" + )(implicit + Kernel: KernelLike + ): String = + plot( + Layout( + title, + legend, + width, + height, + showlegend, + xaxis, + yaxis, + xaxis1, + xaxis2, + xaxis3, + xaxis4, + yaxis1, + yaxis2, + yaxis3, + yaxis4, + barmode, + autosize, + margin, + annotations, + plot_bgcolor, + paper_bgcolor, + font, + bargap, + bargroupgap, + hovermode, + boxmode + ), + div + ) + + def plot( + layout: Layout, + div: String + )(implicit + Kernel: KernelLike + ): String = + ApacheToree.plot(Seq(data), layout, div = div) + } + + implicit class DataSeqOps(val data: Seq[Trace]) extends AnyVal { + def plot( + title: String = null, + legend: Legend = null, + width: JInt = null, + height: JInt = null, + showlegend: JBoolean = null, + xaxis: Axis = null, + yaxis: Axis = null, + xaxis1: Axis = null, + xaxis2: Axis = null, + xaxis3: Axis = null, + xaxis4: Axis = null, + yaxis1: Axis = null, + yaxis2: Axis = null, + yaxis3: Axis = null, + yaxis4: Axis = null, + barmode: BarMode = null, + autosize: JBoolean = null, + margin: Margin = null, + annotations: Seq[Annotation] = null, + plot_bgcolor: Color = null, + paper_bgcolor: Color = null, + font: Font = null, + bargap: JDouble = null, + bargroupgap: JDouble = null, + hovermode: HoverMode = null, + boxmode: BoxMode = null, + div: String = "" + )(implicit + Kernel: KernelLike + ): String = + plot( + Layout( + title, + legend, + width, + height, + showlegend, + xaxis, + yaxis, + xaxis1, + xaxis2, + xaxis3, + xaxis4, + yaxis1, + yaxis2, + yaxis3, + yaxis4, + barmode, + autosize, + margin, + annotations, + plot_bgcolor, + paper_bgcolor, + font, + bargap, + bargroupgap, + hovermode, + boxmode + ), + div + ) + + def plot( + layout: Layout, + div: String + )(implicit + Kernel: KernelLike + ): String = + ApacheToree.plot(data, layout, div = div) + } + +} + + + + + diff --git a/build.sbt b/build.sbt index 503281d..573b0ce 100644 --- a/build.sbt +++ b/build.sbt @@ -127,6 +127,20 @@ lazy val `jupyter-scala` = project ) ) +lazy val `apache-toree` = project + .dependsOn(coreJvm, renderJvm) + .settings( + shared, + plotlyPrefix, + assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false), + assemblyExcludedJars in assembly := { + val cp = (fullClasspath in assembly).value + cp filter {_.data.getName == "toree-assembly-0.2.0.dev1-incubating-SNAPSHOT.jar"} + }, + libs ++= Seq( + "org.apache.spark" % "spark-core_2.11" % "2.1.0" % "provided" + ) + ) lazy val `plotly-scala` = project .in(file(".")) @@ -140,7 +154,8 @@ lazy val `plotly-scala` = project renderJs, demo, tests, - `jupyter-scala` + `jupyter-scala`, + `apache-toree` ) .settings( shared, diff --git a/project/Settings.scala b/project/Settings.scala index d0d91b8..84d02fa 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -89,8 +89,9 @@ object Settings { lazy val shared = Seq( organization := "org.plotly-scala", + scalaVersion := "2.11.8", scalacOptions ++= { - if (scalaBinaryVersion.value == "2.12") + if (scalaBinaryVersion.value == "2.11") Seq() else Seq("-target:jvm-1.7") diff --git a/project/plugins.sbt b/project/plugins.sbt index 32d019e..956d563 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,5 +2,6 @@ addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.20") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.18") addSbtPlugin("com.dwijnand" % "sbt-travisci" % "1.1.1") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0") addSbtCoursier diff --git a/render/jvm/src/main/scala/plotly/Plotly.scala b/render/jvm/src/main/scala/plotly/Plotly.scala index 9801bc0..d0835d4 100644 --- a/render/jvm/src/main/scala/plotly/Plotly.scala +++ b/render/jvm/src/main/scala/plotly/Plotly.scala @@ -58,7 +58,7 @@ object Plotly { buffer.toByteArray } - val plotlyVersion = "1.12.0" // FIXME Get from build.sbt + val plotlyVersion = "1.24.1" // FIXME Get from build.sbt def plotlyMinJs: String = { var is: InputStream = null