Overview of Plotly for Python

Victoria Gregory

4/1/2016

What is Plotly?

  • plotly.js: online JavaScript graphing library
  • Today I'll talk about its Python client
  • Both plotly.js and the Python library are free and open-source
  • Similar libraries for Julia, R, and Matlab

What can I do with Plotly?

  • Useful for data visualization and fully interactive graphics
  • Standard graphics interface across languages
  • Easily shareable online
  • 20 types of charts, including statistical plots, 3D charts, and maps
  • Complete list here

Just a few examples...


In [13]:
import plotly.tools as tls
tls.embed('https://plot.ly/~AnnaG/1/nfl-defensive-player-size-2013-season/')


Out[13]:

In [3]:
tls.embed('https://plot.ly/~chris/7378/relative-number-of-311-complaints-by-city/')


Out[3]:

In [5]:
tls.embed('https://plot.ly/~empet/2922/a-scoreboard-for-republican-candidates-as-of-august-17-2015-annotated-heatmap/')


Out[5]:

In [6]:
tls.embed('https://plot.ly/~vgregory757/2/_2014-us-city-populations-click-legend-to-toggle-traces/')


Out[6]:

Getting started

  • Easy to install: pip install plotly
  • How to save and view files?
    • Can work offline and save as .html files to open on web browser
    • Jupyter notebook
    • Upload to online account for easy sharing: import statement automatically signs you in

How It Works

  • Graph objects
    • Same structure as native Python dictionaries and lists
    • Defined as new classes
    • Every Plotly plot type has its own graph object, i.e., Scatter, Bar, Histogram
  • All information in a Plotly plot is contained in a Figure object, which contains
    • a Data object: stores data and style options, i.e., setting the line color
    • a Layout object: for aesthetic features outside the plotting area, i.e., setting the title
  • trace: refers to a set of data meant to be plotted as a whole (like an $x$ and $y$ pairing)
  • Interactivity is automatic!

Line/Scatter Plots

The following import statements load the three main modules:


In [1]:
# (*) Tools to communicate with Plotly's server
import plotly.plotly as py

 # (*) Useful Python/Plotly tools 
import plotly.tools as tls

# (*) Graph objects to piece together your Plotly plots
import plotly.graph_objs as go

The following code will make a simple line and scatter plot:


In [2]:
# Create random data with numpy
import numpy as np

N = 100 
random_x = np.linspace(0, 1, N)
random_y0 = np.random.randn(N)+5
random_y1 = np.random.randn(N)
random_y2 = np.random.randn(N)-5

# (1.1) Make a 1st Scatter object
trace0 = go.Scatter(
    x = random_x,
    y = random_y0,
    mode = 'markers',
    name = '$\mu = 5$',
    hoverinfo='x+y'     # choosing what to show on hover
)

In [3]:
# (1.2) Make a 2nd Scatter object
trace1 = go.Scatter(
    x = random_x,
    y = random_y1,
    mode = 'lines+markers',
    name = '$\mu = 0$',
    hoverinfo='x+y'
)
# (1.3) Make a 3rd Scatter object
trace2 = go.Scatter(
    x = random_x,
    y = random_y2,
    mode = 'lines',
    name = '$\mu = -5$',
    hoverinfo='x+y'
)

In [4]:
# (2) Make Data object 
# Data is list-like, must use [ ]
data = go.Data([trace0, trace1, trace2])

# (3) Make Layout object (Layout is dict-like)
layout = go.Layout(title='$\\text{Some scatter objects distributed as } \
\mathcal{N}(\mu,1)$',
        xaxis=dict(title='x-axis label'),
        yaxis=dict(title='y-axis label'),
        showlegend=True)

# (4) Make Figure object (Figure is dict-like)
fig = go.Figure(data=data, layout=layout)

In [5]:
print(fig)  # print the figure object in notebook


{'layout': {'showlegend': True, 'yaxis': {'title': 'y-axis label'}, 'xaxis': {'title': 'x-axis label'}, 'title': '$\\text{Some scatter objects distributed as } \\mathcal{N}(\\mu,1)$'}, 'data': [{'name': '$\\mu = 5$', 'mode': 'markers', 'hoverinfo': 'x+y', 'y': array([ 4.04668017,  6.19854098,  4.62444061,  5.09242471,  3.66649515,
        6.58469017,  5.19130891,  6.6651075 ,  4.69078908,  5.8217442 ,
        6.6377433 ,  3.50985828,  5.91740602,  3.42162452,  5.58354415,
        4.42149207,  5.12235742,  4.68431865,  3.85567028,  6.45240545,
        4.39855931,  4.34472981,  4.29497064,  5.50473226,  5.21625372,
        4.46215315,  5.00053252,  5.90014207,  5.41637191,  5.51115194,
        4.56673328,  6.03843503,  5.56792862,  5.7704772 ,  3.71154776,
        4.7388194 ,  6.08732718,  5.42687078,  6.58736437,  5.67774481,
        5.74155225,  5.91060711,  4.88168997,  5.26141665,  4.70980663,
        4.54812936,  4.90691582,  4.81522669,  4.71825569,  5.55335487,
        4.08928611,  5.63225122,  5.94667951,  4.39225355,  4.74958193,
        3.92407449,  7.07111905,  5.495516  ,  4.09448008,  5.77320071,
        4.64677053,  3.10583353,  4.98918102,  4.48544076,  4.76270418,
        3.07037985,  5.43110144,  4.39505671,  6.45377374,  4.79077288,
        4.52728717,  3.82026289,  4.53460106,  4.49427596,  4.43350851,
        3.52965903,  4.87801779,  3.97288821,  5.3209264 ,  5.17132472,
        5.38980652,  4.67934665,  5.90043308,  4.47941995,  4.04320281,
        4.05764549,  5.87833999,  5.42252719,  4.78779398,  4.80676704,
        5.21730358,  4.3471276 ,  6.28070553,  5.28354741,  2.30351284,
        5.10559463,  4.18524983,  6.19731501,  5.62587121,  4.37582245]), 'x': array([ 0.        ,  0.01010101,  0.02020202,  0.03030303,  0.04040404,
        0.05050505,  0.06060606,  0.07070707,  0.08080808,  0.09090909,
        0.1010101 ,  0.11111111,  0.12121212,  0.13131313,  0.14141414,
        0.15151515,  0.16161616,  0.17171717,  0.18181818,  0.19191919,
        0.2020202 ,  0.21212121,  0.22222222,  0.23232323,  0.24242424,
        0.25252525,  0.26262626,  0.27272727,  0.28282828,  0.29292929,
        0.3030303 ,  0.31313131,  0.32323232,  0.33333333,  0.34343434,
        0.35353535,  0.36363636,  0.37373737,  0.38383838,  0.39393939,
        0.4040404 ,  0.41414141,  0.42424242,  0.43434343,  0.44444444,
        0.45454545,  0.46464646,  0.47474747,  0.48484848,  0.49494949,
        0.50505051,  0.51515152,  0.52525253,  0.53535354,  0.54545455,
        0.55555556,  0.56565657,  0.57575758,  0.58585859,  0.5959596 ,
        0.60606061,  0.61616162,  0.62626263,  0.63636364,  0.64646465,
        0.65656566,  0.66666667,  0.67676768,  0.68686869,  0.6969697 ,
        0.70707071,  0.71717172,  0.72727273,  0.73737374,  0.74747475,
        0.75757576,  0.76767677,  0.77777778,  0.78787879,  0.7979798 ,
        0.80808081,  0.81818182,  0.82828283,  0.83838384,  0.84848485,
        0.85858586,  0.86868687,  0.87878788,  0.88888889,  0.8989899 ,
        0.90909091,  0.91919192,  0.92929293,  0.93939394,  0.94949495,
        0.95959596,  0.96969697,  0.97979798,  0.98989899,  1.        ]), 'type': 'scatter'}, {'name': '$\\mu = 0$', 'mode': 'lines+markers', 'hoverinfo': 'x+y', 'y': array([-0.34691493,  2.17938364,  0.51809962, -0.5959291 ,  0.23412758,
       -2.07896695,  1.40091551,  0.24549119, -0.56185707, -0.34058195,
       -0.61737475,  0.45612955, -0.52261175, -0.48896567, -1.04546019,
        0.26031148,  0.8714819 ,  0.66574976, -0.01393808,  1.33190518,
       -0.93344882,  1.47167414, -0.44745963, -0.34761853, -0.8235109 ,
        1.23946937, -0.57356471,  0.12733162,  1.18614807,  0.84700632,
        0.24209963,  1.23406421,  0.16085798, -0.21386201, -0.4344829 ,
        0.28582313,  0.96303331,  0.64243359,  0.80443922, -0.73621594,
       -0.63861189,  0.19156248,  0.13184313,  0.00497728,  0.99412137,
       -0.92522068,  0.42878841, -2.02951441, -1.28557997, -2.74433002,
       -2.60336845,  0.20100076,  0.18442098, -0.04819198,  1.55876483,
        0.2357085 ,  0.43286067, -0.07853408, -1.10796824,  0.73222129,
       -0.18911711, -0.46665695,  0.22134336, -0.34721588, -0.31997409,
        0.22769666, -0.12279111,  0.39043892, -0.40059278, -1.47428438,
       -0.25698252, -1.15126189,  0.98357977,  0.84970328, -1.98720117,
        1.11064262,  1.44028829, -1.63808531,  0.98075371, -0.58109039,
       -0.38653214, -0.82579092, -0.08508776,  0.15513385,  0.1818524 ,
       -0.92253578,  2.0418283 , -1.02322954,  3.76191565, -0.89168133,
        0.28982609,  0.12799418,  1.01013012, -0.24028744, -0.5506389 ,
       -0.21764378, -1.42432799,  0.51234302,  0.12061286,  1.94768532]), 'x': array([ 0.        ,  0.01010101,  0.02020202,  0.03030303,  0.04040404,
        0.05050505,  0.06060606,  0.07070707,  0.08080808,  0.09090909,
        0.1010101 ,  0.11111111,  0.12121212,  0.13131313,  0.14141414,
        0.15151515,  0.16161616,  0.17171717,  0.18181818,  0.19191919,
        0.2020202 ,  0.21212121,  0.22222222,  0.23232323,  0.24242424,
        0.25252525,  0.26262626,  0.27272727,  0.28282828,  0.29292929,
        0.3030303 ,  0.31313131,  0.32323232,  0.33333333,  0.34343434,
        0.35353535,  0.36363636,  0.37373737,  0.38383838,  0.39393939,
        0.4040404 ,  0.41414141,  0.42424242,  0.43434343,  0.44444444,
        0.45454545,  0.46464646,  0.47474747,  0.48484848,  0.49494949,
        0.50505051,  0.51515152,  0.52525253,  0.53535354,  0.54545455,
        0.55555556,  0.56565657,  0.57575758,  0.58585859,  0.5959596 ,
        0.60606061,  0.61616162,  0.62626263,  0.63636364,  0.64646465,
        0.65656566,  0.66666667,  0.67676768,  0.68686869,  0.6969697 ,
        0.70707071,  0.71717172,  0.72727273,  0.73737374,  0.74747475,
        0.75757576,  0.76767677,  0.77777778,  0.78787879,  0.7979798 ,
        0.80808081,  0.81818182,  0.82828283,  0.83838384,  0.84848485,
        0.85858586,  0.86868687,  0.87878788,  0.88888889,  0.8989899 ,
        0.90909091,  0.91919192,  0.92929293,  0.93939394,  0.94949495,
        0.95959596,  0.96969697,  0.97979798,  0.98989899,  1.        ]), 'type': 'scatter'}, {'name': '$\\mu = -5$', 'mode': 'lines', 'hoverinfo': 'x+y', 'y': array([-4.48987402, -5.00299715, -5.27569342, -3.8223728 , -3.6502064 ,
       -4.93187342, -3.5115968 , -7.6986876 , -3.76826013, -6.4241302 ,
       -4.73376471, -5.04163874, -5.77634254, -6.26209807, -4.60243579,
       -4.67358739, -5.14992072, -5.29748225, -5.06602165, -6.13815511,
       -5.564722  , -5.63855557, -4.82780904, -6.33164629, -5.56346489,
       -5.70394686, -4.330434  , -5.49693236, -4.84009953, -4.6317476 ,
       -4.010567  , -7.48336095, -6.09522473, -4.89513925, -4.83467357,
       -4.70691006, -6.33809177, -6.29332726, -2.96358237, -4.7275947 ,
       -5.83294186, -5.9606109 , -5.58472397, -5.62344515, -4.02465416,
       -3.02183737, -4.86414021, -4.39816038, -6.61453443, -5.61632089,
       -5.61164201, -3.60435107, -4.93173037, -5.2246923 , -4.56053351,
       -5.71917183, -5.71984894, -5.60812793, -5.16043173, -4.15756347,
       -3.7194692 , -5.52792439, -3.62796425, -4.86906244, -3.40373272,
       -5.84820953, -3.46684876, -5.16100917, -5.74868657, -5.0236031 ,
       -3.56692692, -2.02221892, -6.80212881, -3.8346147 , -5.91834124,
       -2.31426304, -6.77714362, -4.95939023, -5.32436323, -4.86277363,
       -5.28515788, -4.56678228, -3.81648371, -4.407105  , -4.70197081,
       -6.01753656, -6.82434989, -5.93431004, -4.24573797, -4.33361792,
       -5.97240983, -4.21877573, -4.80431133, -4.50803704, -4.76269954,
       -4.79829357, -4.33052356, -4.4148409 , -5.98019236, -3.94674547]), 'x': array([ 0.        ,  0.01010101,  0.02020202,  0.03030303,  0.04040404,
        0.05050505,  0.06060606,  0.07070707,  0.08080808,  0.09090909,
        0.1010101 ,  0.11111111,  0.12121212,  0.13131313,  0.14141414,
        0.15151515,  0.16161616,  0.17171717,  0.18181818,  0.19191919,
        0.2020202 ,  0.21212121,  0.22222222,  0.23232323,  0.24242424,
        0.25252525,  0.26262626,  0.27272727,  0.28282828,  0.29292929,
        0.3030303 ,  0.31313131,  0.32323232,  0.33333333,  0.34343434,
        0.35353535,  0.36363636,  0.37373737,  0.38383838,  0.39393939,
        0.4040404 ,  0.41414141,  0.42424242,  0.43434343,  0.44444444,
        0.45454545,  0.46464646,  0.47474747,  0.48484848,  0.49494949,
        0.50505051,  0.51515152,  0.52525253,  0.53535354,  0.54545455,
        0.55555556,  0.56565657,  0.57575758,  0.58585859,  0.5959596 ,
        0.60606061,  0.61616162,  0.62626263,  0.63636364,  0.64646465,
        0.65656566,  0.66666667,  0.67676768,  0.68686869,  0.6969697 ,
        0.70707071,  0.71717172,  0.72727273,  0.73737374,  0.74747475,
        0.75757576,  0.76767677,  0.77777778,  0.78787879,  0.7979798 ,
        0.80808081,  0.81818182,  0.82828283,  0.83838384,  0.84848485,
        0.85858586,  0.86868687,  0.87878788,  0.88888889,  0.8989899 ,
        0.90909091,  0.91919192,  0.92929293,  0.93939394,  0.94949495,
        0.95959596,  0.96969697,  0.97979798,  0.98989899,  1.        ]), 'type': 'scatter'}]}

Figure objects store data like a Python dictionary.


In [6]:
# (5) Send Figure object to Plotly and show plot in notebook
py.iplot(fig, filename='scatter-mode')


Out[6]:

Can save a static image as well:


In [59]:
py.image.save_as(fig, filename='scatter-mode.png')

Histograms


In [ ]:
# (1) Generate some random numbers
x0 = np.random.randn(500)
x1 = np.random.randn(500)+1

# (2.1) Create the first Histogram object
trace1 = go.Histogram(
    x=x0,
    histnorm='count',
    name='control',
    autobinx=False,
    xbins=dict(
        start=-3.2,
        end=2.8,
        size=0.2
    ),
    marker=dict(
        color='fuchsia',
        line=dict(
            color='grey',
            width=0
        )
    ),
    opacity=0.75
)

In [7]:
# (2.2) Create the second Histogram object
trace2 = go.Histogram(
    x=x1,
    name='experimental',
    autobinx=False,
    xbins=dict(
        start=-1.8,
        end=4.2,
        size=0.2
    ),
    marker=dict(
        color='rgb(255, 217, 102)'
    ),
    opacity=0.75
)

In [8]:
# (3) Create Data object
data = [trace1, trace2]

# (4) Create Layout object
layout = go.Layout(
    title='Sampled Results',
    xaxis=dict(
        title='Value'
    ),
    yaxis=dict(
        title='Count'
    ),
    barmode='overlay',
    bargap=0.25,
    bargroupgap=0.3,
    showlegend=True
)
fig = go.Figure(data=data, layout=layout)

In [9]:
# (5) Send Figure object to Plotly and show plot in notebook
py.iplot(fig, filename='histogram_example')


Out[9]:

Distplots

Similar to seaborn.distplot. Plot a histogram, kernel density or normal curve, and a rug plot all together.


In [ ]:
from plotly.tools import FigureFactory as FF

# Add histogram data
x1 = np.random.randn(200)-2  
x2 = np.random.randn(200)  
x3 = np.random.randn(200)+2  
x4 = np.random.randn(200)+4  

# Group data together
hist_data = [x1, x2, x3, x4]

group_labels = ['Group 1', 'Group 2', 'Group 3', 'Group 4']

# Create distplot with custom bin_size
fig = FF.create_distplot(hist_data, group_labels, bin_size=.2)

In [63]:
# Plot!
py.iplot(fig, filename='Distplot with Multiple Datasets', \
         validate=False)


Out[63]:

2D Contour Plot


In [3]:
x = np.random.randn(1000)
y = np.random.randn(1000)
py.iplot([go.Histogram2dContour(x=x, y=y, \
        contours=go.Contours(coloring='fill')), \
       go.Scatter(x=x, y=y, mode='markers', \
        marker=go.Marker(color='white', size=3, opacity=0.3))])


Out[3]:

3D Surface Plot

Plot the function: $f(x,y) = A \cos(\pi x y) e^{-(x^2+y^2)/2}$


In [5]:
# Define the function to be plotted
def fxy(x, y):
    A = 1  # choose a maximum amplitude 
    return A*(np.cos(np.pi*x*y))**2 * np.exp(-(x**2+y**2)/2.)

# Choose length of square domain, make row and column vectors
L = 4
x = y = np.arange(-L/2., L/2., 0.1)  # use a mesh spacing of 0.1
yt = y[:, np.newaxis]  # (!) make column vector

# Get surface coordinates!
z = fxy(x, yt)

In [6]:
trace1 = go.Surface(
    z=z,  # link the fxy 2d numpy array
    x=x,  # link 1d numpy array of x coords
    y=y   # link 1d numpy array of y coords
)

# Package the trace dictionary into a data object
data = go.Data([trace1])

# Dictionary of style options for all axes
axis = dict(
    showbackground=True, # (!) show axis background
    backgroundcolor="rgb(204, 204, 204)", # set background color to grey
    gridcolor="rgb(255, 255, 255)",       # set grid line color
    zerolinecolor="rgb(255, 255, 255)",   # set zero grid line color
)

# Make a layout object
layout = go.Layout(
    title='$f(x,y) = A \cos(\pi x y) e^{-(x^2+y^2)/2}$', # set plot title
    scene=go.Scene(  # (!) axes are part of a 'scene' in 3d plots
        xaxis=go.XAxis(axis), # set x-axis style
        yaxis=go.YAxis(axis), # set y-axis style
        zaxis=go.ZAxis(axis)  # set z-axis style
    )
)

In [8]:
# Make a figure object
fig = go.Figure(data=data, layout=layout)

# (@) Send to Plotly and show in notebook
py.iplot(fig, filename='surface')


Out[8]:

Matplotlib Conversion


In [ ]:
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab

n = 50
x, y, z, s, ew = np.random.rand(5, n)
c, ec = np.random.rand(2, n, 4)
area_scale, width_scale = 500, 5

fig, ax = plt.subplots()
sc = ax.scatter(x, y, c=c,
                s=np.square(s)*area_scale,
                edgecolor=ec,
                linewidth=ew*width_scale)
ax.grid()

In [6]:
py.iplot_mpl(fig)


Out[6]:

Pros/Cons

Pros:

  • Beautiful, interactive plots
  • Great documentation: easy to figure out how to customize
  • Easily shareable and modifiable by collaborators using the online GUI
  • Can convert matplotlib graphs

Cons:

  • Static export only supports .png or .jpg. No .eps for free accounts
  • Although not required for use, your data is hosted on their cloud
  • Limited number of private figures for free accounts
  • Limited usage opportunities for economists

Extra Resources