21 Interactive Plots from matplotlib, ggplot for Python,
prettyplotlib, Stack Overflow, and seaborn

Plotly is collaborative, makes beautiful interactive graphs with a URL for you, and stores your data and graphs together. This NB shows how to use Plotly to share plots from some awesome Python plotting libraries. The matplotlylib project is a collaboration with mpld3 and Jake Vanderplas. We've put together a User Guide that outlines the full extent of Plotly's APIs.

For best results, you can copy and paste this Notebook and key. Run $ pip install plotly inside a terminal then start up a Notebook. We'll also be using ggplot, seaborn, and prettyplotlib, which you can also all install form pip. Let's get started.

In [1]:
%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 public key and username or sign up for an account on Plotly. Plotly is free for public use, you own your data, and you control the privacy.

In [2]:
import plotly.plotly as py
import plotly.tools as tls
from plotly.graph_objs import *
py.sign_in("IPython.Demo", "1fw3zw2o13")
In [3]:
# tls.set_credentials_file("IPython.Demo", "1fw3zw2o13")
# tls.get_credentials_file()

You'll want to have version 1.0.0. If not, run $ pip install plotly --upgrade in a terminal. Check out our User Guide for more details on where to get your key. Problems or questions? Email [email protected] or find us on Twitter.

In [4]:
import plotly
plotly.__version__
Out[4]:
'1.0.0'

For matplotlib experts, you'll recognize these graphs from the matplotlib gallery.

In addition to matplotlib and Plotly's own Python API, You can also use Plotly's other APIs for MATLAB, R, Perl, Julia, and REST to write to graphs. That means you and I could edit the same graph with any language. We can even edit the graph and data from the GUI, so technical and non-technical teams can work together. And all the graphs go to your profile, like this: https://plot.ly/~IPython.Demo.

You control the privacy by setting world_readable to False or True, and can control your sharing.

Let's get started with this damped oscillation graph.

In [5]:
fig1 = plt.figure()
# Make a legend for specific lines.
import matplotlib.pyplot as plt
import numpy as np


t1 = np.arange(0.0, 2.0, 0.1)
t2 = np.arange(0.0, 2.0, 0.01)

# note that plot returns a list of lines.  The "l1, = plot" usage
# extracts the first element of the list into l1 using tuple
# unpacking.  So l1 is a Line2D instance, not a sequence of lines
l1, = plt.plot(t2, np.exp(-t2))
l2, l3 = plt.plot(t2, np.sin(2 * np.pi * t2), '--go', t1, np.log(1 + t1), '.')
l4, = plt.plot(t2, np.exp(-t2) * np.sin(2 * np.pi * t2), 'rs-.')

plt.xlabel('time')
plt.ylabel('volts')
plt.title('Damped oscillation')

plt.show()

Now, to convert it to a Plotly figure, this is all it takes:

In [6]:
py.iplot_mpl(fig1)

You can hover, zoom, and pan on the figure. You can also strip out the matplotlib styling, and use Plotly's default styling.

In [7]:
fig = tls.mpl_to_plotly(fig1)
fig['layout'].update(showlegend=True)
fig.strip_style()
py.iplot(fig)

Next up, an example from pylab.

In [8]:
fig2 = plt.figure()

from pylab import *

def f(t):
    'a damped exponential'
    s1 = cos(2*pi*t)
    e1 = exp(-t)
    return multiply(s1,e1)

t1 = arange(0.0, 5.0, .2)


l = plot(t1, f(t1), 'ro')
setp(l, 'markersize', 30)
setp(l, 'markerfacecolor', 'b')

py.iplot_mpl(fig2)

Here's where this gets special. You can get the data from any Plotly graph. That means you can re-plot the graph or part of it, or use your favorite Python tools to wrangle and analyze your data. Check out our getting started guide for a full background on these features.

In [9]:
tls.mpl_to_plotly(fig2).get_data()
Out[9]:
[{'name': '_line0',
  'x': [0.0,
   0.20000000000000001,
   0.40000000000000002,
   0.60000000000000009,
   0.80000000000000004,
   1.0,
   1.2000000000000002,
   1.4000000000000001,
   1.6000000000000001,
   1.8,
   2.0,
   2.2000000000000002,
   2.4000000000000004,
   2.6000000000000001,
   2.8000000000000003,
   3.0,
   3.2000000000000002,
   3.4000000000000004,
   3.6000000000000001,
   3.8000000000000003,
   4.0,
   4.2000000000000002,
   4.4000000000000004,
   4.6000000000000005,
   4.8000000000000007],
  'y': [1.0,
   0.25300171651849518,
   -0.54230030891302927,
   -0.44399794031078654,
   0.13885028597711233,
   0.36787944117144233,
   0.09307413008823949,
   -0.19950113459002566,
   -0.16333771416280363,
   0.051080165611754998,
   0.1353352832366127,
   0.034240058964379601,
   -0.073392365906047419,
   -0.060088587008433003,
   0.018791342780197139,
   0.049787068367863944,
   0.012596213757493282,
   -0.026999542555766767,
   -0.022105355809443925,
   0.0069129486808399343,
   0.018315638888734179,
   0.0046338880779826647,
   -0.0099325766273000524,
   -0.0081321059420741033,
   0.0025431316975542792]}]

Or you can get the figure makeup. Here, we're using 'IPython.Demo', which is the username and '3357' which is the figure number. You can use this command on Plotly graphs to interact with them from the console. You can access graphs via a URL. For example, for this plot, it's:

https://plot.ly/~IPython.Demo/3357/

In [10]:
pylab = py.get_figure('IPython.Demo', '3357')
In [11]:
#print figure
print pylab.to_string()
Figure(
    data=Data([
        Scatter(
            x=[0.0, 0.2, 0.4, 0.6000000000000001, 0.8, 1.0, 1.2000000000000...],
            y=[1.0, 0.2530017165184952, -0.5423003089130293, -0.44399794031...],
            name='_line0',
            mode='markers',
            marker=Marker(
                symbol='dot',
                line=Line(
                    color='#000000',
                    width=0.5
                ),
                size=30,
                color='#0000FF',
                opacity=1
            )
        )
    ]),
    layout=Layout(
        xaxis=XAxis(
            domain=[0.0, 1.0],
            range=[0.0, 5.0],
            showline=True,
            ticks='inside',
            showgrid=False,
            zeroline=False,
            anchor='y',
            mirror=True
        ),
        yaxis=YAxis(
            domain=[0.0, 1.0],
            range=[-0.6000000000000001, 1.2],
            showline=True,
            ticks='inside',
            showgrid=False,
            zeroline=False,
            anchor='x',
            mirror=True
        ),
        hovermode='closest',
        showlegend=False
    )
)

Now let's suppose we wanted to add a fit to the graph (see our fits post to learn more), and re-style it a bit. We can go into the web app, fork a copy, and edit the image in our GUI. No coding required.

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

We also keep the data and graph together. You can analyze it, share it, or add to other plots. You can append data to your plots, copy and paste, import, or upload data. Take-away: a Python user could make plots with an Excel user, ggplot2 Ploty package, and MATLAB user. That's collaboration.

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

I can now call that graph into the NB. I can keep the styling, re-use that styling on future graphs, and save styles from other graphs. And if I want to see the data for the fit or access the figure styling, I can run the same commands, but on the updated figure and data for this graph. I don't need to re-code it, and I can save and share this version.

In [14]:
tls.embed('MattSundquist', '1307')

Plotly graphs are always interactive, and you can even stream data to the browser. You can also embed them in the browser with an iframe snippet.

In [15]:
from IPython.display import HTML
In [16]:
s = """<pre style="background:#f1f1f1;color:#000">&lt;iframe src=<span style="color:#c03030">"https://plot.ly/~etpinard/176/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 [17]:
h = HTML(s); h
Out[17]:
<iframe src="https://plot.ly/~etpinard/176/650/550" width="650" height=550" frameBorder="0" seamless="seamless" scrolling="no"></iframe>

Where it remains interactive. That means your for-free defaults are: D3 graphs, drawn with JavaScript, and shared data. Here's how it looks in the Washington Post.

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

It's fun to zoom. Then double-click to re-size.

In [19]:
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[19]:


Plots can be collaboratively edited and shared with others.

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

So you can keep all your plots for your project, team, or personal work in one plce, you get a profile, like this: https://plot.ly/~jackp/.

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

You can also plot with Plotly with pandas, NumPy, datetime, and more of your favorite Python tools. We've already imported numpy and matplotlib; here we've kept them in so you can simply copy and paste these examples into your own NB.

In [22]:
fig3 = plt.figure()

import numpy as np
import matplotlib.pyplot as plt

# make a little extra space between the subplots
plt.subplots_adjust(wspace=0.5)

dt = 0.01
t = np.arange(0, 30, dt)
nse1 = np.random.randn(len(t))                 # white noise 1
nse2 = np.random.randn(len(t))                 # white noise 2
r = np.exp(-t/0.05)

cnse1 = np.convolve(nse1, r, mode='same')*dt   # colored noise 1
cnse2 = np.convolve(nse2, r, mode='same')*dt   # colored noise 2

# two signals with a coherent part and a random part
s1 = 0.01*np.sin(2*np.pi*10*t) + cnse1
s2 = 0.01*np.sin(2*np.pi*10*t) + cnse2

plt.subplot(211)
plt.plot(t, s1, 'b-', t, s2, 'g-')
plt.xlim(0,5)
plt.xlabel('time')
plt.ylabel('s1 and s2')
plt.grid(True)

plt.subplot(212)
cxy, f = plt.csd(s1, s2, 256, 1./dt)
plt.ylabel('CSD (db)')

py.iplot_mpl(fig3)

Another subplotting example using Plotly's defaults.

In [23]:
fig4 = plt.figure()

from pylab import figure, show
from numpy import arange, sin, pi

t = arange(0.0, 1.0, 0.01)

fig = figure(1)

ax1 = fig.add_subplot(211)
ax1.plot(t, sin(2*pi*t))
ax1.grid(True)
ax1.set_ylim( (-2,2) )
ax1.set_ylabel('1 Hz')
ax1.set_title('A sine wave or two')

for label in ax1.get_xticklabels():
    label.set_color('r')


ax2 = fig.add_subplot(212)
ax2.plot(t, sin(2*2*pi*t))
ax2.grid(True)
ax2.set_ylim( (-2,2) )
l = ax2.set_xlabel('Hi mom')
l.set_color('g')
l.set_fontsize('large')

py.iplot_mpl(fig4, strip_style = True)

From the gallery here we're shwoing Anscombe's quartet. You might also like Plotly's blog post on the subject.

In [24]:
fig5 = plt.figure()

from __future__ import print_function
"""
Edward Tufte uses this example from Anscombe to show 4 datasets of x
and y that have the same mean, standard deviation, and regression
line, but which are qualitatively different.

matplotlib fun for a rainy day
"""

from pylab import *

x =  array([10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5])
y1 = array([8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68])
y2 = array([9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13, 7.26, 4.74])
y3 = array([7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39, 8.15, 6.42, 5.73])
x4 = array([8,8,8,8,8,8,8,19,8,8,8])
y4 = array([6.58,5.76,7.71,8.84,8.47,7.04,5.25,12.50,5.56,7.91,6.89])

def fit(x):
    return 3+0.5*x



xfit = array( [amin(x), amax(x) ] )

subplot(221)
plot(x,y1,'ks', xfit, fit(xfit), 'r-', lw=2)
axis([2,20,2,14])
setp(gca(), xticklabels=[], yticks=(4,8,12), xticks=(0,10,20))
text(3,12, 'I', fontsize=20)

subplot(222)
plot(x,y2,'ks', xfit, fit(xfit), 'r-', lw=2)
axis([2,20,2,14])
setp(gca(), xticklabels=[], yticks=(4,8,12), yticklabels=[], xticks=(0,10,20))
text(3,12, 'II', fontsize=20)

subplot(223)
plot(x,y3,'ks', xfit, fit(xfit), 'r-', lw=2)
axis([2,20,2,14])
text(3,12, 'III', fontsize=20)
setp(gca(), yticks=(4,8,12), xticks=(0,10,20))

subplot(224)

xfit = array([amin(x4),amax(x4)])
plot(x4,y4,'ks', xfit, fit(xfit), 'r-', lw=2)
axis([2,20,2,14])
setp(gca(), yticklabels=[], yticks=(4,8,12), xticks=(0,10,20))
text(3,12, 'IV', fontsize=20)

#verify the stats
pairs = (x,y1), (x,y2), (x,y3), (x4,y4)
for x,y in pairs:
    print ('mean=%1.2f, std=%1.2f, r=%1.2f'%(mean(y), std(y), corrcoef(x,y)[0][1]))

py.iplot_mpl(fig5, strip_style = True)
mean=7.50, std=1.94, r=0.82
mean=7.50, std=1.94, r=0.82
mean=7.50, std=1.94, r=0.82
mean=7.50, std=1.94, r=0.82

And a final histogram from the matplotlib gallery.

In [25]:
fig6 = plt.figure()

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


# example data
mu = 100 # mean of distribution
sigma = 15 # standard deviation of distribution
x = mu + sigma * np.random.randn(10000)

num_bins = 50
# the histogram of the data
n, bins, patches = plt.hist(x, num_bins, normed=1, facecolor='green', alpha=0.5)
# add a 'best fit' line
y = mlab.normpdf(bins, mu, sigma)
plt.plot(bins, y, 'r--')
plt.xlabel('Smarts')
plt.ylabel('Probability')

# Tweak spacing to prevent clipping of ylabel
plt.subplots_adjust(left=0.15)

py.iplot_mpl(fig6, strip_style = True)

Want to see more matplotlylib graphs? Head over to our API and copy and paste away.

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

II. ggplot for Python

An exciting package by Greg Lamp and the team at ┼Ěhat is ggplot for Python. You can draw figures with ggplot's wonderful syntax and share them with Plotly. You'll want to run $ pip install ggplot to get started.

In [27]:
from ggplot import *

We'll start out with a plot from the diamonds dataset.

In [28]:
a = ggplot(aes(x='price'), data=diamonds) + geom_histogram() + facet_wrap("cut") 

Then share it to Plotly.

In [52]:
fig = a.draw() 
py.iplot_mpl(fig, strip_style=True)

Line charts can be interactive (drag your mouse along the line to see the data on the hover).

In [30]:
b = ggplot(aes(x='date', y='beef'), data=meat) + \
    geom_line() 
In [31]:
fig = b.draw() 
py.iplot_mpl(fig)

Histograms are also fun to hover over to get the exact data.

In [32]:
c = ggplot(aes(x='price'), data=diamonds) + geom_histogram() + ggtitle('My Diamond Histogram')
In [33]:
fig = c.draw() 
py.iplot_mpl(fig, strip_style=True)
In [34]:
d = ggplot(aes(x='x', y='y', color='z'), data=diamonds.head(1000)) +\
    geom_point() 
In [35]:
fig = d.draw() 
py.iplot_mpl(fig, strip_style=True)

You can also use more advanced plotting types in collaboration with pandas. You can add a geom.

In [36]:
import pandas as pd
In [37]:
random_walk1 = pd.DataFrame({
  "x": np.arange(100),
  "y": np.cumsum(np.random.choice([-1, 1], 100))
})
random_walk2 = pd.DataFrame({
  "x": np.arange(100),
  "y": np.cumsum(np.random.choice([-1, 1], 100))
})
e = ggplot(aes(x='x', y='y'), data=random_walk1) + \
    geom_step() + \
    geom_step(aes(x='x', y='y'), data=random_walk2)
In [38]:
fig = e.draw() 
py.iplot_mpl(fig, strip_style=True)

III. Prettyplotlib graphs in Plotly

The lovely gallery of examples from prettyplotlib, a matplotlib enhnacing library by Olga Botvinnik, is a fun one to make interactive. Here's a scatter; let us know if you make others. You'll note that not all elements of the styling come through. Head over to the homepage for documentation.

In [39]:
fig12 = plt.figure()

import prettyplotlib as ppl

# Set the random seed for consistency
np.random.seed(12)

# Show the whole color range
for i in range(8):
    x = np.random.normal(loc=i, size=800)
    y = np.random.normal(loc=i, size=800)
    ax = ppl.scatter(x, y, label=str(i))
    
ppl.legend(ax)
ax.set_title('prettyplotlib `scatter`')
ax.legend().set_visible(False)

py.iplot_mpl(fig12)

And another prettyplotlib example.

In [40]:
fig13 = plt.figure()

import prettyplotlib as ppl

# Set the random seed for consistency
np.random.seed(12)

# Show the whole color range
for i in range(8):
    y = np.random.normal(size=1000).cumsum()
    x = np.arange(1000)

    # Specify both x and y
    ppl.plot(x, y, label=str(i), linewidth=0.75)
        
py.iplot_mpl(fig13)

IV. Plotting with seaborn

Another library we really dig is seaborn, a library to maximize aesthetics of matplotlib plots. It's by by Michael Waskom. You'll need to install it with $ pip install seaborn, and may need to import six, which you can do from pip. The styling isn't yet translated to Plotly, so we'll go to Plotly's default settings.

In [41]:
import seaborn as sns
from matplotlylib import fig_to_plotly
In [42]:
def sinplot(flip=1):
    x = np.linspace(0, 14, 100)
    for i in range(1, 7):
        plt.plot(x, np.sin(x + i * .5) * (7 - i) * flip)
In [43]:
fig14 = plt.figure()

sns.set_style("dark")
sinplot()

py.iplot_mpl(fig14, strip_style = True)

You can also run subplots like this.

In [44]:
fig15 = plt.figure()

with sns.axes_style("darkgrid"):
    plt.subplot(211)
    sinplot()
plt.subplot(212)
sinplot(-1)

py.iplot_mpl(fig15, strip_style = True)

And a final example, combining plot types.

In [45]:
import numpy as np
from numpy.random import randn
import pandas as pd
from scipy import stats
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
In [46]:
fig16 = plt.figure()

sns.set_palette("hls")
mpl.rc("figure", figsize=(8, 4))
data = randn(200)
sns.distplot(data);

py.iplot_mpl(fig16, strip_style = True)

V. Stack Overflow Answers

We love Stack Overflow, so wanted answer a few questions from there, in Plotly. If you want to plot data you already have as a histogram and make it interactive, try this one out.

In [47]:
fig17 = plt.figure()

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
hist, bins = np.histogram(x, bins=50)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
plt.bar(center, hist, align='center', width=width)

py.iplot_mpl(fig17, strip_style = True)

Here is how to create a density plot like you might in R, but in matplotlib.

In [48]:
fig18 = plt.figure()

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = gaussian_kde(data)
xs = np.linspace(0,8,200)
density.covariance_factor = lambda : .25
density._compute_covariance()
plt.plot(xs,density(xs))

py.iplot_mpl(fig18, strip_style = True)

Drawing a simple example of different lines for different plots looks like this...

In [49]:
fig19 = plt.figure()

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

py.iplot_mpl(fig19, strip_style = True)

...and can get more exciting like this.

In [50]:
fig20 = plt.figure()

import matplotlib.pyplot as plt
import numpy as np

num_plots = 10

# Have a look at the colormaps here and decide which one you'd like:
# http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html
colormap = plt.cm.gist_ncar
plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, num_plots)])

# Plot several different functions...
x = np.arange(10)
labels = []
for i in range(1, num_plots + 1):
    plt.plot(x, i * x + 5 * i)
    labels.append(r'$y = %ix + %i$' % (i, 5*i))

py.iplot_mpl(fig20, strip_style = True)

Plotly also lets you draw variables as subscripts in math mode.

In [51]:
fig21 = 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)")        

py.iplot_mpl(fig21, strip_style = True)
In [1]:
# CSS styling within IPython notebook
from IPython.core.display import HTML
import urllib2
def css_styling():
    url = 'https://raw.githubusercontent.com/plotly/python-user-guide/master/custom.css'
    styles = urllib2.urlopen(url).read()
    return HTML(styles)

css_styling()
Out[1]: