{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true, "nbpresent": { "id": "47239b29-a291-4e47-81bd-50b6db5f29e8" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## [PlotlyJS.jl](http://spencerlyon.com/PlotlyJS.jl/)\n", "\n", "**Spencer Lyon**\n", "\n", "\n", "September 7, 2016" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", "
Plotly javascript loaded.
\n", "To load again call
init_notebook(true)\n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "WARNING: Method definition require(Symbol) in module Base at loading.jl:317 overwritten in module Main at /Users/sglyon/.julia/v0.5/Requires/src/require.jl:12.\n" ] } ], "source": [ "using PlotlyJS" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Outline\n", "\n", "- Bio\n", "- Brief history of [plotly](https://plot.ly)\n", " - [Online](https://plot.ly)\n", " - [API libraries](https://plot.ly/api/)\n", " - [Open source](https://plot.ly/javascript/)\n", "- [PlotlyJS.jl](http://spencerlyon.com/PlotlyJS.jl/): plotly.js in Julia\n", " - Basics\n", " - Convenience API\n", " - Plots.jl support\n", " - Styles\n", " - Interactivity" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Bio\n", "\n", "- Starting 4th year of economics PhD program at NYU Stern\n", "- Live in NYC with wife and three kids\n", "- Here in London to do research at the Bank of England\n", "- Research interests are (in broad terms) macro-finanace, international macro, reinforcement learning -- all with a computational slant" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "nbpresent": { "id": "8a05f9a5-49eb-4686-85f0-800fd561fc62" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## What is plotly?\n", "\n", "Plotly is (has been) many things...\n", "\n", "- Online interface for creating visualizations/dashboards. \"website mode\"\n", "- RESTful API to create plots. \"online mode\" (APIs in many languages)\n", "- Standalone javascript library [plotly.js](https://plot.ly/javascript/) \"offline mode\"" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "1107be03-2275-4fe0-98a9-149d62b0e1de" }, "slideshow": { "slide_type": "subslide" } }, "source": [ "### plotly.js\n", "\n", "- Built on d3.js and stack.gl: great flexibility and respectable performance\n", "- Fully declarative way of specifying plots: plots are json objects\n", "- Over 20 chart types including 3d, statistical charts, and maps\n", "- [Overview](https://plot.ly/javascript/)" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "5b18388a-71a0-4c81-8afe-d21ad83c26ee" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## PlotlyJS.jl\n", "\n", "- Julia wrapper for plotly.js:\n", " - Creates plotly plots\n", " - Exposes plotly.js API functions to Julia\n", "- Two main goals:\n", " 1. Make it convenient to construct and manipulate plotly visualizations from Julia\n", " 2. Provide infrastructure for viewing plots on multiple frontends and saving publication quality plotly graphics to files" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "12b920f6-f8e8-4d4f-bfe7-8f3447b9d424" }, "slideshow": { "slide_type": "slide" } }, "source": [ "### API Overview\n", "\n", "The PlotlyJS.jl API has two main layers:\n", "\n", "1. Faithful plotly.js layer: makes it possible to do _anything_ plotly.js can\n", "2. Convenience, Julian layer: WIP attempt to make some things more natural in Julia" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Faithful plotly.js api layer\n", "\n", "\n", "plotly.js figures are constructed by calling the (javascript) function:\n", "\n", "```javascript\n", "Plotly.newPlot(graphdiv, data, layout)\n", "```\n", "\n", "where" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "\n", "- `graphdiv` is an html `div` element where the plot should appear\n", "- `data` is an array of JSON objects describing the various `trace`s in the visualization\n", "- `layout` is a JSON object describing the layout properties of the visualization." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "In Julia we construct plots using the function\n", "\n", "```julia\n", "plot(data, layout)\n", "```\n", "\n", "where" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- `data` is an `Array` of traces (or a single trace)\n", "- `layout` is an instance of `Layout`\n", "\n", "(NOTE: `graphdiv` is hidden from the user and is a randomly generated UUID attached to the plot)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Let's look at how we can build these `trace`s and a `Layout` in Julia" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Traces\n", "\n", "Construct traces using the tracename as a function and setting keyword arguments:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "bar with fields name, type, x, and y\n" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "trace1 = scatter(y=rand(10), marker_color=\"red\", \n", " marker_line_width=2.0)\n", "trace2 = contour(x=1:5, y=1:10, z=randn(5, 10))\n", "trace3 = bar(x=1:10, y=rand(1:10, 10), name=\"mybar\")" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "671a01b6-f3d6-4980-8e08-36e12e40e6bf" }, "slideshow": { "slide_type": "fragment" } }, "source": [ "- Notice the syntax `marker_color`. \n", "- This sets a _nested_ json atrribute `{\"marker\": {\"color\": \"red\"}}`" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"y\": [\n", " 0.633990156621,\n", " 0.6236290008669474,\n", " 0.3200607908147035,\n", " 0.575944271085947,\n", " 0.25443412736669635,\n", " 0.534191469861913,\n", " 0.2830423111502989,\n", " 0.25638870636628286,\n", " 0.43323680589145663,\n", " 0.06281959363085088\n", " ],\n", " \"type\": \"scatter\",\n", " \"marker\": {\n", " \"line\": {\n", " \"width\": 2.0\n", " },\n", " \"color\": \"red\"\n", " }\n", "}\n" ] } ], "source": [ "print(json(trace1, 2))" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "ad854122-901e-4876-be3c-5ed34d925c6f" }, "slideshow": { "slide_type": "fragment" } }, "source": [ "- All trace types have a corresponding function\n", "- All trace attributes are settable. Consult [api reference](https://plot.ly/javascript/reference) for an overwhelmingly complete list" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Layout\n", "\n", "Build a layout by constructing a `Layout` object:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "layout with fields margin, title, xaxis, and yaxis\n" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "layout = Layout(xaxis=attr(range=[0, 10], \n", " title=\"assets\"), \n", " yaxis_title=\"consumption\", \n", " title=\"??\")" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "468a7b24-77f3-4772-ab64-68d1fde1d6cc" }, "slideshow": { "slide_type": "fragment" } }, "source": [ "- The same underscore magic applies\n", "- Also notice the `attr` function. This allows you to create _groups_ of nested attributes.\n", "- `foo=attr(x=1, y=2)` produces `{\"foo\": {\"x\": 1, \"y\": 2}}`\n", "- It is an alternative to `foo_x=1, foo_y=2`\n", "- `attr` can be used when building traces also" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"yaxis\": {\n", " \"title\": \"consumption\"\n", " },\n", " \"xaxis\": {\n", " \"range\": [\n", " 0,\n", " 10\n", " ],\n", " \"title\": \"assets\"\n", " },\n", " \"title\": \"??\",\n", " \"margin\": {\n", " \"r\": 50,\n", " \"l\": 50,\n", " \"b\": 50,\n", " \"t\": 60\n", " }\n", "}\n" ] } ], "source": [ "print(json(layout, 2))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "To actually display a plot, we tie one or more traces together with a layout by calling the `plot` function:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot(trace1, layout)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# layout optional\n", "plot(trace2)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot([trace1, trace3], layout)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### Convenience API\n", "\n", "The `plot` function has a number of other methods that try to make it a bit easier to construct simple plots" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "14 methods for generic function plot: