{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotly's Python API User Guide" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Section 1: Line and Scatter Plots With an Introduction to Layout Styling" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Welcome to Plotly's Python API User Guide. \n", "\n", "> Links to the other sections are on the User Guide's [homepage](https://plotly.com/python/user-guide#Table-of-Contents:)
\n", "The GitHub repository is available \n", "here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Section 1 is divided as follows:\n", "\n", "* [1.1 Basic line and scatter plots](#1.1-Basic-line-and-scatter-plots)\n", "* [1.2 Style and layout options](#1.2-Style-and-layout-options)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check which version is installed on your machine and please upgrade if needed. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'1.9.5'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# (*) Import plotly package\n", "import plotly\n", "\n", "# Check plolty version (if not latest, please upgrade)\n", "plotly.__version__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1 Basic line and scatter plots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For our first plot in this section, we use data from this Quartz graph:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Embed Plotly graph in notebook\n", "# Quartz is username of the graph's maker,\n", "# 7 is the graph's unique id number\n", "tls.embed('Quartz', '7')\n", "\n", "# Or any of:\n", "# tls.embed('Quartz', 7)\n", "# tls.embed('https://plotly.com/~Quartz/7')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above graph was featured in this Quartz story." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our first plot will present that the data using lines and points instead of bars (more on Plotly bar charts in section 2).\n", "As we will see, Plotly's syntax makes converting a graph from one plot type to another a breeze.\n", "\n", "So first, pull down the figure object from Plotly's servers into this IPython session using the `get_figure` function:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Get figure object from Plotly's servers\n", "# Quartz is username of the graph's maker,\n", "# 7 is the graph's unique id number (either a string or an integer)\n", "Quartz7 = py.get_figure('Quartz', '7')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Figure(\n", " data=Data([\n", " Bar(\n", " x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2..', ],\n", " y=[u'1.1', u'1.5', u'2.1', u'2.8', u'3.4', u'4.1', u'5.0', '..' ],\n", " name=u'China',\n", " marker=Marker(\n", " color=u'rgb(222, 113, 88)'\n", " )\n", " ),\n", " Bar(\n", " x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2..', ],\n", " y=[u'1.3', u'1.2', u'1.3', u'1.4', u'1.5', u'1.5', u'1.5', '..' ],\n", " name=u'U.S.',\n", " marker=Marker(\n", " color=u'rgb(84, 172, 234)'\n", " )\n", " )\n", " ]),\n", " layout=Layout(\n", " title=u'
#OF UNIVERSITY GRADUATES IN CHINA VS. U.S. (MILLIONS)',\n", " titlefont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " font=Font(\n", " family=u\"'Open sans', verdana, arial, sans-serif\",\n", " size=12,\n", " color=u'rgb(33, 33, 33)'\n", " ),\n", " showlegend=True,\n", " autosize=False,\n", " width=700,\n", " height=400,\n", " xaxis=XAxis(\n", " title=u\"Data: Solidiance's Analysis\",\n", " titlefont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " range=[2000.5, 2014.1492895382241],\n", " domain=[0, 1],\n", " type=u'linear',\n", " rangemode=u'normal',\n", " autorange=True,\n", " showgrid=False,\n", " zeroline=False,\n", " showline=True,\n", " autotick=True,\n", " nticks=17,\n", " ticks=u'',\n", " showticklabels=True,\n", " tick0=2001,\n", " dtick=1,\n", " ticklen=5,\n", " tickwidth=1,\n", " tickcolor=u'#000',\n", " tickangle=u'auto',\n", " tickfont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " exponentformat=u'e',\n", " showexponent=u'all',\n", " mirror=False,\n", " gridcolor=u'#ddd',\n", " gridwidth=1,\n", " zerolinecolor=u'#000',\n", " zerolinewidth=1,\n", " linecolor=u'#000',\n", " linewidth=1,\n", " anchor=u'y',\n", " overlaying=False,\n", " position=0\n", " ),\n", " yaxis=YAxis(\n", " title=u'',\n", " titlefont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " range=[0, 8.1],\n", " domain=[0, 1],\n", " type=u'linear',\n", " rangemode=u'nonnegative',\n", " autorange=False,\n", " showgrid=True,\n", " zeroline=False,\n", " showline=True,\n", " autotick=True,\n", " nticks=0,\n", " ticks=u'',\n", " showticklabels=True,\n", " tick0=0,\n", " dtick=2,\n", " ticklen=5,\n", " tickwidth=1,\n", " tickcolor=u'#000',\n", " tickangle=u'auto',\n", " tickfont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " exponentformat=u'e',\n", " showexponent=u'all',\n", " mirror=False,\n", " gridcolor=u'#ddd',\n", " gridwidth=1,\n", " zerolinecolor=u'#000',\n", " zerolinewidth=1,\n", " linecolor=u'#000',\n", " linewidth=1,\n", " anchor=u'x',\n", " overlaying=False,\n", " position=0\n", " ),\n", " legend=Legend(\n", " x=0.001851851851851852,\n", " y=0.9863636363636363,\n", " traceorder=u'normal',\n", " font=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " bgcolor=u'rgba(255, 255, 255, 0)',\n", " bordercolor=u'rgba(0, 0, 0, 0)',\n", " borderwidth=1,\n", " xanchor=u'auto',\n", " yanchor=u'auto'\n", " ),\n", " annotations=Annotations([\n", " Annotation(\n", " x=2001.7,\n", " y=2.4299999999999997,\n", " xref=u'x',\n", " yref=u'y',\n", " text=u'Source: Data objects are list-like, the ordering determines the order at which the individual traces are plotted. This has an impact on a graph's appearance if two or more traces have overlapping coordinates. By virtue of the ordering, the last trace listed in the data object appears in the foreground.\n", "\n", "So, take note that in the `Quartz7` figure object, the trace corresponding to China's numbers is the first item in the data object.\n", "\n", "Now, using the `get_data()` figure object method, retrieve the data from the figure object:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'data': [{'name': u'China',\n", " 'x': [u'2001',\n", " u'2002',\n", " u'2003',\n", " u'2004',\n", " u'2005',\n", " u'2006',\n", " u'2007',\n", " u'2008',\n", " u'2009',\n", " u'2010',\n", " u'2011',\n", " u'2012'],\n", " 'y': [u'1.1',\n", " u'1.5',\n", " u'2.1',\n", " u'2.8',\n", " u'3.4',\n", " u'4.1',\n", " u'5.0',\n", " u'5.6',\n", " u'6.1',\n", " u'6.3',\n", " u'6.6',\n", " u'6.8']},\n", " {'name': u'U.S.',\n", " 'x': [u'2001',\n", " u'2002',\n", " u'2003',\n", " u'2004',\n", " u'2005',\n", " u'2006',\n", " u'2007',\n", " u'2008',\n", " u'2009',\n", " u'2010',\n", " u'2011',\n", " u'2012'],\n", " 'y': [u'1.3',\n", " u'1.2',\n", " u'1.3',\n", " u'1.4',\n", " u'1.5',\n", " u'1.5',\n", " u'1.5',\n", " u'1.6',\n", " u'1.6',\n", " u'1.7',\n", " u'1.7',\n", " u'1.8']}],\n", " 'layout': [{}]}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Retrieve data from figure object (get a dictionary in return)\n", "Quartz7_data = Quartz7.get_data()\n", "\n", "Quartz7_data # show in notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Quartz7_data` is a dictionary, not a Python graph object (try running `type(Quartz7_data)` to see it yourself).\n", "\n", "Notice that both traces' `'name'` keys and their associated values are part of the `Quartz7_data` dictionary. Values linked to `'name'` are the labels in the legend. They also appear on hover next to the scatter points' coordinates. \n", "\n", "More clearly, the two items in the list of traces are:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'name': u'China',\n", " 'x': [u'2001',\n", " u'2002',\n", " u'2003',\n", " u'2004',\n", " u'2005',\n", " u'2006',\n", " u'2007',\n", " u'2008',\n", " u'2009',\n", " u'2010',\n", " u'2011',\n", " u'2012'],\n", " 'y': [u'1.1',\n", " u'1.5',\n", " u'2.1',\n", " u'2.8',\n", " u'3.4',\n", " u'4.1',\n", " u'5.0',\n", " u'5.6',\n", " u'6.1',\n", " u'6.3',\n", " u'6.6',\n", " u'6.8']}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Quartz7_data['data'][0] # show dictionary associated with data for China" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'name': u'U.S.',\n", " 'x': [u'2001',\n", " u'2002',\n", " u'2003',\n", " u'2004',\n", " u'2005',\n", " u'2006',\n", " u'2007',\n", " u'2008',\n", " u'2009',\n", " u'2010',\n", " u'2011',\n", " u'2012'],\n", " 'y': [u'1.3',\n", " u'1.2',\n", " u'1.3',\n", " u'1.4',\n", " u'1.5',\n", " u'1.5',\n", " u'1.5',\n", " u'1.6',\n", " u'1.6',\n", " u'1.7',\n", " u'1.7',\n", " u'1.8']}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Quartz7_data['data'][1] # show dictionary associated with data for the USA" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our task now is to place the dictionaries associated with data for China and data for the USA inside two different instances of the scatter object.\n", "\n", "Before doing so, we call help on `Scatter` (from `plotly.graph_objs`):" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class Scatter in module plotly.graph_objs.graph_objs:\n", "\n", "class Scatter(PlotlyDict)\n", " | Valid attributes for 'scatter' at path [] under parents ():\n", " | \n", " | ['textposition', 'uid', 'stream', 'ysrc', 'hoverinfo', 'xsrc',\n", " | 'visible', 'marker', 'y0', 'tsrc', 'line', 'fill', 'showlegend',\n", " | 'error_x', 'error_y', 'rsrc', 'xaxis', 'text', 'type', 't', 'opacity',\n", " | 'textfont', 'legendgroup', 'textpositionsrc', 'textsrc', 'dx', 'dy',\n", " | 'x0', 'name', 'yaxis', 'connectgaps', 'r', 'mode', 'y', 'x',\n", " | 'fillcolor']\n", " | \n", " | Run `.help('attribute')` on any of the above.\n", " | '' is the object at []\n", " | \n", " | Method resolution order:\n", " | Scatter\n", " | PlotlyDict\n", " | __builtin__.dict\n", " | PlotlyBase\n", " | __builtin__.object\n", " | \n", " | Methods inherited from PlotlyDict:\n", " | \n", " | __copy__(self)\n", " | \n", " | __deepcopy__(self, memodict={})\n", " | \n", " | __dir__(self)\n", " | Dynamically return the existing and possible attributes.\n", " | \n", " | __getattr__(self, key)\n", " | Python only calls this when key is missing!\n", " | \n", " | __getitem__(self, key)\n", " | Calls __missing__ when key is not found. May mutate object.\n", " | \n", " | __init__(self, *args, **kwargs)\n", " | \n", " | __missing__(self, key)\n", " | Mimics defaultdict. This is called from __getitem__ when key DNE.\n", " | \n", " | __setattr__(self, key, value)\n", " | Maps __setattr__ onto __setitem__\n", " | \n", " | __setitem__(self, key, value, _raise=True)\n", " | Validates/Converts values which should be Graph Objects.\n", " | \n", " | force_clean(self, **kwargs)\n", " | Recursively remove empty/None values.\n", " | \n", " | get_data(self, flatten=False)\n", " | Returns the JSON for the plot with non-data elements stripped.\n", " | \n", " | get_ordered(self, **kwargs)\n", " | Return a predictable, OrderedDict version of self.\n", " | \n", " | help(self, attribute=None, return_help=False)\n", " | Print help string for this object or an attribute of this object.\n", " | \n", " | :param (str) attribute: A valid attribute string for this object.\n", " | :param (bool) return_help: Return help_string instead of printing it?\n", " | :return: (None|str)\n", " | \n", " | strip_style(self)\n", " | Recursively strip style from the current representation.\n", " | \n", " | All PlotlyDicts and PlotlyLists are guaranteed to survive the\n", " | stripping process, though they made be left empty. This is allowable.\n", " | \n", " | Keys that will be stripped in this process are tagged with\n", " | `'type': 'style'` in graph_objs_meta.json. Note that a key tagged as\n", " | style, but with an array as a value may still be considered data.\n", " | \n", " | to_string(self, level=0, indent=4, eol='\\n', pretty=True, max_chars=80)\n", " | Returns a formatted string showing graph_obj constructors.\n", " | \n", " | :param (int) level: The number of indentations to start with.\n", " | :param (int) indent: The indentation amount.\n", " | :param (str) eol: The end of line character(s).\n", " | :param (bool) pretty: Curtail long list output with a '..' ?\n", " | :param (int) max_chars: The max characters per line.\n", " | \n", " | Example:\n", " | \n", " | print(obj.to_string())\n", " | \n", " | update(self, dict1=None, **dict2)\n", " | Update current dict with dict1 and then dict2.\n", " | \n", " | This recursively updates the structure of the original dictionary-like\n", " | object with the new entries in the second and third objects. This\n", " | allows users to update with large, nested structures.\n", " | \n", " | Note, because the dict2 packs up all the keyword arguments, you can\n", " | specify the changes as a list of keyword agruments.\n", " | \n", " | Examples:\n", " | # update with dict\n", " | obj = Layout(title='my title', xaxis=XAxis(range=[0,1], domain=[0,1]))\n", " | update_dict = dict(title='new title', xaxis=dict(domain=[0,.8]))\n", " | obj.update(update_dict)\n", " | obj\n", " | {'title': 'new title', 'xaxis': {'range': [0,1], 'domain': [0,.8]}}\n", " | \n", " | # update with list of keyword arguments\n", " | obj = Layout(title='my title', xaxis=XAxis(range=[0,1], domain=[0,1]))\n", " | obj.update(title='new title', xaxis=dict(domain=[0,.8]))\n", " | obj\n", " | {'title': 'new title', 'xaxis': {'range': [0,1], 'domain': [0,.8]}}\n", " | \n", " | This 'fully' supports duck-typing in that the call signature is\n", " | identical, however this differs slightly from the normal update\n", " | method provided by Python's dictionaries.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from PlotlyDict:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from __builtin__.dict:\n", " | \n", " | __cmp__(...)\n", " | x.__cmp__(y) <==> cmp(x,y)\n", " | \n", " | __contains__(...)\n", " | D.__contains__(k) -> True if D has a key k, else False\n", " | \n", " | __delitem__(...)\n", " | x.__delitem__(y) <==> del x[y]\n", " | \n", " | __eq__(...)\n", " | x.__eq__(y) <==> x==y\n", " | \n", " | __ge__(...)\n", " | x.__ge__(y) <==> x>=y\n", " | \n", " | __getattribute__(...)\n", " | x.__getattribute__('name') <==> x.name\n", " | \n", " | __gt__(...)\n", " | x.__gt__(y) <==> x>y\n", " | \n", " | __iter__(...)\n", " | x.__iter__() <==> iter(x)\n", " | \n", " | __le__(...)\n", " | x.__le__(y) <==> x<=y\n", " | \n", " | __len__(...)\n", " | x.__len__() <==> len(x)\n", " | \n", " | __lt__(...)\n", " | x.__lt__(y) <==> x x!=y\n", " | \n", " | __repr__(...)\n", " | x.__repr__() <==> repr(x)\n", " | \n", " | __sizeof__(...)\n", " | D.__sizeof__() -> size of D in memory, in bytes\n", " | \n", " | clear(...)\n", " | D.clear() -> None. Remove all items from D.\n", " | \n", " | copy(...)\n", " | D.copy() -> a shallow copy of D\n", " | \n", " | fromkeys(...)\n", " | dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n", " | v defaults to None.\n", " | \n", " | get(...)\n", " | D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.\n", " | \n", " | has_key(...)\n", " | D.has_key(k) -> True if D has a key k, else False\n", " | \n", " | items(...)\n", " | D.items() -> list of D's (key, value) pairs, as 2-tuples\n", " | \n", " | iteritems(...)\n", " | D.iteritems() -> an iterator over the (key, value) items of D\n", " | \n", " | iterkeys(...)\n", " | D.iterkeys() -> an iterator over the keys of D\n", " | \n", " | itervalues(...)\n", " | D.itervalues() -> an iterator over the values of D\n", " | \n", " | keys(...)\n", " | D.keys() -> list of D's keys\n", " | \n", " | pop(...)\n", " | D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n", " | If key is not found, d is returned if given, otherwise KeyError is raised\n", " | \n", " | popitem(...)\n", " | D.popitem() -> (k, v), remove and return some (key, value) pair as a\n", " | 2-tuple; but raise KeyError if D is empty.\n", " | \n", " | setdefault(...)\n", " | D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D\n", " | \n", " | values(...)\n", " | D.values() -> list of D's values\n", " | \n", " | viewitems(...)\n", " | D.viewitems() -> a set-like object providing a view on D's items\n", " | \n", " | viewkeys(...)\n", " | D.viewkeys() -> a set-like object providing a view on D's keys\n", " | \n", " | viewvalues(...)\n", " | D.viewvalues() -> an object providing a view on D's values\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from __builtin__.dict:\n", " | \n", " | __hash__ = None\n", " | \n", " | __new__ = \n", " | T.__new__(S, ...) -> a new object with type S, a subtype of T\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from PlotlyBase:\n", " | \n", " | to_graph_objs(self, **kwargs)\n", " | Everything is cast into graph_objs. Here for backwards compat.\n", " | \n", " | validate(self)\n", " | Everything is *always* validated now. keep for backwards compat.\n", "\n" ] } ], "source": [ "help(Scatter) # call help!\n", "\n", "# notice 'mode'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pay special attention to the `'mode'` key. It accepts as values `'lines'`, `'markers'`, `'text'` and any sets of these three, determining how the coordinates are displayed.\n", "\n", "* With `'markers'`, coordinates are display as free (i.e. scatter, unlinked) points,\n", "* With `'lines'`, coordinates are linked with lines, \n", "* With `'text'`, text linked to the `'text'` in `Scatter` is display on top of the coordinates (more in [subsection 1.4](#1.4-Others-types-of-scatter-plots)). \n", "\n", "Then, for example, the set `'lines+markers'` (or `'markers+lines'`, order is unimportant) corresponds to points at the coordinates together with lines in-between them. Another possibility is `'lines+markers+text'` which displays points at the coordinates, lines in-between them as well as text at the coordinates.\n", "\n", "We choose to set `'mode'` to `'lines+markers'` for the China `Scatter` instance and set `'mode'` to `'markers'` for the USA `Scatter` instance. \n", "\n", "The China scatter trace object is then:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Make scatter trace object with data for China\n", "trace_china = Scatter(\n", " Quartz7_data['data'][0], # (!) 'name', 'x' and 'y' as in original figure\n", " mode='markers+lines' # marker pts and lines (the default here)\n", ")" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scatter(\n", " x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'..', ],\n", " y=[u'1.1', u'1.5', u'2.1', u'2.8', u'3.4', u'4.1', u'5.0', u'5.6', '..' ],\n", " mode='markers+lines',\n", " name=u'China'\n", ")\n" ] } ], "source": [ "print(trace_china.to_string())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Correspondingly, the USA scatter trace object is:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Make instance of Scatter object with data for the USA\n", "trace_usa = Scatter(\n", " Quartz7_data['data'][1], # (!) 'name', 'x' and 'y' as in original figure\n", " mode='markers', # show marker pts only\n", " marker=Marker(\n", " symbol='square' # show square marker pts\n", " )\n", ")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Scatter(\n", " x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'..', ],\n", " y=[u'1.3', u'1.2', u'1.3', u'1.4', u'1.5', u'1.5', u'1.5', u'1.6', '..' ],\n", " mode='markers',\n", " name=u'U.S.',\n", " marker=Marker(\n", " symbol='square'\n", " )\n", ")\n" ] } ], "source": [ "print(trace_usa.to_string())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, package these two scatter trace objects using a data object:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Make data object containing two traces\n", "data = Data([trace_china, trace_usa])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add our own title for this figure in the layout object:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Make a layout object\n", "layout = Layout(title='Fig 1: Number of university graduates [in millions]')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Recall that all the information about any Plotly figure is contained in a lone figure JSON object. From Plotly's Python API, Data and layout are brought together with `Figure`:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Make a figure object\n", "fig = Figure(data=data, layout=layout)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, send `fig` to Plotly using the `iplot()` method attached a file name and get the resulting plot directly in this notebook:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# (@) Send figure object to Plotly and show result in notebook \n", "py.iplot(fig, filename='s1_grad-china-usa')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*All that's it.*\n", "\n", "We just converted an existing Plotly bar charts into a scatter plot.\n", "\n", "Hover over the scatter points with your cursor and see how Plotly's interactibility is ideal to compare two y-coordinates for a given x-coordinate.\n", "\n", "\n", "If you want more examples and information regarding how to make scatter and line plots, you can refer to the following links for [Line Charts](https://plotly.com/python/line-charts/) and [Scatter Plots](https://plotly.com/python/line-and-scatter/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Saving figures made from the API" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The way figures made from the API are saved is determined by the `fileopt` keyword argument in `py.plot()` and `py.iplot()`. We encourage user to always specify a file name for each Plotly figure made, using the `filename` keyword, in order to better track of them.\n", "\n", "The `fileopt` keyword argument can take on four values: `'new'`, `'overwrite'`, `'append'` and `'extend'`. For now, take note that by default, if `filename` is set then `fileopt` corresponds to `'overwrite'`. That is,\n", "\n", " >>> py.plot(fig, filename='some-figure')\n", " \n", "followed by\n", "\n", " >>> py.plot(fig2, filename='some-figure')\n", " \n", "will overwrite the figure made with the figure object `fig` with a figure made with `fig2`. Alternatively, \n", " \n", " >>> py.plot(fig,filename='s1_grad-china-usa', fileopt='new')\n", " \n", "creates a new file named `s1_grad-china-usa (1)` if `s1_grad-china-usa` already exist on your Plotly account. Your workspace would look something like:\n", " \n", "\n", "\n", "If `s1_grad-china-usa (1)` already existed then the new file would have been named `s1_grad-china-usa (2)` and so on.\n", "\n", "In addition, Plotly allows users to create folders of files. For example,\n", "\n", " >>> py.plot(fig, filename='some-folder/some-figure')\n", " \n", "saves the generated figure in a file named `some-figure` in a folder named `some-folder` (that Plotly automatically creates if it does not exist)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Import and share your plots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, Plotly figures made from the Python API are *public* meaning that anyone is allow to see them. To make a *private* figure simply add `world_readable=False` to your `py.plot()` or `py.iplot` call, for example:\n", "\n", " >>> py.plot(fig, filename='private-fig', world_readable=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Importing a Plotly figure as an image to your hard drive can be done either from the Workspace or the directly from an Python/IPython session.\n", "\n", "\n", "\n", "To import a Plotly figure from the workspace, \n", "\n", "1. Go to the figure's URL (or click on the *data and graph* link at the button of any embedded Plotly figure),\n", "1. Click *Fork and Edit* button. You are now entering the Workspace,\n", "1. Click on the *download* button, leading you to this page:\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "where you can choose the image's size and format." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Imports from an Python/IPython session are done by making a call to Plotly's image server with the `plotly.plotly.image` class:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class image in module plotly.plotly.plotly:\n", "\n", "class image\n", " | Helper functions wrapped around plotly's static image generation api.\n", " | \n", " | Class methods defined here:\n", " | \n", " | ishow(cls, figure_or_data, format='png', width=None, height=None) from __builtin__.classobj\n", " | Display a static image of the plot described by `figure`\n", " | in an IPython Notebook.\n", " | \n", " | save_as(cls, figure_or_data, filename, format=None, width=None, height=None) from __builtin__.classobj\n", " | Save a static image of the plot described by `figure` locally as `filename`.\n", " | Valid image formats are 'png', 'svg', 'jpeg', and 'pdf'.\n", " | The format is taken as the extension of the filename or as the supplied format.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Static methods defined here:\n", " | \n", " | get(figure_or_data, format='png', width=None, height=None)\n", " | Return a static image of the plot described by `figure`.\n", " | \n", " | Valid formats: 'png', 'svg', 'jpeg', 'pdf'\n", "\n" ] } ], "source": [ "help(py.image) # call help!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For instance, \n", "\n", " >>> py.image.save_as(fig, filename='some-fig.svg')\n", " \n", "where `fig` is the figure object, either defined in the current Python/IPython session or retrieved by \n", "\n", " >>> fig = py.get_figure('plotly-username', figure_id)\n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For more on sharing, you are invited to watch the following video:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import VimeoVideo\n", "VimeoVideo('94003080', width='100%', height='350')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2 Style and layout options" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this subsection, we start from a figure showcasing a great data, but lacking some style:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tls.embed('BrianVancil', 8, width=1100)\n", "\n", "# (-) You can adjust the width the notebook cell with\n", "# 'width' keyword argument." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotly's web GUI allows users to modify the appearance of the figure in real-time, that is without having to run, rerun and re-rerun code to get the desired results.\n", "\n", "Together with `py.get_figure()`, this method is also reproducible. \n", "\n", "Watch the following video to see an example of how to transform a figure's apperance using the Workspace:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo('YEM6QMSylfU', width='100%', height='350')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that some the UI elements in the above video are out-of-date; however, the graph editing would be done the same way on the current plot.ly/plot.\n", "\n", "The resulting figure is:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tls.embed(\"https://plotly.com/~etpinard/329/\", width=1100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We hope you think that the above looks better than the original." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we take a closer look on how Plotly stores this information. More precisely, we explore [(1)](#-1--HTML-tags-in-text) HTML tags in text, [(2)](#-2--Color-models) color models, [(3)](#-3--Axis-and-Legend) the axis and legend graph objects and finally [(4)](#-4--Figure-sizing) figure sizing.\n", "\n", "But first, retrieve the styled figure object from Plotly's servers:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# (@) Retrieve figure object using the figure's URL\n", "fig = py.get_figure(\"https://plotly.com/~etpinard/329\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### -1- HTML tags in text" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Take a look at the `'name'` key of are two traces:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "u'Data from Freedman et al.
\"FINAL RESULTS FROM THE HUBBLE SPACE TELESCOPE
KEY PROJECT TO MEASURE THE HUBBLE CONSTANT\"
'" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['data'][0]['name']" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "u'$\\\\text{Linear fit:} \\\\; v = (72.1 \\\\text{km/s/Mpc}) r + 65.7 \\\\text{km/s}$'" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['data'][1]['name']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotly uses a subset of HTML tags to do things like newline (`
`), bold (``), italics (``), hyperlinks (``). Tags ``, ``, ``,\n", " `` are also supported, making it easy to style text shown the plot's title, the axes' titles, annotations and anywhere else in a Plotly figure." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### -2- Color models" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A few examples of colors set in the previous figure:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "u'rgb(204, 65, 37)'" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['data'][1]['line']['color']" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "u'rgb(217, 217, 217)'" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['layout']['plot_bgcolor']" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "u'rgb(255, 255, 255)'" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['layout']['xaxis']['gridcolor']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All Plotly colors are specified as strings (i.e. inside `''` or `\"\"` in Python). \n", "\n", "Although the above all are set in the red-green-blue color model (e.g. `'rgb(0,139,139)`), Plotly also accepts red-green-blue-alpha (e.g. `'rgba(0,139,139,0.5)'`), Hex (e.g. `'#008b8b'`) and numerous pre-defined color names (e.g. `'blue'`, `'red'`, `'yellow'`, the full list can be found here here). \n", "\n", "\t\n", "\n", "Later in section 3 on Bubble Charts, we will see that the `'color'` without the `Marker` object of trace objects such as `Scatter` and `Bar` can be links to lists of colors." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### -3- Axis and Legend" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Axis and legend style options are set through the `'xaxis'` (or `'xaxis1'`), `'yaxis'` (or `'yaxis1'`) and `'legend'` keys in the layout object. For instance, " ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "XAxis(\n", " title=u'Distance \\xa0[Mpc]',\n", " titlefont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " range=[0, 23.39607843137255],\n", " domain=[0, 1],\n", " type=u'linear',\n", " rangemode=u'tozero',\n", " autorange=True,\n", " showgrid=True,\n", " zeroline=False,\n", " showline=False,\n", " autotick=False,\n", " nticks=0,\n", " ticks=u'outside',\n", " showticklabels=True,\n", " tick0=0,\n", " dtick=2,\n", " ticklen=8,\n", " tickwidth=1.5,\n", " tickcolor=u'#444',\n", " tickangle=u'auto',\n", " tickfont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " exponentformat=u'B',\n", " showexponent=u'all',\n", " mirror=False,\n", " gridcolor=u'rgb(255, 255, 255)',\n", " gridwidth=1.5,\n", " zerolinecolor=u'#444',\n", " zerolinewidth=1,\n", " linecolor=u'#444',\n", " linewidth=1,\n", " anchor=u'y',\n", " overlaying=False,\n", " position=0\n", ")\n" ] } ], "source": [ "print(fig['layout']['xaxis'].to_string())" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "YAxis(\n", " title=u'Radial velocity \\xa0[km/s]',\n", " titlefont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " range=[-221.13855421686748, 2148.1385542168673],\n", " domain=[0, 1],\n", " type=u'linear',\n", " rangemode=u'tozero',\n", " autorange=True,\n", " showgrid=True,\n", " zeroline=False,\n", " showline=False,\n", " autotick=True,\n", " nticks=0,\n", " ticks=u'outside',\n", " showticklabels=True,\n", " tick0=0,\n", " dtick=500,\n", " ticklen=8,\n", " tickwidth=1.5,\n", " tickcolor=u'#444',\n", " tickangle=u'auto',\n", " tickfont=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " exponentformat=u'B',\n", " showexponent=u'all',\n", " mirror=False,\n", " gridcolor=u'rgb(255, 255, 255)',\n", " gridwidth=1.5,\n", " zerolinecolor=u'#444',\n", " zerolinewidth=1,\n", " linecolor=u'#444',\n", " linewidth=1,\n", " anchor=u'x',\n", " overlaying=False,\n", " position=0\n", ")\n" ] } ], "source": [ "print(fig['layout']['yaxis'].to_string())" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Legend(\n", " x=0.010260457774269928,\n", " y=0.9551820728291316,\n", " traceorder=u'normal',\n", " font=Font(\n", " family=u'',\n", " size=0,\n", " color=u''\n", " ),\n", " bgcolor=u'rgba(0, 0, 0, 0)',\n", " bordercolor=u'#444',\n", " borderwidth=0,\n", " xanchor=u'left',\n", " yanchor=u'top'\n", ")\n" ] } ], "source": [ "print(fig['layout']['legend'].to_string())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above three layout keys are linked to the `XAxis`, `YAxis` and `Legend` graph objects respectively (which are all dictionary-like). You are invited to call help on each of them." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More closely, note that the legend position is assigned using normalized coordinates with respect to the axis frame. For example,\n", "\n", " >>> Legend(x=0, y=1)\n", " \n", "would place the legend at the top-left corner; \n", "\n", " >>> Legend(x=0, y=0)\n", " \n", "would place the legend at the bottom-left. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### -4- Figure sizing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Modifying the size of a figure is done using three keys in the layout object. These are:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['layout']['autosize']" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1110" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['layout']['width']" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "525" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig['layout']['height']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "where `'autosize'` must be set to `False` for `'width'` and `'height'` to have an effect.\n", "Both `'width'` and `'height'` are measured in pixels.\n", "\n", "As an example, adjust the size of our previous figure while keeping the width-height ratio the same:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Compute width-heigth ratio\n", "ratio = float(fig['layout']['width']) / fig['layout']['height']\n", "\n", "# (-) One of the components must be a float so that the division yields a float\n", "\n", "new_width = 650 # set new width (in pixels)\n", "new_height = int(new_width/ratio) # (!) set new height, must be an integer\n", "\n", "# Update layout object\n", "fig['layout'].update(\n", " autosize=False, # allow custom size (set already, only for completeness here)\n", " width=new_width, # link new width value\n", " height=new_height, # link new height value\n", " font=Font(size=7), # update global font size\n", " titlefont=Font(size=12) # as well as the title font size \n", ")" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# (@) Send figure object to Plotly and show result in notebook \n", "py.iplot(fig, filename='s1_hubble', height=new_height)\n", "\n", "# (-) adjust height of output cell with 'height'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To sum up, styling a Plotly figure requires nothing more than filling in keys with values in appropriate graph objects. By the time you are done reading the User Guide, you will have seen in action (almost) all of Plotly's style options." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " \n", "

Go to\n", "\n", "[Section 2 --- Bar Charts](https://plotly.com/python/bar-charts-tutorial)

\n", "\n", "

Go to\n", "\n", "[Section 0 --- Getting Started with Plotly](https://plotly.com/python/overview)

\n", "\n", "

Go to\n", "\n", "[top of page](#Plotly's-Python-API-User-Guide)

\n", "\n", "

Go to User Guide's\n", "\n", "[homepage](https://plotly.com/python/user-guide)

\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " \n", "
\n", "\n", "

Got Questions or Feedback?

\n", "\n", "About Plotly\n", "\n", "* email: feedback@plot.ly \n", "* tweet: \n", "@plotlygraphs\n", "\n", "About the User Guide\n", " \n", "* email: etienne@plot.ly\n", "* tweet: @etpinard\n", "\n", "

Notebook styling ideas

\n", "\n", "Big thanks to\n", "\n", "* Cam Davidson-Pilon\n", "* Lorena A. Barba\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# CSS styling within IPython notebook\n", "from IPython.display import display, HTML\n", "display(HTML(open('../custom.css').read()))" ] } ], "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.9" } }, "nbformat": 4, "nbformat_minor": 0 }