{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#### New to Plotly?\n", "Plotly's Python library is free and open source! [Get started](https://plotly.com/python/getting-started/) by downloading the client and [reading the primer](https://plotly.com/python/getting-started/).\n", "
You can set up Plotly to work in [online](https://plotly.com/python/getting-started/#initialization-for-online-plotting) or [offline](https://plotly.com/python/getting-started/#initialization-for-offline-plotting) mode, or in [jupyter notebooks](https://plotly.com/python/getting-started/#start-plotting-online).\n", "
We also have a quick-reference [cheatsheet](https://images.plot.ly/plotly-documentation/images/python_cheat_sheet.pdf) (new!) to help you get started!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Gauge Chart Outline\n", "\n", "We will use `donut` charts with custom colors to create a `semi-circular` gauge meter, such that lower half of the chart is invisible(same color as background).\n", "\n", "This `semi-circular` meter will be overlapped on a base `donut` chart to create the `analog range` of the meter. We will have to rotate the base chart to align the range marks in the edges of meter's section, because by default `Plotly` places them at the center of a pie section." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Base Chart (rotated)\n", "\n", "To make a `gauge meter` with 5 equally sized sections, we will create 6 sections in the base chart. So that center(position of label) aligns with the edges of each section." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import plotly.plotly as py\n", "import plotly.graph_objs as go\n", "\n", "base_chart = {\n", " \"values\": [40, 10, 10, 10, 10, 10, 10],\n", " \"labels\": [\"-\", \"0\", \"20\", \"40\", \"60\", \"80\", \"100\"],\n", " \"domain\": {\"x\": [0, .48]},\n", " \"marker\": {\n", " \"colors\": [\n", " 'rgb(255, 255, 255)',\n", " 'rgb(255, 255, 255)',\n", " 'rgb(255, 255, 255)',\n", " 'rgb(255, 255, 255)',\n", " 'rgb(255, 255, 255)',\n", " 'rgb(255, 255, 255)',\n", " 'rgb(255, 255, 255)'\n", " ],\n", " \"line\": {\n", " \"width\": 1\n", " }\n", " },\n", " \"name\": \"Gauge\",\n", " \"hole\": .4,\n", " \"type\": \"pie\",\n", " \"direction\": \"clockwise\",\n", " \"rotation\": 108,\n", " \"showlegend\": False,\n", " \"hoverinfo\": \"none\",\n", " \"textinfo\": \"label\",\n", " \"textposition\": \"outside\"\n", "}\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outline of the generated `base chart` will look like the one below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " \"Gauge\"\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Meter Chart\n", "\n", "Now we will superimpose our `semi-circular` meter on top of this.
\n", "For that, we will also use 6 sections, but one of them will be invisible to form the lower half (colored same as the background)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "meter_chart = {\n", " \"values\": [50, 10, 10, 10, 10, 10],\n", " \"labels\": [\"Log Level\", \"Debug\", \"Info\", \"Warn\", \"Error\", \"Fatal\"],\n", " \"marker\": {\n", " 'colors': [\n", " 'rgb(255, 255, 255)',\n", " 'rgb(232,226,202)',\n", " 'rgb(226,210,172)',\n", " 'rgb(223,189,139)',\n", " 'rgb(223,162,103)',\n", " 'rgb(226,126,64)'\n", " ]\n", " },\n", " \"domain\": {\"x\": [0, 0.48]},\n", " \"name\": \"Gauge\",\n", " \"hole\": .3,\n", " \"type\": \"pie\",\n", " \"direction\": \"clockwise\",\n", " \"rotation\": 90,\n", " \"showlegend\": False,\n", " \"textinfo\": \"label\",\n", " \"textposition\": \"inside\",\n", " \"hoverinfo\": \"none\"\n", "}\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can see that the first section's value is equal to the sum of other sections.
\n", "We are using `rotation` and `direction` parameters to start the sections from 3 o'clock `[rotation=90]` instead of the default value of 12 o'clock `[rotation=0]`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After imposing on the base chart, it'll look like this." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " \"Gauge\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Dial\n", "\n", "Now we need a `dial` to show the current position in the meter at a particular time.
\n", "`Plotly's` [path shape](https://plotly.com/python/reference/#layout-shapes-path) can be used for this. A nice explanation of SVG path is available [here](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) by Mozilla.
\n", "We can use a `filled triangle` to create our `Dial`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "...\n", "'shapes': [\n", " {\n", " 'type': 'path',\n", " 'path': 'M 0.235 0.5 L 0.24 0.62 L 0.245 0.5 Z',\n", " 'fillcolor': 'rgba(44, 160, 101, 0.5)',\n", " 'line': {\n", " 'width': 0.5\n", " },\n", " 'xref': 'paper',\n", " 'yref': 'paper'\n", " }\n", "]\n", "...\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the `filled-triangle`, the first point `(0.235, 0.5)` is left to the center of meter `(0.24, 0.5)`, the second point `(0.24 0.62)` is representing the current position on the `semi-circle` and the third point `(0.245, 0.5)` is just right to the center." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`M` represents the `'Move'` command that moves cursor to a particular point, `L` is the `'Line To'` command and `Z` represents the `'Close Path'` command. This way, this path string makes a triangle with those three points." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "layout = {\n", " 'xaxis': {\n", " 'showticklabels': False,\n", " 'showgrid': False,\n", " 'zeroline': False,\n", " },\n", " 'yaxis': {\n", " 'showticklabels': False,\n", " 'showgrid': False,\n", " 'zeroline': False,\n", " },\n", " 'shapes': [\n", " {\n", " 'type': 'path',\n", " 'path': 'M 0.235 0.5 L 0.24 0.65 L 0.245 0.5 Z',\n", " 'fillcolor': 'rgba(44, 160, 101, 0.5)',\n", " 'line': {\n", " 'width': 0.5\n", " },\n", " 'xref': 'paper',\n", " 'yref': 'paper'\n", " }\n", " ],\n", " 'annotations': [\n", " {\n", " 'xref': 'paper',\n", " 'yref': 'paper',\n", " 'x': 0.23,\n", " 'y': 0.45,\n", " 'text': '50',\n", " 'showarrow': False\n", " }\n", " ]\n", "}\n", "\n", "# we don't want the boundary now\n", "base_chart['marker']['line']['width'] = 0\n", "\n", "fig = {\"data\": [base_chart, meter_chart],\n", " \"layout\": layout}\n", "py.iplot(fig, filename='gauge-meter-chart')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Reference\n", "See https://plotly.com/python/reference/ for more information and chart attribute options!" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Collecting git+https://github.com/plotly/publisher.git\n", " Cloning https://github.com/plotly/publisher.git to /private/var/folders/tc/bs9g6vrd36q74m5t8h9cgphh0000gn/T/pip-req-build-PcJrlB\n", "Building wheels for collected packages: publisher\n", " Running setup.py bdist_wheel for publisher ... \u001b[?25ldone\n", "\u001b[?25h Stored in directory: /private/var/folders/tc/bs9g6vrd36q74m5t8h9cgphh0000gn/T/pip-ephem-wheel-cache-LDk1sh/wheels/99/3e/a0/fbd22ba24cca72bdbaba53dbc23c1768755fb17b3af0f33966\n", "Successfully built publisher\n", "Installing collected packages: publisher\n", " Found existing installation: publisher 0.11\n", " Uninstalling publisher-0.11:\n", " Successfully uninstalled publisher-0.11\n", "Successfully installed publisher-0.11\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/IPython/nbconvert.py:13: ShimWarning:\n", "\n", "The `IPython.nbconvert` package has been deprecated since IPython 4.0. You should import from nbconvert instead.\n", "\n", "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/publisher/publisher.py:53: UserWarning:\n", "\n", "Did you \"Save\" this notebook before running this command? Remember to save, always save.\n", "\n" ] } ], "source": [ "from IPython.display import display, HTML\n", "\n", "display(HTML(''))\n", "display(HTML(''))\n", "\n", "! pip install git+https://github.com/plotly/publisher.git --upgrade\n", "import publisher\n", "publisher.publish(\n", " 'semicircular-gauge.ipynb', 'python/gauge-charts/', 'Python Gauge Chart | plotly',\n", " 'How to make guage meter charts in Python with Plotly. ',\n", " name = 'Gauge Charts',\n", " title = 'Python Gauge Chart | plotly',\n", " thumbnail='thumbnail/gauge.jpg', language='python',\n", " has_thumbnail='true', display_as='basic', order=11,\n", " ipynb='~notebook_demo/11')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 1 }