Collaboration with Plotly in Python/v3

An IPython Notebook showing how to collaboration between different programming languages with plotly


Note: this page is part of the documentation for version 3 of Plotly.py, which is not the most recent version.
See our Version 4 Migration Guide for information about how to upgrade.

IPython and Plotly: A Rosetta Stone for MATLAB,
R, Python, and Excel plotting

Collaboration, data analysis, and data visualization sometimes feels like this:

In [1]:
from IPython.display import Image
Image(url = 'https://i.imgur.com/4DrMgLI.png')
Out[1]:

Graphing and data analysis need a Rosetta Stone to solve the fragmentation and collaboration problem. Plotly is about bridging the divide and serving as an interoperable platform for analysis and plotting. You can import, edit, and plot data using scripts and data from Python, MATLAB, R, Julia, Perl, REST, Arduino, Raspberry Pi, or Excel. So can your team.

All in the same online plot.

Read on to learn more, or run $ pip install plotly and copy and paste the code below. Plotly is online, meaning no downloads or installations necessary.

In [2]:
%matplotlib inline
import matplotlib.pyplot as plt # side-stepping mpl backend
import matplotlib.gridspec as gridspec # subplots
import numpy as np

You can use our key, or sign-up to get started. It's free for any public sharing and you own your data, so you can make and share as many plots as you want.

In [3]:
import plotly.plotly as py
import plotly.tools as tls
from plotly.graph_objs import *
py.sign_in("IPython.Demo", "1fw3zw2o13")
In [4]:
import plotly
plotly.__version__
Out[4]:
'1.0.12'

I. shareable matplotlib figures

Let's start out with a matplotlib example. We also have a user guide section on the subject.

In [5]:
fig1 = plt.figure()

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab

mean = [10,12,16,22,25]
variance = [3,6,8,10,12]

x = np.linspace(0,40,1000)

for i in range(4):
    sigma = np.sqrt(variance[i])
    y = mlab.normpdf(x,mean[i],sigma)
    plt.plot(x,y, label=r'$v_{}$'.format(i+1))

plt.xlabel("X")
plt.ylabel("P(X)")        
Out[5]:
<matplotlib.text.Text at 0x7f549f2ea050>

To re-create the graph in Plotly and use Plotly's defaults, call iplot and add strip_style.

In [6]:
py.iplot_mpl(fig1, strip_style = True)

It's shareable at a URL, contains the data as part of the plot, and can be edited collaboratively from any API or our web app. Head over to Plotly's API to see more, and check out our user guide to see how it all works.

Plotly also jointly preserves the data in a graph, the graph, and the graph description (in this case JSON). That's valuable. One study in current biology found that over 90 percent of data from papers published over the past 20 years was not available. So sharing data is good for science and reproducibility, useful for your projects, and great for collaboration.

II. ggplot2 plots in Plotly

Let's take a real-world look storing data and graphs together. Suppose you see a graph on the World Bank website. The graph uses ggplot2, a remarkable plotting library for R.

In [7]:
from IPython.display import Image
Image(url = 'http://i.imgur.com/PkRRmHq.png')
Out[7]:

You would like to re-make the graph and analyze and share the data. Getting the data using Plotly is easy. You can run the ggplot2 script in RStudio. Here we're running it using the new R kernel for IPython). The Notebook with the replicable code and installation is here.

In [8]:
library(WDI)
library(ggplot2)
 
#Grab GNI per capita data for Chile, Hungary and Uruguay
 
dat = WDI(indicator='NY.GNP.PCAP.CD', country=c('CL','HU','UY'), start=1960, end=2012)
 
#a quick plot with legend, title and label
 
wb <- ggplot(dat, aes(year, NY.GNP.PCAP.CD, color=country)) + geom_line() 
+     xlab('Year') + ylab('GDI per capita (Atlas Method USD)') 
+     labs(title <- "GNI Per Capita ($USD Atlas Method)")

ggplotly(wb)

We can add ggplotly to the call, which will draw the figure with Plotly's R API. Then we can call it in a Notebook. You can similarly call any Plotly graph with the username and graph id pair.

In [9]:
tls.embed('RgraphingAPI', '1457')

Note: the data is called from a WDI database; if you make it with Plotly, the data is stored with the plot. I forked the data and shared it: https://plotly.com/~MattSundquist/1343.

If you want to use Plotly's default graph look, you can edit the graph with Python.

In [10]:
fig = py.get_figure('RgraphingAPI', '1457')
fig.strip_style()
py.iplot(fig)

Often we come to a visualization with data rather than coming to data with a visualization. In that case, Plotly is useful for quick exploration, with matplotlib or Plotly's API.

In [11]:
my_data = py.get_figure('PythonAPI', '455').get_data()
In [12]:
%matplotlib inline
import matplotlib.pyplot as plt
In [13]:
fig1 = plt.figure()

plt.subplot(311)
plt.plot(my_data[0]['x'], my_data[0]['y'])
plt.subplot(312)
plt.plot(my_data[1]['x'], my_data[1]['y'])
plt.subplot(313)
plt.plot(my_data[2]['x'], my_data[2]['y'])

py.iplot_mpl(fig1, strip_style = True)

You can also draw the graph with subplots in Plotly.

In [14]:
my_data[1]['yaxis'] = 'y2'
my_data[2]['yaxis'] = 'y3'

layout = Layout(
    yaxis=YAxis(
        domain=[0, 0.33]
    ),
    legend=Legend(
        traceorder='reversed'
    ),
    yaxis2=YAxis(
        domain=[0.33, 0.66]
    ),
    yaxis3=YAxis(
        domain=[0.66, 1]
    )
)

fig = Figure(data=my_data, layout=layout)

py.iplot(fig)

Then maybe I want to edit it quickly with a GUI, without coding. I click through to the graph in the "data and graph" link, fork my own copy, and can switch between graph types, styling options, and more.

In [15]:
Image(url = 'http://i.imgur.com/rHP53Oz.png')
Out[15]:

Now, having re-styled it, we can call the graph back into the NB, and if we want, get the figure information for the new, updated graph. The graphs below are meant to show the flexibility available to you in styling from the GUI.

In [16]:
tls.embed('MattSundquist', '1404')
In [17]:
tls.embed('MattSundquist', '1339')

We can also get the data in a grid, and run stats, fits, functions, add error bars, and more. Plotly keeps data and graphs together.

In [18]:
Image(url = 'http://i.imgur.com/JJkNPJg.png')
Out[18]:

And there we have it. A reproducible figure, drawn with D3 that includes the plot, data, and plot structure. And you can easily call that figure or data as well. Check to see what URL it is by hoving on "data and graph" and then call that figure.

In [19]:
ggplot = py.get_figure('MattSundquist', '1339') 
In [20]:
ggplot #print it
Out[20]:
{'data': [{'line': {'color': 'rgb(31, 119, 180)', 'width': 4},
   'mode': 'lines',
   'name': 'Chile',
   'type': 'scatter',
   'x': [1960,
    1961,
    1962,
    1963,
    1964,
    1965,
    1966,
    1967,
    1968,
    1969,
    1970,
    1971,
    1972,
    1973,
    1974,
    1975,
    1976,
    1977,
    1978,
    1979,
    1980,
    1981,
    1982,
    1983,
    1984,
    1985,
    1986,
    1987,
    1988,
    1989,
    1990,
    1991,
    1992,
    1993,
    1994,
    1995,
    1996,
    1997,
    1998,
    1999,
    2000,
    2001,
    2002,
    2003,
    2004,
    2005,
    2006,
    2007,
    2008,
    2009,
    2010,
    2011,
    2012],
   'y': [None,
    None,
    600,
    640,
    660,
    650,
    740,
    760,
    770,
    800,
    860,
    1020,
    1110,
    1320,
    1620,
    1120,
    980,
    1070,
    1320,
    1740,
    2240,
    2640,
    2190,
    1780,
    1600,
    1410,
    1410,
    1560,
    1820,
    2090,
    2240,
    2490,
    3020,
    3330,
    3610,
    4320,
    4930,
    5380,
    5250,
    4910,
    4920,
    4760,
    4550,
    4570,
    5230,
    6250,
    7260,
    8630,
    10020,
    9930,
    10720,
    12270,
    14310]},
  {'line': {'color': 'rgb(255, 127, 14)', 'width': 4},
   'mode': 'lines',
   'name': 'Hungary',
   'type': 'scatter',
   'x': [1960,
    1961,
    1962,
    1963,
    1964,
    1965,
    1966,
    1967,
    1968,
    1969,
    1970,
    1971,
    1972,
    1973,
    1974,
    1975,
    1976,
    1977,
    1978,
    1979,
    1980,
    1981,
    1982,
    1983,
    1984,
    1985,
    1986,
    1987,
    1988,
    1989,
    1990,
    1991,
    1992,
    1993,
    1994,
    1995,
    1996,
    1997,
    1998,
    1999,
    2000,
    2001,
    2002,
    2003,
    2004,
    2005,
    2006,
    2007,
    2008,
    2009,
    2010,
    2011,
    2012],
   'y': [None,
    None,
    None,
    None,
    None,
    None,
    None,
    None,
    None,
    None,
    540,
    590,
    670,
    830,
    1000,
    1150,
    1200,
    1330,
    1520,
    1770,
    2070,
    2200,
    2170,
    2010,
    1930,
    1860,
    2040,
    2400,
    2710,
    2770,
    2880,
    2740,
    3140,
    3630,
    4000,
    4220,
    4320,
    4370,
    4380,
    4460,
    4580,
    4720,
    5210,
    6550,
    8540,
    10220,
    11040,
    11510,
    12890,
    12980,
    12930,
    12900,
    12410]},
  {'line': {'color': 'rgb(44, 160, 44)', 'width': 4},
   'mode': 'lines',
   'name': 'Uruguay',
   'type': 'scatter',
   'x': [1960,
    1961,
    1962,
    1963,
    1964,
    1965,
    1966,
    1967,
    1968,
    1969,
    1970,
    1971,
    1972,
    1973,
    1974,
    1975,
    1976,
    1977,
    1978,
    1979,
    1980,
    1981,
    1982,
    1983,
    1984,
    1985,
    1986,
    1987,
    1988,
    1989,
    1990,
    1991,
    1992,
    1993,
    1994,
    1995,
    1996,
    1997,
    1998,
    1999,
    2000,
    2001,
    2002,
    2003,
    2004,
    2005,
    2006,
    2007,
    2008,
    2009,
    2010,
    2011,
    2012],
   'y': [None,
    None,
    580,
    610,
    660,
    680,
    720,
    640,
    610,
    670,
    820,
    850,
    870,
    1060,
    1370,
    1620,
    1490,
    1420,
    1630,
    2150,
    2870,
    3650,
    3290,
    2190,
    1740,
    1510,
    1780,
    2210,
    2600,
    2730,
    2840,
    3180,
    3830,
    4350,
    5040,
    5530,
    6160,
    6970,
    7240,
    7260,
    7050,
    6500,
    5140,
    4240,
    4130,
    4720,
    5380,
    6380,
    7690,
    8520,
    10110,
    11700,
    13580]}],
 'layout': {'annotations': [{'align': 'center',
    'arrowcolor': '',
    'arrowhead': 1,
    'arrowsize': 1,
    'arrowwidth': 0,
    'ax': -10,
    'ay': -28.335936546325684,
    'bgcolor': 'rgba(0,0,0,0)',
    'bordercolor': '',
    'borderpad': 1,
    'borderwidth': 1,
    'font': {'color': '', 'family': '', 'size': 0},
    'opacity': 1,
    'showarrow': False,
    'tag': '',
    'text': 'Source: <a href="http://blogs.worldbank.org/opendata/accessing-world-bank-data-apis-python-r-ruby-stata">World Bank</a>',
    'x': 0.9880317848410782,
    'xanchor': 'auto',
    'xref': 'paper',
    'y': 0.02994334820619583,
    'yanchor': 'auto',
    'yref': 'paper'}],
  'autosize': True,
  'bargap': 0.2,
  'bargroupgap': 0,
  'barmode': 'group',
  'boxgap': 0.3,
  'boxgroupgap': 0.3,
  'boxmode': 'overlay',
  'dragmode': 'zoom',
  'font': {'color': 'rgb(67, 67, 67)',
   'family': "'Open sans', verdana, arial, sans-serif",
   'size': 12},
  'height': 547,
  'hidesources': False,
  'hovermode': 'x',
  'legend': {'bgcolor': '#fff',
   'bordercolor': '#444',
   'borderwidth': 0,
   'font': {'color': '', 'family': '', 'size': 0},
   'traceorder': 'normal',
   'x': 1.02,
   'xanchor': 'left',
   'y': 0.5,
   'yanchor': 'auto'},
  'margin': {'autoexpand': True,
   'b': 80,
   'l': 80,
   'pad': 0,
   'r': 80,
   't': 100},
  'paper_bgcolor': '#fff',
  'plot_bgcolor': 'rgba(245, 247, 247, 0.7)',
  'separators': '.,',
  'showlegend': True,
  'title': 'GNI Per Capita ($USD Atlas Method)',
  'titlefont': {'color': '', 'family': '', 'size': 0},
  'width': 1304,
  'xaxis': {'anchor': 'y',
   'autorange': True,
   'autotick': True,
   'domain': [0, 1],
   'dtick': 10,
   'exponentformat': 'B',
   'gridcolor': 'rgb(255, 255, 255)',
   'gridwidth': 1,
   'linecolor': '#444',
   'linewidth': 1,
   'mirror': False,
   'nticks': 0,
   'overlaying': False,
   'position': 0,
   'range': [1960, 2012],
   'rangemode': 'normal',
   'showexponent': 'all',
   'showgrid': True,
   'showline': False,
   'showticklabels': True,
   'tick0': 0,
   'tickangle': 'auto',
   'tickcolor': '#444',
   'tickfont': {'color': '', 'family': '', 'size': 0},
   'ticklen': 5,
   'ticks': '',
   'tickwidth': 1,
   'title': 'year',
   'titlefont': {'color': '', 'family': '', 'size': 0},
   'type': 'linear',
   'zeroline': False,
   'zerolinecolor': '#444',
   'zerolinewidth': 1},
  'yaxis': {'anchor': 'x',
   'autorange': True,
   'autotick': True,
   'domain': [0, 1],
   'dtick': 'D1',
   'exponentformat': 'B',
   'gridcolor': 'rgb(255, 255, 255)',
   'gridwidth': 1,
   'linecolor': '#444',
   'linewidth': 1,
   'mirror': False,
   'nticks': 0,
   'overlaying': False,
   'position': 0,
   'range': [2.6533245446042573, 4.234708848978488],
   'rangemode': 'normal',
   'showexponent': 'all',
   'showgrid': True,
   'showline': False,
   'showticklabels': True,
   'tick0': 0,
   'tickangle': 'auto',
   'tickcolor': '#444',
   'tickfont': {'color': '', 'family': '', 'size': 0},
   'ticklen': 5,
   'ticks': '',
   'tickwidth': 1,
   'title': 'NY.GNP.PCAP.CD',
   'titlefont': {'color': '', 'family': '', 'size': 0},
   'type': 'log',
   'zeroline': False,
   'zerolinecolor': '#444',
   'zerolinewidth': 1}}}

Want to analyze the data or use it for another figure?

In [21]:
ggplot_data = ggplot.get_data()
In [22]:
ggplot_data
Out[22]:
{'data': [{'name': 'Chile',
   'x': [1960,
    1961,
    1962,
    1963,
    1964,
    1965,
    1966,
    1967,
    1968,
    1969,
    1970,
    1971,
    1972,
    1973,
    1974,
    1975,
    1976,
    1977,
    1978,
    1979,
    1980,
    1981,
    1982,
    1983,
    1984,
    1985,
    1986,
    1987,
    1988,
    1989,
    1990,
    1991,
    1992,
    1993,
    1994,
    1995,
    1996,
    1997,
    1998,
    1999,
    2000,
    2001,
    2002,
    2003,
    2004,
    2005,
    2006,
    2007,
    2008,
    2009,
    2010,
    2011,
    2012],
   'y': [None,
    None,
    600,
    640,
    660,
    650,
    740,
    760,
    770,
    800,
    860,
    1020,
    1110,
    1320,
    1620,
    1120,
    980,
    1070,
    1320,
    1740,
    2240,
    2640,
    2190,
    1780,
    1600,
    1410,
    1410,
    1560,
    1820,
    2090,
    2240,
    2490,
    3020,
    3330,
    3610,
    4320,
    4930,
    5380,
    5250,
    4910,
    4920,
    4760,
    4550,
    4570,
    5230,
    6250,
    7260,
    8630,
    10020,
    9930,
    10720,
    12270,
    14310]},
  {'name': 'Hungary',
   'x': [1960,
    1961,
    1962,
    1963,
    1964,
    1965,
    1966,
    1967,
    1968,
    1969,
    1970,
    1971,
    1972,
    1973,
    1974,
    1975,
    1976,
    1977,
    1978,
    1979,
    1980,
    1981,
    1982,
    1983,
    1984,
    1985,
    1986,
    1987,
    1988,
    1989,
    1990,
    1991,
    1992,
    1993,
    1994,
    1995,
    1996,
    1997,
    1998,
    1999,
    2000,
    2001,
    2002,
    2003,
    2004,
    2005,
    2006,
    2007,
    2008,
    2009,
    2010,
    2011,
    2012],
   'y': [None,
    None,
    None,
    None,
    None,
    None,
    None,
    None,
    None,
    None,
    540,
    590,
    670,
    830,
    1000,
    1150,
    1200,
    1330,
    1520,
    1770,
    2070,
    2200,
    2170,
    2010,
    1930,
    1860,
    2040,
    2400,
    2710,
    2770,
    2880,
    2740,
    3140,
    3630,
    4000,
    4220,
    4320,
    4370,
    4380,
    4460,
    4580,
    4720,
    5210,
    6550,
    8540,
    10220,
    11040,
    11510,
    12890,
    12980,
    12930,
    12900,
    12410]},
  {'name': 'Uruguay',
   'x': [1960,
    1961,
    1962,
    1963,
    1964,
    1965,
    1966,
    1967,
    1968,
    1969,
    1970,
    1971,
    1972,
    1973,
    1974,
    1975,
    1976,
    1977,
    1978,
    1979,
    1980,
    1981,
    1982,
    1983,
    1984,
    1985,
    1986,
    1987,
    1988,
    1989,
    1990,
    1991,
    1992,
    1993,
    1994,
    1995,
    1996,
    1997,
    1998,
    1999,
    2000,
    2001,
    2002,
    2003,
    2004,
    2005,
    2006,
    2007,
    2008,
    2009,
    2010,
    2011,
    2012],
   'y': [None,
    None,
    580,
    610,
    660,
    680,
    720,
    640,
    610,
    670,
    820,
    850,
    870,
    1060,
    1370,
    1620,
    1490,
    1420,
    1630,
    2150,
    2870,
    3650,
    3290,
    2190,
    1740,
    1510,
    1780,
    2210,
    2600,
    2730,
    2840,
    3180,
    3830,
    4350,
    5040,
    5530,
    6160,
    6970,
    7240,
    7260,
    7050,
    6500,
    5140,
    4240,
    4130,
    4720,
    5380,
    6380,
    7690,
    8520,
    10110,
    11700,
    13580]}],
 'layout': [{}]}

Want to use Python to analyze your data? You can read that data into a pandas DataFrame.

In [23]:
import pandas as pd
In [24]:
my_data = py.get_figure('MattSundquist', '1339').get_data()
frames = {data['name']: {'x': data['x'], 'y': data['y']} for data in my_data['data']}
df = pd.DataFrame(frames)
df
Out[24]:
Chile Hungary Uruguay
x [1960, 1961, 1962, 1963, 1964, 1965, 1966, 196... [1960, 1961, 1962, 1963, 1964, 1965, 1966, 196... [1960, 1961, 1962, 1963, 1964, 1965, 1966, 196...
y [None, None, 600, 640, 660, 650, 740, 760, 770... [None, None, None, None, None, None, None, Non... [None, None, 580, 610, 660, 680, 720, 640, 610...

2 rows × 3 columns

Plotly has interactive support that lets you call help on graph objects. Try layout or data too. For example.

In [25]:
from plotly.graph_objs import Data, Layout, Figure
In [26]:
help(Figure)
Help on class Figure in module plotly.graph_objs.graph_objs:

class Figure(PlotlyDict)
 |  A dictionary-like object representing a figure to be rendered in plotly.
 |  
 |      This is the container for all things to be rendered in a figure.
 |  
 |      For help with setting up subplots, run:
 |      `help(plotly.tools.get_subplots)`
 |  
 |      
 |  Quick method reference:
 |  
 |      Figure.update(changes)
 |      Figure.strip_style()
 |      Figure.get_data()
 |      Figure.to_graph_objs()
 |      Figure.validate()
 |      Figure.to_string()
 |      Figure.force_clean()
 |  
 |  Valid keys:
 |  
 |      data [required=False] (value=Data object | dictionary-like):
 |          A list-like array of the data that is to be visualized.
 |  
 |          For more, run `help(plotly.graph_objs.Data)`
 |  
 |      layout [required=False] (value=Layout object | dictionary-like):
 |          The layout dictionary-like object contains axes information, gobal
 |          settings, and layout information related to the rendering of the
 |          figure.
 |  
 |          For more, run `help(plotly.graph_objs.Layout)`
 |  
 |  Method resolution order:
 |      Figure
 |      PlotlyDict
 |      __builtin__.dict
 |      __builtin__.object
 |  
 |  Methods defined here:
 |  
 |  __init__(self, *args, **kwargs)
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from PlotlyDict:
 |  
 |  force_clean(self)
 |      Attempts to convert to graph_objs and call force_clean() on values.
 |      
 |      Calling force_clean() on a PlotlyDict will ensure that the object is
 |      valid and may be sent to plotly. This process will also remove any
 |      entries that end up with a length == 0.
 |      
 |      Careful! This will delete any invalid entries *silently*.
 |  
 |  get_data(self)
 |      Returns the JSON for the plot with non-data elements stripped.
 |  
 |  strip_style(self)
 |      Strip style from the current representation.
 |      
 |      All PlotlyDicts and PlotlyLists are guaranteed to survive the
 |      stripping process, though they made be left empty. This is allowable.
 |      
 |      Keys that will be stripped in this process are tagged with
 |      `'type': 'style'` in the INFO dictionary listed in graph_objs_meta.py.
 |      
 |      This process first attempts to convert nested collections from dicts
 |      or lists to subclasses of PlotlyList/PlotlyDict. This process forces
 |      a validation, which may throw exceptions.
 |      
 |      Then, each of these objects call `strip_style` on themselves and so
 |      on, recursively until the entire structure has been validated and
 |      stripped.
 |  
 |  to_graph_objs(self)
 |      Walk obj, convert dicts and lists to plotly graph objs.
 |      
 |      For each key in the object, if it corresponds to a special key that
 |      should be associated with a graph object, the ordinary dict or list
 |      will be reinitialized as a special PlotlyDict or PlotlyList of the
 |      appropriate `kind`.
 |  
 |  to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80)
 |      Returns a formatted string showing graph_obj constructors.
 |      
 |              Example:
 |      
 |                  print obj.to_string()
 |      
 |              Keyword arguments:
 |              level (default = 0) -- set number of indentations to start with
 |              indent (default = 4) -- set indentation amount
 |              eol (default = '
 |      ') -- set end of line character(s)
 |              pretty (default = True) -- curtail long list output with a '...'
 |              max_chars (default = 80) -- set max characters per line
 |  
 |  update(self, dict1=None, **dict2)
 |      Update current dict with dict1 and then dict2.
 |      
 |      This recursively updates the structure of the original dictionary-like
 |      object with the new entries in the second and third objects. This
 |      allows users to update with large, nested structures.
 |      
 |      Note, because the dict2 packs up all the keyword arguments, you can
 |      specify the changes as a list of keyword agruments.
 |      
 |      Examples:
 |      # update with dict
 |      obj = Layout(title='my title', xaxis=XAxis(range=[0,1], domain=[0,1]))
 |      update_dict = dict(title='new title', xaxis=dict(domain=[0,.8]))
 |      obj.update(update_dict)
 |      obj
 |      {'title': 'new title', 'xaxis': {'range': [0,1], 'domain': [0,.8]}}
 |      
 |      # update with list of keyword arguments
 |      obj = Layout(title='my title', xaxis=XAxis(range=[0,1], domain=[0,1]))
 |      obj.update(title='new title', xaxis=dict(domain=[0,.8]))
 |      obj
 |      {'title': 'new title', 'xaxis': {'range': [0,1], 'domain': [0,.8]}}
 |      
 |      This 'fully' supports duck-typing in that the call signature is
 |      identical, however this differs slightly from the normal update
 |      method provided by Python's dictionaries.
 |  
 |  validate(self)
 |      Recursively check the validity of the keys in a PlotlyDict.
 |      
 |      The valid keys constitute the entries in each object
 |      dictionary in INFO stored in graph_objs_meta.py.
 |      
 |      The validation process first requires that all nested collections be
 |      converted to the appropriate subclass of PlotlyDict/PlotlyList. Then,
 |      each of these objects call `validate` and so on, recursively,
 |      until the entire object has been validated.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from PlotlyDict:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from PlotlyDict:
 |  
 |  __metaclass__ = <class 'plotly.graph_objs.graph_objs.DictMeta'>
 |      A meta class for PlotlyDict class creation.
 |      
 |      The sole purpose of this meta class is to properly create the __doc__
 |      attribute so that running help(Obj), where Obj is a subclass of PlotlyDict,
 |      will return information about key-value pairs for that object.
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from __builtin__.dict:
 |  
 |  __cmp__(...)
 |      x.__cmp__(y) <==> cmp(x,y)
 |  
 |  __contains__(...)
 |      D.__contains__(k) -> True if D has a key k, else False
 |  
 |  __delitem__(...)
 |      x.__delitem__(y) <==> del x[y]
 |  
 |  __eq__(...)
 |      x.__eq__(y) <==> x==y
 |  
 |  __ge__(...)
 |      x.__ge__(y) <==> x>=y
 |  
 |  __getattribute__(...)
 |      x.__getattribute__('name') <==> x.name
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(...)
 |      x.__gt__(y) <==> x>y
 |  
 |  __iter__(...)
 |      x.__iter__() <==> iter(x)
 |  
 |  __le__(...)
 |      x.__le__(y) <==> x<=y
 |  
 |  __len__(...)
 |      x.__len__() <==> len(x)
 |  
 |  __lt__(...)
 |      x.__lt__(y) <==> x<y
 |  
 |  __ne__(...)
 |      x.__ne__(y) <==> x!=y
 |  
 |  __repr__(...)
 |      x.__repr__() <==> repr(x)
 |  
 |  __setitem__(...)
 |      x.__setitem__(i, y) <==> x[i]=y
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -> size of D in memory, in bytes
 |  
 |  clear(...)
 |      D.clear() -> None.  Remove all items from D.
 |  
 |  copy(...)
 |      D.copy() -> a shallow copy of D
 |  
 |  fromkeys(...)
 |      dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.
 |      v defaults to None.
 |  
 |  get(...)
 |      D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.
 |  
 |  has_key(...)
 |      D.has_key(k) -> True if D has a key k, else False
 |  
 |  items(...)
 |      D.items() -> list of D's (key, value) pairs, as 2-tuples
 |  
 |  iteritems(...)
 |      D.iteritems() -> an iterator over the (key, value) items of D
 |  
 |  iterkeys(...)
 |      D.iterkeys() -> an iterator over the keys of D
 |  
 |  itervalues(...)
 |      D.itervalues() -> an iterator over the values of D
 |  
 |  keys(...)
 |      D.keys() -> list of D's keys
 |  
 |  pop(...)
 |      D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
 |      If key is not found, d is returned if given, otherwise KeyError is raised
 |  
 |  popitem(...)
 |      D.popitem() -> (k, v), remove and return some (key, value) pair as a
 |      2-tuple; but raise KeyError if D is empty.
 |  
 |  setdefault(...)
 |      D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
 |  
 |  values(...)
 |      D.values() -> list of D's values
 |  
 |  viewitems(...)
 |      D.viewitems() -> a set-like object providing a view on D's items
 |  
 |  viewkeys(...)
 |      D.viewkeys() -> a set-like object providing a view on D's keys
 |  
 |  viewvalues(...)
 |      D.viewvalues() -> an object providing a view on D's values
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from __builtin__.dict:
 |  
 |  __hash__ = None
 |  
 |  __new__ = <built-in method __new__ of type object>
 |      T.__new__(S, ...) -> a new object with type S, a subtype of T

III. MATLAB, Julia, and Perl plotting with Plotly

We just made a plot with R using ggplot2, edited it in an IPython Notebook with Python, edited with our web app, shared it, and read the data into a pandas DataFrame. We have another Notebook that shows how to use Plotly with seaborn, prettyplotlib, and ggplot for Python Your whole team can now collaborate, regardless of technical capability or language of choice. This linguistic flexibility and technical interoperability powers collaboration, and it's what Plotly is all about. Let's jump into a few more examples.

Let's say you see some code and data for a MATLAB gallery plot you love and want to share.

In [27]:
Image(url = 'http://i.imgur.com/bGj8EzI.png?1')
Out[27]:

You can use Plotly's MATLAB Open Source Graphing Library to make a shareable plots, with LaTeX included. You run the MATLAB code in your MATLAB environrment or the MATLAB kernel in IPython and add fig2plotly to the call. Check out the user guide to see the installation and setup.

In [28]:
%%matlab

close all

% Create a set of values for the damping factor
zeta = [0.01 .02 0.05 0.1 .2 .5 1 ];

% Define a color for each damping factor
colors = ['r' 'g' 'b' 'c' 'm' 'y' 'k'];

% Create a range of frequency values equally spaced logarithmically
w = logspace(-1, 1, 1000);

% Plot the gain vs. frequency for each of the seven damping factors
figure;
for i = 1:7
    a = w.^2 - 1;
    b = 2*w*zeta(i);
    gain = sqrt(1./(a.^2 + b.^2));
    loglog(w, gain, 'color', colors(i), 'linewidth', 2);
    hold on;
end

% Set the axis limits
axis([0.1 10 0.01 100]);

% Add a title and axis labels
title('Gain vs Frequency');
xlabel('Frequency');
ylabel('Gain');

% Turn the grid on
grid on;

% ----------------------------------------
% Let's convert the figure to plotly structures, and set stripping to false
[data, layout] = convertFigure(get(gcf), false);

% But, before we publish, let's modify and add some features:
% Naming the traces
for i=1:numel(data)
    data{i}.name =  ['$\\zeta = ' num2str(zeta(i)) '$']; %LATEX FORMATTING
    data{i}.showlegend = true;
end
% Adding a nice the legend
legendstyle = struct( ...
    'x' , 0.15, ...
    'y' , 0.9, ...
    'bgcolor' , '#E2E2E2', ...
    'bordercolor' , '#FFFFFF', ...
    'borderwidth' , 2, ...
    'traceorder' , 'normal' ...
    );
layout.legend = legendstyle;
layout.showlegend = true;

% Setting the hover mode
layout.hovermode = 'closest';

% Giving the plot a custom name
plot_name = 'My_improved_plot';

% Sending to Plotly
response = plotly(data, struct('layout', layout, ...
    'filename',plot_name, ...
	'fileopt', 'overwrite'));

display(response.url)
https://plotly.com/~MATLAB-demos/4

Which produces:

In [29]:
tls.embed('MATLAB-Demos', '4')

And you can similarly collaborate across all Plotly APIs, working on plots from IJulia, Perl, Arduino, Raspberry Pi, or Ruby. You could also append data to any figure from any API, or from the GUI. Want to make your own wrapper? Check out our REST API.

IV. WebPlotDigitizer and Plotly

Let's suppose next that you wanted to plot data from a graph you loved in a Facebook Data Science post.

In [30]:
Image(url = 'https://i.imgur.com/sAHsjk3.png')
Out[30]:

You can take a screenshot, and drag and drop the image into WebPlotDigitizer. Here's a tutorial on using the helpful tool, which includes the handy "Graph in Plotly" button. You can put it on your website so your users can easily access, graph, and share your data. And it links to your source.

In [31]:
Image (url = 'https://i.imgur.com/y4t5hdj.png')
Out[31]:

I can then make and share the graph in Plotly. You could do this to access data in any images you find online, then add fits or data from the grid or APIs. Check out our post with five fits to see more.

In [32]:
Image (url = 'http://i.imgur.com/BUOe85E.png')
Out[32]:

We'll add a fit then style it a bit.

In [33]:
tls.embed('MattSundquist', '1337')

V. Revisions, embedding, and sharing

We can share it to edit collaboratively, privately or publicly. I can share straight into a folder from the API. My collaborators and I can always add, append, or extend data to that same plot with Python, R, or tbhe GUI.

In [34]:
Image(url = 'http://i.imgur.com/YRyTCQy.png')
Out[34]:

We can also save revisions and versions.

In [35]:
Image (url = 'http://i.imgur.com/ATn7vE4.png')
Out[35]:

You can also export your plot for presentations, emails, infographics, or publications, but link back to the online version so others can access your figure and data.

In [36]:
Image(url = 'http://i.imgur.com/QaIw9p4.png?1')
Out[36]:

You can also stop emailing files around. Have your discussion in context in Plotly. The graph being discussed is here.

In [37]:
Image(url = 'http://i.imgur.com/OqXKs0r.png')
Out[37]:

And displaying in your browser in an iframe is easy. You can copy and paste the snippet below and put it in a blog or website and get a live, interactive graph that lets your readers zoom, toggle, and get text on the hover.

In [38]:
from IPython.display import HTML
In [39]:
i = """<pre style="background:#f1f1f1;color:#000">&lt;iframe src=<span style="color:#c03030">"https://plotly.com/~MattSundquist/1334/650/550"</span> width=<span style="color:#c03030">"650"</span> height=550<span style="color:#c03030">" frameBorder="</span>0<span style="color:#c03030">" seamless="</span>seamless<span style="color:#c03030">" scrolling="</span>no<span style="color:#c03030">">&lt;/iframe>
</span></pre>"""
In [40]:
h = HTML(i); h
Out[40]:
<iframe src="https://plotly.com/~MattSundquist/1334/650/550" width="650" height=550" frameBorder="0" seamless="seamless" scrolling="no"></iframe>

It's also interactive, even when embedded.

In [41]:
HTML('<br><center><iframe class="vine-embed" src="https://vine.co/v/Mvzin6HZzLB/embed/simple" width="600" height="600" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script></center><br>')
Out[41]:


Your profile keeps all your graphs and data together like this https://plotly.com/~jackp/.

In [42]:
Image(url='https://i.imgur.com/gUC4ajR.png')
Out[42]:

Plotly also does content. Check out our's posts on boxplots or histograms.

In [43]:
HTML('<center><iframe class="vine-embed" src="https://vine.co/v/M6JBhdiqPqA/embed/simple" width="600" height="600" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script></center>')
Out[43]:

VI. Streaming Graphs

You can stream data into Plotly. That means you could publish your results to anyone in the world by streaming it through Plotly. You could also send data from multiple sources and languages, and keep your data around to analyze and publish it.

In [44]:
tls.embed('flann321', '9')

Or you can even stream in real-time. Check out a Notebook here or see our Raspberry Pi Instructable showing real-time dissolved oxygen.

In [45]:
tls.embed('streaming-demos','4')

You can stream from basically anywhere.

In [46]:
HTML('<center><iframe src="//instagram.com/p/nJkMMQRyvS/embed/" width="612" height="710" frameborder="0" scrolling="no" allowtransparency="true"></iframe></center>')
Out[46]: