{ "metadata": { "name": "", "signature": "sha256:f685f4304e61fe6296aab96795f876f6d4bb17b426a8447d9542498901e1c67c" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Gr\u00e1ficas interactivas con `plotly`\n", "\n", "En un [art\u00edculo anterior](http://pybonacci.org/2014/08/05/de-matplotlib-a-la-web-con-plotly/) ya vimos como pasar las gr\u00e1ficas creadas con `matplotlib` a `plotly` para obtener cierto nivel de interacci\u00f3n con los datos en la web.\n", "Ahora, lo que vamos a ver es c\u00f3mo crear gr\u00e1ficas directamente con `plotly`.\n", "Para ello vamos a utilizar:\n", "\n", "+ `pandas 0.14.1`, para trabajar con tablas de datos.\n", "+ `plotly 1.2.6`, para crear las gr\u00e1ficas.\n", "\n", "Importamos los paquetes de la manera habitual en cada caso." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import pandas as pd\n", "import plotly.plotly as py\n", "from plotly.graph_objs import *" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "En el caso de Plotly hemos importado adem\u00e1s unos objetos `graph_objs` que nos ser\u00e1n de ayuda a la hora de crear las gr\u00e1ficas.\n", "Trabajar con la API de Plotly en Python se resume en trabajar con *listas y diccionarios* de Python. \n", "Los `graph_objs` de Plotly nos ayudar\u00e1n a trabajar con estas listas y diccionarios proporcionando ayuda y validando los datos y par\u00e1metros introducidos.\n", "\n", "Entre los objetos que importamos tenemos los bloques principales de trabajo:\n", "\n", "+ **Figure**, diccionario que representa la figura a representar en `plotly`.\n", "+ **Data**, lista para englobar todos los trazos a representar en una gr\u00e1fica, ya sean tipo *Scatter*, *Heatmap*, *Box*, etc.\n", "+ **Layout**, diccionario que define los detalles de la disposici\u00f3n de la figura." ] }, { "cell_type": "code", "collapsed": false, "input": [ "help(Figure)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Help on class Figure in module plotly.graph_objs.graph_objs:\n", "\n", "class Figure(PlotlyDict)\n", " | A dictionary-like object representing a figure to be rendered in plotly.\n", " | \n", " | This is the container for all things to be rendered in a figure.\n", " | \n", " | For help with setting up subplots, run:\n", " | `help(plotly.tools.get_subplots)`\n", " | \n", " | \n", " | Quick method reference:\n", " | \n", " | Figure.update(changes)\n", " | Figure.strip_style()\n", " | Figure.get_data()\n", " | Figure.to_graph_objs()\n", " | Figure.validate()\n", " | Figure.to_string()\n", " | Figure.force_clean()\n", " | \n", " | Valid keys:\n", " | \n", " | data [required=False] (value=Data object | array-like of one or several\n", " | dictionaries):\n", " | A list-like array of the data trace(s) that is/are to be visualized.\n", " | \n", " | For more, run `help(plotly.graph_objs.Data)`\n", " | \n", " | layout [required=False] (value=Layout object | dictionary-like):\n", " | A dictionary-like object that contains the layout parameters (e.g.\n", " | information about the axis, global settings and layout information\n", " | related to the rendering of the figure).\n", " | \n", " | For more, run `help(plotly.graph_objs.Layout)`\n", " | \n", " | Method resolution order:\n", " | Figure\n", " | PlotlyDict\n", " | builtins.dict\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, *args, **kwargs)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from PlotlyDict:\n", " | \n", " | force_clean(self, caller=True)\n", " | Attempts to convert to graph_objs and call force_clean() on values.\n", " | \n", " | Calling force_clean() on a PlotlyDict will ensure that the object is\n", " | valid and may be sent to plotly. This process will also remove any\n", " | entries that end up with a length == 0.\n", " | \n", " | Careful! This will delete any invalid entries *silently*.\n", " | \n", " | get_data(self)\n", " | Returns the JSON for the plot with non-data elements stripped.\n", " | \n", " | get_ordered(self, caller=True)\n", " | \n", " | strip_style(self)\n", " | 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 the INFO dictionary listed in graph_objs_meta.py.\n", " | \n", " | This process first attempts to convert nested collections from dicts\n", " | or lists to subclasses of PlotlyList/PlotlyDict. This process forces\n", " | a validation, which may throw exceptions.\n", " | \n", " | Then, each of these objects call `strip_style` on themselves and so\n", " | on, recursively until the entire structure has been validated and\n", " | stripped.\n", " | \n", " | to_graph_objs(self, caller=True)\n", " | Walk obj, convert dicts and lists to plotly graph objs.\n", " | \n", " | For each key in the object, if it corresponds to a special key that\n", " | should be associated with a graph object, the ordinary dict or list\n", " | will be reinitialized as a special PlotlyDict or PlotlyList of the\n", " | appropriate `kind`.\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", " | Example:\n", " | \n", " | print obj.to_string()\n", " | \n", " | Keyword arguments:\n", " | level (default = 0) -- set number of indentations to start with\n", " | indent (default = 4) -- set indentation amount\n", " | eol (default = '\n", " | ') -- set end of line character(s)\n", " | pretty (default = True) -- curtail long list output with a '...'\n", " | max_chars (default = 80) -- set max characters per line\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", " | validate(self, caller=True)\n", " | Recursively check the validity of the keys in a PlotlyDict.\n", " | \n", " | The valid keys constitute the entries in each object\n", " | dictionary in INFO stored in graph_objs_meta.py.\n", " | \n", " | The validation process first requires that all nested collections be\n", " | converted to the appropriate subclass of PlotlyDict/PlotlyList. Then,\n", " | each of these objects call `validate` and so on, recursively,\n", " | until the entire object has been validated.\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 builtins.dict:\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", " | __getitem__(...)\n", " | x.__getitem__(y) <==> x[y]\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", " | __setitem__(...)\n", " | x.__setitem__(i, y) <==> x[i]=y\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", " | items(...)\n", " | D.items() -> a set-like object providing a view on D's items\n", " | \n", " | keys(...)\n", " | D.keys() -> a set-like object providing a view on 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() -> an object providing a view on D's values\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from builtins.dict:\n", " | \n", " | __hash__ = None\n", " | \n", " | __new__ = \n", " | T.__new__(S, ...) -> a new object with type S, a subtype of T\n", "\n" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "help(Data)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Help on class Data in module plotly.graph_objs.graph_objs:\n", "\n", "class Data(PlotlyList)\n", " | A list of traces to be shown on a plot/graph.\n", " | \n", " | Any operation that can be done with a standard list may be used with Data.\n", " | Instantiation requires an iterable (just like list does), for example:\n", " | \n", " | Data([Scatter(), Heatmap(), Box()])\n", " | \n", " | Valid entry types: (dict or any subclass of Trace, i.e., Scatter, Box, etc.)\n", " | \n", " | \n", " | Quick method reference:\n", " | \n", " | Data.update(changes)\n", " | Data.strip_style()\n", " | Data.get_data()\n", " | Data.to_graph_objs()\n", " | Data.validate()\n", " | Data.to_string()\n", " | Data.force_clean()\n", " | \n", " | Method resolution order:\n", " | Data\n", " | PlotlyList\n", " | builtins.list\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | to_graph_objs(self, caller=True)\n", " | Change any nested collections to subclasses of PlotlyDict/List.\n", " | \n", " | Procedure:\n", " | 1. Attempt to convert all entries to a subclass of PlotlyTrace.\n", " | 2. Call `to_graph_objects` on each of these entries.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from PlotlyList:\n", " | \n", " | __init__(self, *args)\n", " | \n", " | force_clean(self, caller=True)\n", " | Attempts to convert to graph_objs and calls force_clean() on entries.\n", " | \n", " | Calling force_clean() on a PlotlyList will ensure that the object is\n", " | valid and may be sent to plotly. This process will remove any entries\n", " | that end up with a length == 0. It will also remove itself from\n", " | enclosing trivial structures if it is enclosed by a collection with\n", " | length 1, meaning the data is the ONLY object in the collection.\n", " | \n", " | Careful! This will delete any invalid entries *silently*.\n", " | \n", " | get_data(self)\n", " | Returns the JSON for the plot with non-data elements stripped.\n", " | \n", " | get_ordered(self, caller=True)\n", " | \n", " | strip_style(self)\n", " | 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 the INFO dictionary listed in graph_objs_meta.py.\n", " | \n", " | This process first attempts to convert nested collections from dicts\n", " | or lists to subclasses of PlotlyList/PlotlyDict. This process forces\n", " | a validation, which may throw exceptions.\n", " | \n", " | Then, each of these objects call `strip_style` on themselves and so\n", " | on, recursively until the entire structure has been validated and\n", " | stripped.\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", " | Example:\n", " | \n", " | print obj.to_string()\n", " | \n", " | Keyword arguments:\n", " | level (default = 0) -- set number of indentations to start with\n", " | indent (default = 4) -- set indentation amount\n", " | eol (default = '\n", " | ') -- set end of line character(s)\n", " | pretty (default = True) -- curtail long list output with a '...'\n", " | max_chars (default = 80) -- set max characters per line\n", " | \n", " | update(self, changes, make_copies=False)\n", " | Update current list with changed_list, which must be iterable.\n", " | The 'changes' should be a list of dictionaries, however,\n", " | it is permitted to be a single dict object.\n", " | \n", " | Because mutable objects contain references to their values, updating\n", " | multiple items in a list will cause the items to all reference the same\n", " | original set of objects. To change this behavior add\n", " | `make_copies=True` which makes deep copies of the update items and\n", " | therefore break references.\n", " | \n", " | validate(self, caller=True)\n", " | Recursively check the validity of the entries in a PlotlyList.\n", " | \n", " | PlotlyList may only contain suclasses of PlotlyDict, or dictionary-like\n", " | objects that can be re-instantiated as subclasses of PlotlyDict.\n", " | \n", " | The validation process first requires that all nested collections be\n", " | converted to the appropriate subclass of PlotlyDict/PlotlyList. Then,\n", " | each of these objects call `validate` and so on, recursively,\n", " | until the entire list has been validated.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from PlotlyList:\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 builtins.list:\n", " | \n", " | __add__(...)\n", " | x.__add__(y) <==> x+y\n", " | \n", " | __contains__(...)\n", " | x.__contains__(y) <==> y in x\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", " | __getitem__(...)\n", " | x.__getitem__(y) <==> x[y]\n", " | \n", " | __gt__(...)\n", " | x.__gt__(y) <==> x>y\n", " | \n", " | __iadd__(...)\n", " | x.__iadd__(y) <==> x+=y\n", " | \n", " | __imul__(...)\n", " | x.__imul__(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*n\n", " | \n", " | __ne__(...)\n", " | x.__ne__(y) <==> x!=y\n", " | \n", " | __repr__(...)\n", " | x.__repr__() <==> repr(x)\n", " | \n", " | __reversed__(...)\n", " | L.__reversed__() -- return a reverse iterator over the list\n", " | \n", " | __rmul__(...)\n", " | x.__rmul__(n) <==> n*x\n", " | \n", " | __setitem__(...)\n", " | x.__setitem__(i, y) <==> x[i]=y\n", " | \n", " | __sizeof__(...)\n", " | L.__sizeof__() -- size of L in memory, in bytes\n", " | \n", " | append(...)\n", " | L.append(object) -> None -- append object to end\n", " | \n", " | clear(...)\n", " | L.clear() -> None -- remove all items from L\n", " | \n", " | copy(...)\n", " | L.copy() -> list -- a shallow copy of L\n", " | \n", " | count(...)\n", " | L.count(value) -> integer -- return number of occurrences of value\n", " | \n", " | extend(...)\n", " | L.extend(iterable) -> None -- extend list by appending elements from the iterable\n", " | \n", " | index(...)\n", " | L.index(value, [start, [stop]]) -> integer -- return first index of value.\n", " | Raises ValueError if the value is not present.\n", " | \n", " | insert(...)\n", " | L.insert(index, object) -- insert object before index\n", " | \n", " | pop(...)\n", " | L.pop([index]) -> item -- remove and return item at index (default last).\n", " | Raises IndexError if list is empty or index is out of range.\n", " | \n", " | remove(...)\n", " | L.remove(value) -> None -- remove first occurrence of value.\n", " | Raises ValueError if the value is not present.\n", " | \n", " | reverse(...)\n", " | L.reverse() -- reverse *IN PLACE*\n", " | \n", " | sort(...)\n", " | L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from builtins.list:\n", " | \n", " | __hash__ = None\n", " | \n", " | __new__ = \n", " | T.__new__(S, ...) -> a new object with type S, a subtype of T\n", "\n" ] } ], "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ "help(Layout)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Help on class Layout in module plotly.graph_objs.graph_objs:\n", "\n", "class Layout(PlotlyDict)\n", " | A dictionary-like object holding plot settings for plotly figures.\n", " | \n", " | \n", " | Quick method reference:\n", " | \n", " | Layout.update(changes)\n", " | Layout.strip_style()\n", " | Layout.get_data()\n", " | Layout.to_graph_objs()\n", " | Layout.validate()\n", " | Layout.to_string()\n", " | Layout.force_clean()\n", " | \n", " | Valid keys:\n", " | \n", " | title [required=False] (value=string):\n", " | The title of the figure.\n", " | \n", " | titlefont [required=False] (value=Font object | dictionary-like):\n", " | A dictionary-like object describing the font settings of the\n", " | figure's title.\n", " | \n", " | For more, run `help(plotly.graph_objs.Font)`\n", " | \n", " | font [required=False] (value=Font object | dictionary-like):\n", " | A dictionary-like object describing the global font settings for\n", " | this figure (e.g. all axis titles and labels).\n", " | \n", " | For more, run `help(plotly.graph_objs.Font)`\n", " | \n", " | showlegend [required=False] (value=boolean: True | False):\n", " | Toggle whether or not the legend will be shown in this figure.\n", " | \n", " | autosize [required=False] (value=boolean: True | False):\n", " | Toggle whether or not the dimensions of the figure are automatically\n", " | picked by Plotly. Plotly picks figure's dimensions as a function of\n", " | your machine's display resolution. Once 'autosize' is set to False,\n", " | the figure's dimensions can be set with 'width' and 'height'.\n", " | \n", " | width [required=False] (value=number: x > 0):\n", " | Sets the width in pixels of the figure you are generating.\n", " | \n", " | height [required=False] (value=number: x > 0):\n", " | Sets the height in pixels of the figure you are generating.\n", " | \n", " | xaxis [required=False] (value=XAxis object | dictionary-like):\n", " | A dictionary-like object describing an x-axis (i.e. an horizontal\n", " | axis). The first XAxis object can be entered into layout by linking\n", " | it to 'xaxis' OR 'xaxis1', both keys are identical to Plotly. To\n", " | create references other x-axes, you need to define them in the\n", " | layout dictionary-like object using keys 'xaxis2', 'xaxis3' and so\n", " | on.\n", " | \n", " | For more, run `help(plotly.graph_objs.XAxis)`\n", " | \n", " | yaxis [required=False] (value=YAxis object | dictionary-like):\n", " | A dictionary-like object describing an y-axis (i.e. an vertical\n", " | axis). The first YAxis object can be entered into layout by linking\n", " | it to 'yaxis' OR 'yaxis1', both keys are identical to Plotly. To\n", " | create references other y-axes, you need to define them in the\n", " | layout dictionary-like object using keys 'yaxis2', 'yaxis3' and so\n", " | on.\n", " | \n", " | For more, run `help(plotly.graph_objs.YAxis)`\n", " | \n", " | legend [required=False] (value=Legend object | dictionary-like):\n", " | A dictionary-like object containing the legend parameters for this\n", " | figure.\n", " | \n", " | For more, run `help(plotly.graph_objs.Legend)`\n", " | \n", " | annotations [required=False] (value=Annotations object | array-like of\n", " | one or several dictionaries):\n", " | A list-like object that contains one or multiple annotation\n", " | dictionaries.\n", " | \n", " | For more, run `help(plotly.graph_objs.Annotations)`\n", " | \n", " | margin [required=False] (value=Margin object | dictionary-like):\n", " | A dictionary-like object containing the margin parameters for this\n", " | figure.\n", " | \n", " | For more, run `help(plotly.graph_objs.Margin)`\n", " | \n", " | paper_bgcolor [required=False] (value=string describing color):\n", " | Sets the color of the figure's paper (i.e. area representing the\n", " | canvas of the figure).\n", " | \n", " | Examples:\n", " | [\"'green'\", \"'rgb(0, 255, 0)'\", \"'rgba(0, 255, 0, 0.3)'\",\n", " | \"'hsl(120,100%,50%)'\", \"'hsla(120,100%,50%,0.3)'\"]\n", " | \n", " | plot_bgcolor [required=False] (value=string describing color):\n", " | Sets the background color of the plot (i.e. the area laying inside\n", " | this figure's axes.\n", " | \n", " | Examples:\n", " | [\"'green'\", \"'rgb(0, 255, 0)'\", \"'rgba(0, 255, 0, 0.3)'\",\n", " | \"'hsl(120,100%,50%)'\", \"'hsla(120,100%,50%,0.3)'\"]\n", " | \n", " | hovermode [required=False] (value='closest' | 'x' | 'y'):\n", " | Sets this figure's behavior when a user hovers over it. When set to\n", " | 'x', all data sharing the same 'x' coordinate will be shown on\n", " | screen with corresponding trace labels. When set to 'y' all data\n", " | sharing the same 'y' coordainte will be shown on the screen with\n", " | corresponding trace labels. When set to 'closest', information about\n", " | the data point closest to where the viewer is hovering will appear.\n", " | \n", " | dragmode [required=False] (value='zoom' | 'pan'):\n", " | Sets this figure's behavior when a user preforms a mouse 'drag' in\n", " | the plot area. When set to 'zoom', a portion of the plot will be\n", " | highlighted, when the viewer exits the drag, this highlighted\n", " | section will be zoomed in on. When set to 'pan', data in the plot\n", " | will move along with the viewers dragging motions. A user can always\n", " | depress the 'shift' key to access the whatever functionality has not\n", " | been set as the default.\n", " | \n", " | separators [required=False] (value=a two-character string):\n", " | Sets the decimal (the first character) and thousands (the second\n", " | character) separators to be displayed on this figure's tick labels\n", " | and hover mode. This is meant for internationalization purposes. For\n", " | example, if 'separator' is set to ', ', then decimals are separated\n", " | by commas and thousands by spaces. One may have to set\n", " | 'exponentformat' to 'none' in the corresponding axis object(s) to\n", " | see the effects.\n", " | \n", " | barmode [required=False] (value='stack' | 'group' | 'overlay'):\n", " | For bar and histogram plots only. This sets how multiple bar objects\n", " | are plotted together. In other words, this defines how bars at the\n", " | same location appear on the plot. If set to 'stack' the bars are\n", " | stacked on top of one another. If set to 'group', the bars are\n", " | plotted next to one another, centered around the shared location. If\n", " | set to 'overlay', the bars are simply plotted over one another, you\n", " | may need to set the opacity to see this.\n", " | \n", " | bargap [required=False] (value=number: x >= 0):\n", " | For bar and histogram plots only. Sets the gap between bars (or sets\n", " | of bars) at different locations.\n", " | \n", " | bargroupgap [required=False] (value=number: x >= 0):\n", " | For bar and histogram plots only. Sets the gap between bars in the\n", " | same group. That is, when multiple bar objects are plotted and share\n", " | the same locations, this sets the distance between bars at each\n", " | location.\n", " | \n", " | boxmode [required=False] (value='overlay' | 'group'):\n", " | For box plots only. Sets how groups of box plots appear. If set to\n", " | 'overlay', a group of boxes will be plotted directly on top of one\n", " | another at their specified location. If set to 'group', the boxes\n", " | will be centered around their shared location, but they will not\n", " | overlap.\n", " | \n", " | radialaxis [required=False] (value=RadialAxis object | dictionary-like):\n", " | A dictionary-like object describing the radial axis in a polar plot.\n", " | \n", " | For more, run `help(plotly.graph_objs.RadialAxis)`\n", " | \n", " | angularaxis [required=False] (value=AngularAxis object | dictionary-\n", " | like):\n", " | A dictionary-like object describing the angular axis in a polar\n", " | plot.\n", " | \n", " | For more, run `help(plotly.graph_objs.AngularAxis)`\n", " | \n", " | direction [required=False] (value='clockwise' | 'counterclockwise'):\n", " | For polar plots only. Sets the direction corresponding to positive\n", " | angles.\n", " | \n", " | orientation [required=False] (value=number: x in [-360, 360]):\n", " | For polar plots only. Rotates the entire polar by the given angle.\n", " | \n", " | hidesources [required=False] (value=boolean: True | False):\n", " | Toggle whether or not an annotation citing the data source is placed\n", " | at the bottom-right corner of the figure.This key has an effect only\n", " | on graphs that have been generated from forked graphs from plot.ly.\n", " | \n", " | Method resolution order:\n", " | Layout\n", " | PlotlyDict\n", " | builtins.dict\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, *args, **kwargs)\n", " | \n", " | force_clean(self, caller=True)\n", " | Attempts to convert to graph_objs and call force_clean() on values.\n", " | \n", " | Calling force_clean() on a Layout will ensure that the object is\n", " | valid and may be sent to plotly. This process will also remove any\n", " | entries that end up with a length == 0.\n", " | \n", " | Careful! This will delete any invalid entries *silently*.\n", " | \n", " | This method differs from the parent (PlotlyDict) method in that it\n", " | must check for an infinite number of possible axis keys, i.e. 'xaxis',\n", " | 'xaxis1', 'xaxis2', 'xaxis3', etc. Therefore, it cannot make a call\n", " | to super...\n", " | \n", " | to_graph_objs(self, caller=True)\n", " | Walk obj, convert dicts and lists to plotly graph objs.\n", " | \n", " | For each key in the object, if it corresponds to a special key that\n", " | should be associated with a graph object, the ordinary dict or list\n", " | will be reinitialized as a special PlotlyDict or PlotlyList of the\n", " | appropriate `kind`.\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", " | Example:\n", " | \n", " | print obj.to_string()\n", " | \n", " | Keyword arguments:\n", " | level (default = 0) -- set number of indentations to start with\n", " | indent (default = 4) -- set indentation amount\n", " | eol (default = '\n", " | ') -- set end of line character(s)\n", " | pretty (default = True) -- curtail long list output with a '...'\n", " | max_chars (default = 80) -- set max characters per line\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from PlotlyDict:\n", " | \n", " | get_data(self)\n", " | Returns the JSON for the plot with non-data elements stripped.\n", " | \n", " | get_ordered(self, caller=True)\n", " | \n", " | strip_style(self)\n", " | 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 the INFO dictionary listed in graph_objs_meta.py.\n", " | \n", " | This process first attempts to convert nested collections from dicts\n", " | or lists to subclasses of PlotlyList/PlotlyDict. This process forces\n", " | a validation, which may throw exceptions.\n", " | \n", " | Then, each of these objects call `strip_style` on themselves and so\n", " | on, recursively until the entire structure has been validated and\n", " | stripped.\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", " | validate(self, caller=True)\n", " | Recursively check the validity of the keys in a PlotlyDict.\n", " | \n", " | The valid keys constitute the entries in each object\n", " | dictionary in INFO stored in graph_objs_meta.py.\n", " | \n", " | The validation process first requires that all nested collections be\n", " | converted to the appropriate subclass of PlotlyDict/PlotlyList. Then,\n", " | each of these objects call `validate` and so on, recursively,\n", " | until the entire object has been validated.\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 builtins.dict:\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", " | __getitem__(...)\n", " | x.__getitem__(y) <==> x[y]\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", " | __setitem__(...)\n", " | x.__setitem__(i, y) <==> x[i]=y\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", " | items(...)\n", " | D.items() -> a set-like object providing a view on D's items\n", " | \n", " | keys(...)\n", " | D.keys() -> a set-like object providing a view on 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() -> an object providing a view on D's values\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from builtins.dict:\n", " | \n", " | __hash__ = None\n", " | \n", " | __new__ = \n", " | T.__new__(S, ...) -> a new object with type S, a subtype of T\n", "\n" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como vemos, `Figure` y `Layout` son objetos de tipo diccionario y `Data` es un objeto de tipo lista.\n", "En el caso de `Data`, el orden es importante pues determina el orden de composici\u00f3n de los trazos, empezando por el primero objeto en `Data`.\n", "Por ejemplo, representar una l\u00ednea sobre una barras no produce, normalmente, el mismo resultado que representar unas barras sobre una l\u00ednea.\n", "\n", "En Plotly cada tipo de gr\u00e1fica tiene su propio objeto (*trace graph object*) como son `Scatter`, `Bar` o `Histogram`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "help(Scatter)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Help on class Scatter in module plotly.graph_objs.graph_objs:\n", "\n", "class Scatter(PlotlyTrace)\n", " | A dictionary-like object for representing a scatter plot in plotly.\n", " | \n", " | Example:\n", " | \n", " | py.plot([Scatter(name='tacters', x=[1,4,2,3], y=[1,6,2,1])])\n", " | \n", " | \n", " | Quick method reference:\n", " | \n", " | Scatter.update(changes)\n", " | Scatter.strip_style()\n", " | Scatter.get_data()\n", " | Scatter.to_graph_objs()\n", " | Scatter.validate()\n", " | Scatter.to_string()\n", " | Scatter.force_clean()\n", " | \n", " | Valid keys:\n", " | \n", " | x [required= when 'y','r' and 't' are unset] (value=array-like of\n", " | numbers, strings, datetimes) (streamable):\n", " | The x coordinates of the points of this scatter trace. If 'x' is\n", " | linked to an list or array of strings, then the x coordinates are\n", " | integers [0,1,2,3, ...] labeled on the x-axis by the list or array\n", " | of strings linked to 'x'.\n", " | \n", " | y [required= when 'x','r' and 't' are unset] (value=array-like of\n", " | numbers, strings, datetimes) (streamable):\n", " | The y coordinates of the points of this scatter trace. If 'y' is\n", " | linked to an list or array of strings, then the y coordinates are\n", " | integers [0,1,2,3, ...] labeled on the y-axis by the list or array\n", " | of strings linked to 'y'.\n", " | \n", " | r [required= when making a Polar Chart] (value=array-like of numbers)\n", " | (streamable):\n", " | For Polar charts only. The radial coordinates of the points in this\n", " | polar scatter trace about the origin.\n", " | \n", " | t [required= when making a Polar Chart] (value=array-like of numbers,\n", " | strings, datetimes) (streamable):\n", " | For Polar charts only. The angular coordinates of the points in this\n", " | polar scatter trace. By default, the angular coordinates are in\n", " | degrees (0 to 360) where the angles are measured clockwise about the\n", " | right-hand side of the origin. To change this behavior, modify\n", " | 'range' in AngularAxis or/and 'direction' in Layout. If 't' is\n", " | linked to an array-like of strings, then the angular coordinates are\n", " | [0, 360\\N, 2*360/N, ...] where N is the number of coordinates given\n", " | labeled by the array-like of strings linked to 't'.\n", " | \n", " | mode [required=False] (value='lines' | 'markers' | 'text' |\n", " | 'lines+markers' | 'lines+text' | 'markers+text' | 'lines+markers+text'):\n", " | Plotting mode (or style) for the scatter plot. If the mode includes\n", " | 'text' then the 'text' will appear at the (x,y) points, otherwise it\n", " | will appear on hover.\n", " | \n", " | name [required=False] (value=string):\n", " | The label associated with this trace. This name will appear in the\n", " | legend, on hover and in the column header in the online spreadsheet.\n", " | \n", " | text [required=False] (value=array-like of strings) (streamable):\n", " | The text elements associated with each (x,y) pair in this scatter\n", " | trace. If the scatter 'mode' does not include 'text' then text\n", " | elements will appear on hover only. In contrast, if 'text' is\n", " | included in 'mode', the entries in 'text' will be rendered on the\n", " | plot at the locations specified in part by their corresponding (x,y)\n", " | coordinate pair and the 'textposition' key.\n", " | \n", " | error_y [required=False] (value=ErrorY object | dictionary-like)\n", " | (streamable):\n", " | A dictionary-like object describing the vetical error bars (i.e.\n", " | along the y-axis) that can be drawn from the (x, y) coordinates.\n", " | \n", " | For more, run `help(plotly.graph_objs.ErrorY)`\n", " | \n", " | error_x [required=False] (value=ErrorX object | dictionary-like)\n", " | (streamable):\n", " | A dictionary-like object describing the horizontal error bars (i.e.\n", " | along the x-axis) that can be drawn from the (x, y) coordinates.\n", " | \n", " | For more, run `help(plotly.graph_objs.ErrorX)`\n", " | \n", " | marker [required=False] (value=Marker object | dictionary-like)\n", " | (streamable):\n", " | A dictionary-like object containing marker style parameters for this\n", " | scatter trace. Has an effect only if 'mode' contains 'markers'.\n", " | \n", " | For more, run `help(plotly.graph_objs.Marker)`\n", " | \n", " | line [required=False] (value=Line object | dictionary-like)\n", " | (streamable):\n", " | A dictionary-like object containing line style parameters for this\n", " | scatter trace. Has an effect only if 'mode' contains 'lines'.\n", " | \n", " | For more, run `help(plotly.graph_objs.Line)`\n", " | \n", " | textposition [required=False] (value='top left' | 'top' (or 'top\n", " | center')| 'top right' | 'left' (or 'middle left') | '' (or 'middle\n", " | center') |'right' (or 'middle right') |'bottom left' | 'bottom' (or\n", " | 'bottom center') |'bottom right'):\n", " | Sets the position of the text elements in the 'text' key with\n", " | respect to the data points. By default, the text elements are\n", " | plotted directly at the (x,y) coordinates.\n", " | \n", " | textfont [required=False] (value=Font object | dictionary-like):\n", " | A dictionary-like object describing the font style of this scatter\n", " | trace's text elements. Has only an effect if 'mode' is set and\n", " | includes 'text'.\n", " | \n", " | For more, run `help(plotly.graph_objs.Font)`\n", " | \n", " | connectgaps [required=False] (value=boolean: True | False):\n", " | Toggle whether or not missing data points (i.e. '' or NaNs) linked\n", " | to 'x' and/or 'y', are added in by Plotly using linear\n", " | interpolation.\n", " | \n", " | fill [required=False] (value='none' | 'tozeroy' | 'tonexty' | 'tozerox'\n", " | | 'tonextx):\n", " | Use to make area-style charts. Determines which area to fill with a\n", " | solid color.By default, the area will appear in a more-transparent\n", " | shape of the line color (or of the marker color if 'mode' does not\n", " | contains 'lines').\n", " | \n", " | fillcolor [required=False] (value=string describing color):\n", " | Sets the color that will appear in the specified fill area (set in\n", " | 'fill'). Has no effect if 'fill' is set to 'none'.\n", " | \n", " | Examples:\n", " | [\"'green'\", \"'rgb(0, 255, 0)'\", \"'rgba(0, 255, 0, 0.3)'\",\n", " | \"'hsl(120,100%,50%)'\", \"'hsla(120,100%,50%,0.3)'\"]\n", " | \n", " | opacity [required=False] (value=number: x in [0, 1]):\n", " | Sets the opacity, or transparency, of the entire object, also known\n", " | as the alpha channel of colors. If the object's color is given in\n", " | terms of 'rgba' color model, 'opacity' is redundant.\n", " | \n", " | xaxis [required=False] (value='x1' | 'x2' | 'x3' | etc.):\n", " | This key determines which x-axis the x-coordinates of this trace\n", " | will reference in the figure. Values 'x1' and 'x' reference to\n", " | layout['xaxis'], 'x2' references layout['xaxis2'], and so on. Note\n", " | that 'x1' will always refer to layout['xaxis'] or layout['xaxis1'],\n", " | they are the same.\n", " | \n", " | yaxis [required=False] (value='y1' | 'y2' | 'y3' | etc.):\n", " | This key determines which y-axis the y-coordinates of this trace\n", " | will reference in the figure. Values 'y1' and 'y' reference to\n", " | layout['yaxis'], 'y2' references layout['yaxis2'], and so on. Note\n", " | that 'y1' will always refer to layout['yaxis'] or layout['yaxis1'],\n", " | they are the same.\n", " | \n", " | showlegend [required=False] (value=boolean: True | False):\n", " | Toggle whether or not this trace will be labeled in the legend.\n", " | \n", " | stream [required=False] (value=Stream object | dictionary-like):\n", " | The stream dictionary-like object that initializes traces as\n", " | writable-streams, for use with the real-time streaming API. Learn\n", " | more here: https://plot.ly/python/streaming/\n", " | \n", " | For more, run `help(plotly.graph_objs.Stream)`\n", " | \n", " | visible [required=False] (value=boolean: True | False):\n", " | Toggles whether or not this object will actually be visible in the\n", " | rendered figure.\n", " | \n", " | type [required=False] (value=scatter):\n", " | Plotly identifier for this data's trace type. This defines how this\n", " | data dictionary will be handled. For example, 'scatter' type\n", " | expects x and y data-arrays corresponding to (x, y) coordinates\n", " | whereas a 'histogram' only requires a single x or y array and a\n", " | 'heatmap' type requires a z matrix.\n", " | \n", " | Method resolution order:\n", " | Scatter\n", " | PlotlyTrace\n", " | PlotlyDict\n", " | builtins.dict\n", " | builtins.object\n", " | \n", " | Methods inherited from PlotlyTrace:\n", " | \n", " | __init__(self, *args, **kwargs)\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", " | Example:\n", " | \n", " | print obj.to_string()\n", " | \n", " | Keyword arguments:\n", " | level (default = 0) -- set number of indentations to start with\n", " | indent (default = 4) -- set indentation amount\n", " | eol (default = '\n", " | ') -- set end of line character(s)\n", " | pretty (default = True) -- curtail long list output with a '...'\n", " | max_chars (default = 80) -- set max characters per line\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from PlotlyDict:\n", " | \n", " | force_clean(self, caller=True)\n", " | Attempts to convert to graph_objs and call force_clean() on values.\n", " | \n", " | Calling force_clean() on a PlotlyDict will ensure that the object is\n", " | valid and may be sent to plotly. This process will also remove any\n", " | entries that end up with a length == 0.\n", " | \n", " | Careful! This will delete any invalid entries *silently*.\n", " | \n", " | get_data(self)\n", " | Returns the JSON for the plot with non-data elements stripped.\n", " | \n", " | get_ordered(self, caller=True)\n", " | \n", " | strip_style(self)\n", " | 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 the INFO dictionary listed in graph_objs_meta.py.\n", " | \n", " | This process first attempts to convert nested collections from dicts\n", " | or lists to subclasses of PlotlyList/PlotlyDict. This process forces\n", " | a validation, which may throw exceptions.\n", " | \n", " | Then, each of these objects call `strip_style` on themselves and so\n", " | on, recursively until the entire structure has been validated and\n", " | stripped.\n", " | \n", " | to_graph_objs(self, caller=True)\n", " | Walk obj, convert dicts and lists to plotly graph objs.\n", " | \n", " | For each key in the object, if it corresponds to a special key that\n", " | should be associated with a graph object, the ordinary dict or list\n", " | will be reinitialized as a special PlotlyDict or PlotlyList of the\n", " | appropriate `kind`.\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", " | validate(self, caller=True)\n", " | Recursively check the validity of the keys in a PlotlyDict.\n", " | \n", " | The valid keys constitute the entries in each object\n", " | dictionary in INFO stored in graph_objs_meta.py.\n", " | \n", " | The validation process first requires that all nested collections be\n", " | converted to the appropriate subclass of PlotlyDict/PlotlyList. Then,\n", " | each of these objects call `validate` and so on, recursively,\n", " | until the entire object has been validated.\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 builtins.dict:\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", " | __getitem__(...)\n", " | x.__getitem__(y) <==> x[y]\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", " | __setitem__(...)\n", " | x.__setitem__(i, y) <==> x[i]=y\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", " | items(...)\n", " | D.items() -> a set-like object providing a view on D's items\n", " | \n", " | keys(...)\n", " | D.keys() -> a set-like object providing a view on 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() -> an object providing a view on D's values\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from builtins.dict:\n", " | \n", " | __hash__ = None\n", " | \n", " | __new__ = \n", " | T.__new__(S, ...) -> a new object with type S, a subtype of T\n", "\n" ] } ], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ejemplo pr\u00e1ctico: aeropuerto de Heathrow\n", "\n", "Hecha la presentaci\u00f3n de Plotly pasamos a un ejemplo pr\u00e1ctico de uso de la herramienta.\n", "Para ello tomaremos datos de [estad\u00edsticas de tr\u00e1fico](http://www.heathrowairport.com/about-us/investor-centre/results-and-performance/traffic-statistics) del aeropuerto de Heathrow, el tercer mayor del mundo por tr\u00e1fico de pasajeros.\n", "\n", "### Datos estad\u00edsticos\n", "\n", "Los datos son proporcionados en un fichero Excel que podemos importar con Pandas." ] }, { "cell_type": "code", "collapsed": false, "input": [ "pasajeros = pd.io.excel.read_excel('07-Heathrow_Monthly_Traffic_Statistics_(Jan_2005-Jul_2014).xls',\n", " sheetname=0, # tomamos la primera hoja del archivo\n", " header=2, # la cebecera empieza en la fila 3\n", " index_col=0) # empleamos las fechas como indices\n", "pasajeros.head(5)" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
HeathrowSouthamptonGlasgowAberdeenNon-London AirportsUK Total
Month
2005-01-01 5141123 99945 504138 186378 790461 5931584
2005-02-01 4753591 109120 506851 189925 805896 5559487
2005-03-01 5708627 131983 603225 227621 962829 6671456
2005-04-01 5573022 145749 641107 232191 1019047 6592069
2005-05-01 5636621 168971 795732 242493 1207196 6843817
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ " Heathrow Southampton Glasgow Aberdeen Non-London Airports \\\n", "Month \n", "2005-01-01 5141123 99945 504138 186378 790461 \n", "2005-02-01 4753591 109120 506851 189925 805896 \n", "2005-03-01 5708627 131983 603225 227621 962829 \n", "2005-04-01 5573022 145749 641107 232191 1019047 \n", "2005-05-01 5636621 168971 795732 242493 1207196 \n", "\n", " UK Total \n", "Month \n", "2005-01-01 5931584 \n", "2005-02-01 5559487 \n", "2005-03-01 6671456 \n", "2005-04-01 6592069 \n", "2005-05-01 6843817 " ] } ], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "mercancias = pd.io.excel.read_excel('07-Heathrow_Monthly_Traffic_Statistics_(Jan_2005-Jul_2014).xls',\n", " sheetname=5, # tomamos la sexta hoja del archivo\n", " header=2, # la cebecera empieza en la fila 3\n", " index_col=0) # empleamos las fechas como indices\n", "mercancias.head(5)" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
HeathrowSouthamptonGlasgowAberdeenNon-London AirportsUK Total
Month
2005-01-01 98781.175 16.237 491.582 304.274 812.093 99593.268
2005-02-01 99555.454 16.554 545.170 310.282 872.006 100427.460
2005-03-01 109387.896 18.830 578.286 368.156 965.272 110353.168
2005-04-01 108057.553 18.277 569.431 321.004 908.712 108966.265
2005-05-01 110612.691 17.466 661.753 369.324 1048.543 111661.234
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ " Heathrow Southampton Glasgow Aberdeen Non-London Airports \\\n", "Month \n", "2005-01-01 98781.175 16.237 491.582 304.274 812.093 \n", "2005-02-01 99555.454 16.554 545.170 310.282 872.006 \n", "2005-03-01 109387.896 18.830 578.286 368.156 965.272 \n", "2005-04-01 108057.553 18.277 569.431 321.004 908.712 \n", "2005-05-01 110612.691 17.466 661.753 369.324 1048.543 \n", "\n", " UK Total \n", "Month \n", "2005-01-01 99593.268 \n", "2005-02-01 100427.460 \n", "2005-03-01 110353.168 \n", "2005-04-01 108966.265 \n", "2005-05-01 111661.234 " ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como podemos ver, se trata de una serie temporal.\n", "Y puesto que los datos se proporcionan mes a mes, podr\u00edamos deshacernos del d\u00eda del mes indicandole a Pandas que se trata de un periodo de frecuencia mensual con `to_period`. Pero no es necesario, pues como veremos m\u00e1s adelante, Plotly es capaz de *intuir* que queremos representar los datos mes a mes." ] }, { "cell_type": "code", "collapsed": false, "input": [ "pasajeros.to_period('M').head(2)" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
HeathrowSouthamptonGlasgowAberdeenNon-London AirportsUK Total
Month
2005-01 5141123 99945 504138 186378 790461 5931584
2005-02 4753591 109120 506851 189925 805896 5559487
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 8, "text": [ " Heathrow Southampton Glasgow Aberdeen Non-London Airports \\\n", "Month \n", "2005-01 5141123 99945 504138 186378 790461 \n", "2005-02 4753591 109120 506851 189925 805896 \n", "\n", " UK Total \n", "Month \n", "2005-01 5931584 \n", "2005-02 5559487 " ] } ], "prompt_number": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Representaci\u00f3n gr\u00e1fica de los datos\n", "\n", "Si ya hemos guardado nuestras credenciales de Plotly en el ordenador, al importar el paquete como\n", "\n", " import plotly.plotly as py\n", " \n", "ya nos *logueamos* autom\u00e1ticamente en el servidor sin tener que acceder mediante\n", "\n", " py.sign_in('username', 'api_key')\n", " \n", "Una figura (`Figure`) Plotly se compone de los datos a representar (`Data`) y de un formato (`Layout`), y estos a su vez no son m\u00e1s que un conjunto de listas y diccionarios que Plotly se encargar\u00e1 de convertir a un formato [JSON](http://en.wikipedia.org/wiki/Json).\n", "Como hemos mencionado arriba, Plotly proporciona una serie de `graph_objs` que nos facilitar\u00e1n la tarea de componer gr\u00e1ficas interactivas y que veremos a continuaci\u00f3n.\n", "\n", "#### Data\n", "\n", "Empezamos por el conjunto de datos a representar.\n", "En este caso vamos a representar el tr\u00e1fico mensual de pasajeros en los aeropuertos brit\u00e1nicos del grupo [Heathrow](http://en.wikipedia.org/wiki/Heathrow_Airport_Holdings), participada al 25% por [Ferrovial](http://es.wikipedia.org/wiki/Ferrovial), que incluye los aeropuertos de:\n", "\n", "+ London Heathrow Airport\n", "+ Southampton Airport\n", "+ Glasgow Airport\n", "+ Aberdeen Airport\n", "\n", "Para representar estos datos nos valdremos de la herramienta `Data` que, como hemos visto anteriormente, admite una lista de objetos. \n", "En nuestro caso, l\u00edneas.\n", "Para ello nos valdremos de `Scatter` (*dispersi\u00f3n*) al cual pasaremos los siguentes par\u00e1metros:\n", "\n", "+ `name`, nombre que damos a la l\u00ednea, en nuestro caso, el nombre del aeropuerto.\n", "+ `x`, array con los meses del a\u00f1o que corresponden al *index* de nuestro `DataFrame`.\n", "+ `y`, array con el n\u00famero de pasajeros correspondientes a cada aeropuerto.\n", "+ `mode`, cadena de texto que indica el tipo de representaci\u00f3n que queremos, ya sea `'lines'`, `'markers'`, `'text'` o una combinaci\u00f3n de ellos como podr\u00eda ser `'lines+markers'`.\n", "\n", "Puesto que se trata de una lista con cuatro l\u00edneas a representar, haremos uso de las [list comprehensions](https://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions) de Python." ] }, { "cell_type": "code", "collapsed": false, "input": [ "p_data = Data([Scatter(name=col,\n", " x=pasajeros.index,\n", " y=pasajeros[col],\n", " mode='lines') for col in pasajeros.columns.values[:4]])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Layout\n", "\n", "Ya con los datos a representar definidos, ahora podemos pasar a retocar el *layout* de la figura.\n", "Para ello vamos a a\u00f1adir un t\u00edtulo a la gr\u00e1fica y a los ejes *x* e *y*.\n", "Otra cosa que haremos tambi\u00e9n es encuadrar la gr\u00e1fica con \n", " \n", " showline=True, mirror='ticks', linewidth=2\n", "\n", "y reducir los margenes derecho `r` y superior `t` para aprovechar mejor el espacio." ] }, { "cell_type": "code", "collapsed": false, "input": [ "p_layout = Layout(title='Tr\u00e1fico mensual de pasajeros en aeropuertos del grupo Heathrow',\n", " xaxis=XAxis(title='Mes', showgrid=False, showline=True, mirror='ticks', linewidth=2),\n", " yaxis=YAxis(title='Pasajeros', zeroline=False, showline=True, mirror='ticks', linewidth=2),\n", " margin=Margin(r=20, t=80))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Figure\n", "\n", "Una vez ya tenemos los datos y el *layout* podemos pasar a componer la figura y subirla al servidor." ] }, { "cell_type": "code", "collapsed": false, "input": [ "p_fig = Figure(data=p_data, layout=p_layout)\n", "p_plot = py.iplot(p_fig, filename='pybonacci/heathrow-pasajeros')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 11 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Diccionarios y listas\n", "\n", "Tanto `Figure` como `Layout`, `XAxis`, `YAxis` y `Margin` se podr\u00edan substituir por la expresi\u00f3n `dict()` pues, como ya hemos mencionados, Plotly trabaja con diccionarios y listas de Python. Sin embargo, el utilizar estas herramientas de `plotly.graph_objs` nos da acceso a la ayuda, y nos permite validar los par\u00e1metros introducidos." ] }, { "cell_type": "code", "collapsed": false, "input": [ "m_data = Data([Scatter(name=col,\n", " x=mercancias.index,\n", " y=mercancias[col],\n", " mode='lines') for col in pasajeros.columns.values[:4]])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "m_layout = Layout(title='Tr\u00e1fico mensual de mercanc\u00edas en aeropuertos del grupo Heathrow',\n", " xaxis=XAxis(title='Mes', showgrid=False, showline=True, mirror='ticks', linewidth=2),\n", " yaxis=YAxis(title='Mercanc\u00edas (t)', zeroline=False, showline=True, mirror='ticks', lineheight=2),\n", " margin=Margin(r=20, t=80))" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "PlotlyDictKeyError", "evalue": "Invalid key, 'lineheight', for class, 'YAxis'.\n\nRun 'help(plotly.graph_objs.YAxis)' for more information.\n\nPath To Error:\n['lineheight']\n\nAdditional Notes:\nCouldn't find uses for key: 'lineheight'\n\n", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mPlotlyDictKeyError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m m_layout = Layout(title='Tr\u00e1fico mensual de mercanc\u00edas en aeropuertos del grupo Heathrow',\n\u001b[0;32m 2\u001b[0m \u001b[0mxaxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mXAxis\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtitle\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'Mes'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mshowgrid\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mshowline\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmirror\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'ticks'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlinewidth\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0myaxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mYAxis\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtitle\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'Mercanc\u00edas (t)'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mzeroline\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mshowline\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmirror\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'ticks'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlineheight\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m margin=Margin(r=20, t=80))\n", "\u001b[1;32mC:\\Miniconda3\\lib\\site-packages\\plotly\\graph_objs\\graph_objs.py\u001b[0m in \u001b[0;36m__init__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 536\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mclass_name\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[1;34m'PlotlyTrace'\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mclass_name\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[1;34m'Trace'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 537\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'type'\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mNAME_TO_KEY\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mclass_name\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 538\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvalidate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 539\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__name__\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m'PlotlyDict'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 540\u001b[0m warnings.warn(\"\\nThe PlotlyDict class is a base class of \"\n", "\u001b[1;32mC:\\Miniconda3\\lib\\site-packages\\plotly\\graph_objs\\graph_objs.py\u001b[0m in \u001b[0;36mvalidate\u001b[1;34m(self, caller)\u001b[0m\n\u001b[0;32m 784\u001b[0m raise exceptions.PlotlyDictKeyError(obj=self,\n\u001b[0;32m 785\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 786\u001b[1;33m notes=notes)\n\u001b[0m\u001b[0;32m 787\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 788\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mto_string\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlevel\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mindent\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0meol\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'\\n'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpretty\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmax_chars\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m80\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mPlotlyDictKeyError\u001b[0m: Invalid key, 'lineheight', for class, 'YAxis'.\n\nRun 'help(plotly.graph_objs.YAxis)' for more information.\n\nPath To Error:\n['lineheight']\n\nAdditional Notes:\nCouldn't find uses for key: 'lineheight'\n\n" ] } ], "prompt_number": 13 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si hubiesemos hecho lo mismo con `dict()`, el error hubiese pasado desapercibido hasta el final." ] }, { "cell_type": "code", "collapsed": false, "input": [ "m_layout = dict(title='Tr\u00e1fico mensual de mercanc\u00edas en aeropuertos del grupo Heathrow',\n", " xaxis=dict(title='Mes', showgrid=False, showline=True, mirror='ticks', linewidth=2),\n", " yaxis=dict(title='Mercanc\u00edas (t)', zeroline=False, showline=True, mirror='ticks', linewidth=2),\n", " margin=dict(r=20, t=80))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ "m_fig = Figure(data=m_data, layout=m_layout)\n", "m_plot = py.iplot(m_fig, filename='pybonacci/heathrow-mercancias')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 15 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Interpretaci\u00f3n de los datos\n", "\n", "Disponemos de una muestra lo suficientemente grande como desaprovechar la oportunidad de extraer alguna conclusi\u00f3n al respecto.\n", "Y contamos con la ventaja de poder hacer zoom en los datos, lo cual resulta especialmente \u00fatil en le tr\u00e1fico de mercanc\u00edas, donde el aeropuerto de Heathrow est\u00e1 varios \u00f3rdenes de magnitud por encima del resto.\n", "\n", "#### Pasajeros\n", "\n", "Vemos claramente que en los meses de verano hay un aumento del n\u00famero de pasajeros en todos los aeropuertos del grupo.\n", "Tambi\u00e9n se aprecia un ligero repunte en el mes de diciembre con motivo, previsiblemente, de las vacaciones de navidad.\n", "Esto lo podemos visualizar de otra manera mediante un `Heatmap` del aeropuerto de Heathrow.\n", "\n", "Para ello vamos a utilizar el paquete `calendar` que nos permitir\u00e1 crear una lista con los nombres de los meses; y Numpy para crear una lista con los a\u00f1os." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import calendar\n", "import numpy as np" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para representar el `Heatmap` necesitaremos agrupar los datos por a\u00f1os o meses, en funci\u00f3n del eje *y* que tomemos.\n", "En este caso hemos decido representar los meses en el eje de ordenadas, por lo tanto agruparemos los datos por meses.\n", "Para ello nos valdremos de una [funci\u00f3n an\u00f3nima](https://docs.python.org/3.4/reference/expressions.html#lambda)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "gb = lambda x: x.month" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 17 }, { "cell_type": "code", "collapsed": false, "input": [ "data = Data([Heatmap(x=np.arange(2005,2015),\n", " y=calendar.month_abbr[1:],\n", " z=[grp['Heathrow'] for key, grp in pasajeros.groupby(gb)],\n", " colorscale='Portland')])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 18 }, { "cell_type": "markdown", "metadata": {}, "source": [ "En el eje *x* hemos colocado los a\u00f1os, en el eje *y* los meses, y la intensidad del color viene determinada por el n\u00famero de pasajeros.\n", "\n", "Con `Layout` a\u00f1adimos el t\u00edtulo de la gr\u00e1fica y los nombres de los ejes, y tambi\u00e9n podemos especificar el tama\u00f1o de la gr\u00e1fica deshabilitando el `autosize` y definiendo nuestro propio ancho y alto." ] }, { "cell_type": "code", "collapsed": false, "input": [ "layout = Layout(title='Tr\u00e1fico de pasajeros en el aeropuerto de Heathrow',\n", " autosize=False,\n", " width=550,\n", " height=550,\n", " xaxis=XAxis(title='A\u00f1o', showgrid=False),\n", " yaxis=YAxis(title='Mes', showgrid=False))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 19 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ya podemos publicar nuestra gr\u00e1fica de la manera habitual." ] }, { "cell_type": "code", "collapsed": false, "input": [ "heatmap_plot = py.iplot(Figure(data=data,layout=layout), filename='pybonacci/heathrow-heatmap')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 20 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Mercanc\u00edas\n", "\n", "Si en el transporte de pasajeros hay un patr\u00f3n claro, el transporte de mercanc\u00edas por avi\u00f3n no muestra signos de estacionalidad.\n", "Para verlo mejor podr\u00edamos volver a emplear un `Heatmap`, pero vamos a hacerlo con un [diagrama de caja](http://es.wikipedia.org/wiki/Diagrama_de_caja) `Box` para el aeropuerto de Heathrow.\n", "\n", "Aprovecharemos nuevamente la agrupaci\u00f3n por meses que hemos empleado para el `Heatmap` de pasajeros. Nuevamente hacemos uso de las list comprehensions de Python para crear una lista de bloques, cada uno correspondiente a un mes. Lo mismo podr\u00edamos conseguirlo sin crear una lista y sin necesidad de agrupar si en vez de asignar un `name` asignamos un \u00fanico array `x` con el valor del mes correspondiente a cada `y`. Con `boxpoints='all'` lo que hacemos es mostrar los puntos de la muestra al lado de cada bloque." ] }, { "cell_type": "code", "collapsed": false, "input": [ "data = Data([Box(name=calendar.month_abbr[key],\n", " y=grp['Heathrow'].values,\n", " boxpoints='all') for key, grp in mercancias.groupby(gb)])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 21 }, { "cell_type": "markdown", "metadata": {}, "source": [ "A\u00f1adimos, como es costumbre, un t\u00edtulo a la gr\u00e1fica y aprovechamos para ocultar la leyenda y ajustar los margenes." ] }, { "cell_type": "code", "collapsed": false, "input": [ "layout = Layout(title='Tr\u00e1fico de mercanc\u00edas en el aeropuerto de Heathrow (2005-2014)',\n", " showlegend=False,\n", " margin=Margin(r=20, t=90))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 22 }, { "cell_type": "code", "collapsed": false, "input": [ "box_plot = py.iplot(Figure(data=data, layout=layout), filename='pybonacci/heathrow-box')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 23 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Pasajeros vs mercanc\u00edas\n", "\n", "Hasta ahora hemos visto por separado los datos de pasajeros y mercanc\u00edas. Compararemos en una \u00fanica gr\u00e1fica los datos del aeropuerto de Glasgow. Para facilitar la visualizaci\u00f3n y compensar la diferencia de magnitud utilizaremos m\u00faltiples ejes y, de paso, emplearemos diferentes representaciones para el tr\u00e1fico de pasajeros y el de mercanc\u00edas.\n", "\n", "Los pasajeros los representaremos mediante l\u00edneas y puntos `'lines+markers'` y le asignamos el segundo eje *y* `'y2'`, pues vamos a querer que nos lo represente por encima de las barras de tr\u00e1fico de mercanc\u00edas. \n", "El orden en Plotly es importante.\n", "Vamos a representar las lineas de color dorado primero como horizontales y luego verticales de un valor a otro con `shape='hv'`.\n", "Los puntos ser\u00e1n de un color dorado m\u00e1s claro con el borde tambi\u00e9n dorado." ] }, { "cell_type": "code", "collapsed": false, "input": [ "pas = Scatter(name='Pasajeros',\n", " x=pasajeros.index,\n", " y=pasajeros['Glasgow'],\n", " yaxis='y2',\n", " mode='lines+markers',\n", " line=Line(shape='hv', color='darkgoldenrod'),\n", " marker=Marker(color='goldenrod',\n", " line=Line(color='darkgoldenrod', width=2)))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 24 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por su parte, el tr\u00e1fico de mercanc\u00edas lo representaremos como barras verticales de color gris claro. Por defecto se le asigna el primer eje *y*." ] }, { "cell_type": "code", "collapsed": false, "input": [ "mer = Bar(name='Mercanc\u00edas',\n", " x=pasajeros.index,\n", " y=mercancias['Glasgow'],\n", " marker=Marker(color='lightgray'))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 25 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creamos la lista con los elementos a representar." ] }, { "cell_type": "code", "collapsed": false, "input": [ "data = Data([mer, pas])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 26 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por \u00faltimo configuramos el *layout* a\u00f1adiendo un t\u00edtulo a la gr\u00e1fica y configurando los ejes." ] }, { "cell_type": "code", "collapsed": false, "input": [ "layout = Layout(title='Tr\u00e1fico de pasajeros y mercanc\u00edas en el aeropuerto de Glasgow',\n", " showlegend=False,\n", " xaxis=XAxis(title='Mes'),\n", " yaxis=YAxis(title='Mercanc\u00edas (t)',\n", " showgrid=False),\n", " yaxis2=YAxis(title='Pasajeros',\n", " showgrid=False,\n", " overlaying='y',\n", " side='right'))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 27 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Incluimos tambi\u00e9n una nota de texto indicando la fuente de los datos.\n", "Plotly nos permite untilizar un subconjunto de etiquetas HTML para dar formato a los textos para por ejemplo incluir nuevas l\u00edneas (`
`) o a\u00f1adir hiperv\u00ednculos (``) que podremos utilizar en cualquier texto de la gr\u00e1fica (t\u00edtulos y anotaciones)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fuente = Annotation(text=\"Fuente: LHR Airports Limited\",\n", " xref='paper', # empleamos coordenadas 'paper', con ello la nota no se mover\u00e1 al mover los ejes.\n", " yref='paper',\n", " x=0,\n", " y=-0.15,\n", " showarrow=False)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 28 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Actualizamos el diccionario de *layout* de la gr\u00e1fica." ] }, { "cell_type": "code", "collapsed": false, "input": [ "layout.update(annotations=Annotations([fuente]))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 29 }, { "cell_type": "code", "collapsed": false, "input": [ "ma_plot = py.iplot(Figure(data=data, layout=layout), filename='pybonacci/heathrow-multipleaxis')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mucho m\u00e1s\n", "\n", "Aqu\u00ed s\u00f3lo hemos mostrado una peque\u00f1a parte del potencial de Plotly.\n", "Todo aquel que quiere ampliar detalles encontrar\u00e1 mucha m\u00e1s informaci\u00f3n en el [API library](https://plot.ly/python/) de Plotly.\n", "Tambi\u00e9n se pueden sacar buenas ideas del [graphing news feed](https://plot.ly/) viendo lo que publican otros usuarios.\n", "\n", "No dudeis en contactar con nosotros o el equipo de Plotly por [email](mailto:feedback@plot.ly) o [Twitter](https://twitter.com/plotlygraphs) para cualquier duda o sugerencia." ] } ], "metadata": {} } ] }