import plotly
plotly.__version__
'1.0.29'
import plotly.plotly as py #
import plotly.tools as tls #
If you are not familiar with credentials files, refer to the User Guide's homepage.
sdfds
from plotly.graph_objs import Data, Layout, Figure
from plotly.graph_objs import Heatmap, Contour
from plotly.graph_objs import XAxis, YAxis, ColorBar, Margin
from plotly.graph_objs import Font, Contours
import numpy as np #
import pandas as pd #
import urllib2 #
import datetime #
import locale
locale.setlocale(locale.LC_ALL, 'fr_CA.utf8')
'fr_CA.utf8'
#tls.embed()
#tls.embed()
#tls.embed()
#tls.embed()
#
url_csv = 'http://donnees.ville.montreal.qc.ca/storage/f/\
2014-01-20T20%3A48%3A50.296Z/2013.csv'
fichier_csv = urllib2.urlopen(url_csv) #
df = pd.read_csv(fichier_csv) #
df.head() # affiche les 5 premières lignes du tableau
Date | Unnamed: 1 | Berri1 | CSC | Mais1 | Mais2 | Parc | PierDup | Rachel1 | Totem_Laurier | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 01/01/2013 | 00:00 | 0 | 0 | 1 | 0 | 6 | 0 | 1 | 0 |
1 | 02/01/2013 | 00:00 | 69 | 0 | 13 | 0 | 18 | 0 | 2 | 0 |
2 | 03/01/2013 | 00:00 | 69 | 2 | 21 | 6 | 22 | 1 | 0 | 0 |
3 | 04/01/2013 | 00:00 | 80 | 0 | 22 | 4 | 16 | 0 | 125 | 0 |
4 | 05/01/2013 | 00:00 | 52 | 4 | 19 | 3 | 12 | 0 | 97 | 0 |
5 rows × 10 columns
df.tail() # affiche les 5 premières lignes du tableau
Date | Unnamed: 1 | Berri1 | CSC | Mais1 | Mais2 | Parc | PierDup | Rachel1 | Totem_Laurier | |
---|---|---|---|---|---|---|---|---|---|---|
256 | 14/09/2013 | 00:00 | 2488 | 1494 | 1706 | 2911 | 979 | 1075 | 3277 | 2456 |
257 | 15/09/2013 | 00:00 | 2243 | 1749 | 1417 | 2933 | 1804 | 1459 | 3623 | 2527 |
258 | 16/09/2013 | 00:00 | 4206 | 2466 | 2799 | 5485 | 3272 | 855 | 4307 | 3012 |
259 | 17/09/2013 | 00:00 | 5506 | 3153 | 3563 | 6626 | 3882 | 1485 | 5332 | 3745 |
260 | 18/09/2013 | 00:00 | 1564 | 3330 | 1154 | 1803 | 4074 | 1759 | 1511 | 3921 |
5 rows × 10 columns
.. en faite,
df.shape
(261, 10)
# Sites' full names
sites = ['Berri/<br>de Maisonneuve',
'Côte-Ste-Catherine<br>(parc Beaubien)',
'de Maisonneuve/<br>Berri',
'de Maisonneuve/<br>Peel',
'du Parc/<br>Duluth',
'Pierre-Dupuy<br>(Habitat 67)',
'Rachel/<br>Marquette',
'Laurier<br>(métro)']
Where we used the <br>
HTML tags to break line inside some of the sites' names for better-looking tick labels.
Moreover, the data set does not include every day of the year 2013:
To have a more homogenous data set, trim the data frame to have 8 full months of data, from January 1st to August 31st:
First, check the total number of cyclists that passed by all the counter sites from January 1st to August 31th.
To do so, we could plot the data as a time series where the x-axis represents all the dates in the sample and the y-axis the total number of cyclists that passed by all counter sites. But, here with a sample of 243 dates, this would make a pretty big or not-that-precise plot.
Instead, let's plot the data using a Plotly heatmap where the color scheme represents the total number of cyclists, the x-axis the month (January to August) and the y-axis the day of the month (1 to 31). So, start by importing the heatmap graph object:
So, let's start with summing the daily bike traffic count across all 8 sites in the January-to-August dataframe:
# Somme de toutes les rangées du tableau,
z = np.array(df.sum(axis=1).tolist())
# The resulting array is 1d, 1 entry per date from Jan to Aug
z.shape
(261,)
Next, we need to convert the 1D array to a 2D array where the columns correspond to the months (January to August) and the rows to the days of the month (1 to 31).
The following code cell is a bit technical; hence, readers only interesting in heatmap plot styling ideas are invited to skip it.
# Define a convertion function
def dates_a_jourXmois(X, zz):
dates = df_in['Date'].tolist() # make list of dates in dataframe
# (1.1) List of months for all item in dates
months = np.array([datetime.datetime.strptime(date,'%d/%m/%Y').strftime('%B')
for date in dates])
# (1.2) Find indices of first day of the months
_,ind_tmp = np.unique(months,return_index=True) # -> array([90,212,31,0, ...])
the_months_ind = np.sort(ind_tmp).tolist() # -> array([0,31,59,90, ...])
# (1*) Use these indices to make list months' name
the_months = months[the_months_ind]
N_the_months = len(the_months) # 8 months, in our case, from Jan to Aug
# (2*) Make list of days of the month
N_the_days = 31
the_days = np.arange(1,N_the_days+1) # [1, ..., 31]
# (3.1) Make tmp array filled with NaNs
Z_tmp = np.empty((N_the_days,N_the_months))
Z_tmp.fill(np.nan)
# (3.2) Make list of indices to fill in Z_tmp month by month
fill_i = the_months_ind + [len(months)]
# (3.3) Loop through months
for i in range(N_the_months):
i0 = fill_i[i] # get start
i1 = fill_i[i+1] # and end index
delta_i = i1-i0 # compute their difference (either 30,31 or 28)
Z_tmp[0:delta_i,i] = z_in[i0:i1] # fill in rows of
# (3*) Copy tmp array to output variable
Z = Z_tmp
return (the_months, the_days, Z) # output coordinates for our plot
# Call function, get coordinates for our plot
les_mois, les_jours, Z_jourXmois = dates_a_jourXmois(df,z)
#
les_mois.shape, les_jours.shape, Z_jourXmois.shape
((9,), (31,), (31, 9))
Ok. So, now we have a 1D array of x-axis labels, a 1D array of y-axis labels and a 2D array corresponding to our heatmap.
Before building the Plotly graph object, let's check the dimensions of our arrays:
The arrays are compatible, as the 2D array has as many rows as the array of y-axis labels and has as many columns as the array of x-axis labels.
data = Data([
Heatmap(
x=les_mois, # x-axis labels
y=les_jours, # y-axis labels
z=Z_jourXmois, # 2D array
scl='YIGnBu', # N.B. select colormap
reversescl=True, # N.B. reverve color ordering
colorbar=ColorBar(
title='Nombre de cyclistes par jour',
titleside='right',
)
)])
Where we reversed the color ordering with reversescl=True
so that, in this case, low values will be plotted in white and high values in dark-blue.
Next, make an instance of the layout object:
# URL of the data source
url = 'http://donnees.ville.montreal.qc.ca/dataset/velos-comptage'
def make_anno(text='',x=1,y=1):
return Annotation(
text= text, # annotation text
x= x, # position's x-coord
y= y, # and y-coord
xref='paper', # use paper coords
yref='paper', # for both coordinates
font= Font(
size=14), # increase font size (default is 12)
showarrow=False, # remove arrow
)
#
title = "Totaux journaliers de l'affluence cyclistes <br>\
sur 8 sites de comptage montréalais en 2013"
#Bike traffic daily totals across 8 Montreal sites in 2013"
#
anno_text = "Source et info: <a href=\""+url+"\">\
Données ouvertes de la Ville de Montréal</a>"
plot_width = 650 # plot width
plot_height = 800 # plot height in pixels
#
layout = Layout(
title= title, # plot's title
font= Font(
family='PT Sans Narrow, sans-serif', # global font
size=13,
color='#635F5D'
),
xaxis = XAxis(
title='Mois',
showgrid=False
), # remove grid
yaxis= YAxis(
title='Jours du mois', # y-axis title
autorange='reversed', # N.B. reverse tick ordering
showgrid=False, # remove grid
autotick=False, # custom ticks
dtick=1), # showing 1 tick per day
autosize=False, # custom size
height=650, # plot's height in pixels
width=800, # plot's width in pixels
annotations= [make_anno(anno_text,1,1.03)]
)
In the above, we reverse the order of the y-axis with autorange='reversed'
in YAxis
so that day 1 appears on the top of the y-axis instead of at the bottom. Alternatively, we could have reversed the order of the y-label array and flipped the 2D array accordingly.
Next, let's add an annotation citing our data source:
figure = Figure(data=data, layout=layout)
py.iplot(figure, filename='velo-comptage-1',
width=plot_width, height=plot_height) # set notebook output frame size
These numbers may seem a little high, but note that a particular cyclist can pass by one or multiple counter sites several times during the same day.
Now, comparing bike traffic for some day of month (1,2,..,31) across all month may not be the most informative analysis. Why would June 9 and July 9 show the same patterns in bike traffic? That said, comparing day of week totals could be. We expect week day (Monday to Friday) to be higher than weekend totals. Now, let's see by how much.
For subsequent analysis, we will drop the lesser-trafficked months of January, February and March. The corresponding dataframe and ararys are named without suffixes from this point on. So, first we trim the January to August dataframe:
# Liste of booleans corresponding to days in Avril à Août
i_AA = ['/01/' not in date and '/02/' not in date and
'/03/' not in date and '/09/' not in date
for date in df['Date']]
# Trim the Jan, Feb and Mar days in df_JanAug
df_AA = df[i_AA]
df_AA.head() # dataframe now starts on April 1st
Date | Unnamed: 1 | Berri1 | CSC | Mais1 | Mais2 | Parc | PierDup | Rachel1 | Totem_Laurier | |
---|---|---|---|---|---|---|---|---|---|---|
90 | 01/04/2013 | 00:00 | 371 | 245 | 276 | 608 | 343 | 66 | 2315 | 524 |
91 | 02/04/2013 | 00:00 | 1055 | 547 | 669 | 1316 | 840 | 105 | 2835 | 818 |
92 | 03/04/2013 | 00:00 | 1030 | 614 | 719 | 1470 | 869 | 119 | 3085 | 947 |
93 | 04/04/2013 | 00:00 | 1466 | 855 | 1027 | 2022 | 1243 | 261 | 2492 | 1147 |
94 | 05/04/2013 | 00:00 | 1098 | 543 | 723 | 1384 | 761 | 145 | 2553 | 995 |
5 rows × 10 columns
df_AA.tail()
Date | Unnamed: 1 | Berri1 | CSC | Mais1 | Mais2 | Parc | PierDup | Rachel1 | Totem_Laurier | |
---|---|---|---|---|---|---|---|---|---|---|
238 | 27/08/2013 | 00:00 | 5566 | 2805 | 3662 | 6355 | 3373 | 2153 | 5888 | 3738 |
239 | 28/08/2013 | 00:00 | 5560 | 2759 | 3717 | 6323 | 3355 | 1881 | 5673 | 3886 |
240 | 29/08/2013 | 00:00 | 5806 | 2766 | 3902 | 6713 | 3466 | 1941 | 6044 | 3995 |
241 | 30/08/2013 | 00:00 | 4381 | 2209 | 3019 | 5409 | 2724 | 1632 | 5109 | 3106 |
242 | 31/08/2013 | 00:00 | 2682 | 1018 | 1701 | 3178 | 1385 | 1494 | 3593 | 2303 |
5 rows × 10 columns
Perform the same operation as before to get the daily totals for all sites combined:
# Row sum of dataframe, get a numpy array
z_AA = np.array(df_AA.sum(axis=1).tolist())
# The dataframe .sum() method ignores non-number (e.g. the date strings)
# while computing the row (with axis=1) sum.
# The resulting array is 1d, 1 entry per date from Apr to Aug
z_AA.shape
(153,)
Now, we convert the daily total 1D array into a 2D array of mean traffic for each day of week for each month. Readers only interesting in heatmap plot styling ideas are invited to skip it.
# Define another convertion function
def dates_a_joursemXmois(X, zz):
dates = X['Date'].tolist() # make list of dates in dataframe
# (1.1) List of months for all item in dates
months = np.array([datetime.datetime.strptime(i,'%d/%m/%Y').strftime('%B')
for i in dates])
# (1.2) Find indices of first day of the months
_,ind_tmp = np.unique(months,return_index=True) # -> array([0,122,91,61,30])
the_months_ind = np.sort(ind_tmp).tolist() # -> array([0,30,61,91,122])
# (1*) Use these indices to make list months' names
the_months = months[the_months_ind]
N_the_months = len(the_months) # 5 months, in our case, from Apr to Aug
# (2.1) List of week day names for all items in dates
wdays = np.array([datetime.datetime.strptime(i,'%d/%m/%Y').strftime('%A')
for i in dates])
# (2*) Make list of week day names
the_wdays = np.array(['Lundis','Mardis','Mercredis','Jeudis','Vendredis',
'Samedis','Dimanches'])
N_the_wdays = len(the_wdays) # 7 days in a week
# (3.1) Init. tmp array 7 days-of-week by 5 months
Z_tmp = np.empty((N_the_wdays,N_the_months))
i_month = 0 # init. month counter
for the_month in the_months: # loop through the months
# (3.2) Find indices corresp. to the_month, trim wdays and z_in
ind_month = np.where(months == the_month)
wdays_month = wdays[ind_month]
z_month = zz[ind_month]
i_wday = 0 # init/re-init week day counter
for the_wday in the_wdays: # loop through the week days
# (3.3) Find indices corresp. to the week day, trim z_month,
# fill in Z_tmp with mean value
ind_month_wday = np.where(wdays_month == the_wday)
Z_tmp[i_wday,i_month] = np.mean(z_month[ind_month_wday])
i_wday += 1 # inc. week day counter
i_month += 1 # inc. month counter
# (3*) Copy tmp array to output variable
Z = Z_tmp
return (the_months, the_wdays, Z) # output coordinates for our next plot
# Call conversion function, get coordinates for our next plot
les_mois, les_joursem, Z_moisXjoursem = dates_a_joursemXmois(df_AA, z_AA)
les_mois.shape, les_joursem.shape, Z_moisXjoursem.shape
((5,), (7,), (7, 5))
A quick check on the dimensions:
Next, make the y-axis labels plural (e.g. Mondays instead of Monday) and normalized the 2D array by its maximum value:
# Normalize 2D array by max value
Z_moisXjoursem_norm = Z_moisXjoursem/Z_moisXjoursem.max()
Z_moisXjoursem
array([[ nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan]])
Note that the colorbar object is meant to be linked to the 'colorbar'
key in Heatmap
or, more generally, in the trace object in question. Plotly colorbars are considered specifications of each plotted trace. In other words, Plotly allows users to add multiple colorbars to the same figure. So,
my_cbartitle = "Mean bike traffic<br>per week day<br>\
norm. by max value<br>(so 1=max value)"
# Make instance of data object
data = Data([
Heatmap(
x=les_mois, # x-axis labels
y=les_joursem, # y-axis labels
z=Z_moisXjoursem_norm, # 2D array for heatmap
scl='Greys', # N.B. try other predefined colormap
reversescl=True, # reverse its color ordering
opacity=0.9, # a slightly transparent color scale
colorbar= ColorBar(
title=my_cbartitle, # color bar title
titleside='bottom', # placed below the color bar
thickness=25, # color bar thickness in px
#autotick=False, # custom colorbar ticks
ticks='outside', # tick outside colorbar
dtick=0.1 # distance between ticks
)
)])
Next, update the layout object (of the previous figure):
# Update the figure's height (in px)
layout.update(height=500)
# Update y-axis title and set tick angle
layout['yaxis'].update(title='Days of the weeks',
tickangle=-20)
# Update annotation's position
layout['annotations'][0].update(y=1.08)
# Update title
#my_title = "Fig 5.1b: Bike traffic across 8 Montreal sites in 2013"
#my_layout.update(title=my_title)
Finally, make a new instance of the figure object and send it to Plotly:
# Make instance of figure object
figure = Figure(data=data, layout=layout)
# Send figure object to Plotly's server, show result in notebook
py.iplot(figure, filename='s5_cyclists-per-wday')
Thursdays in July were on average the busiest days in 2013. Weekends are less busy than weekday by roughly 30 to 40 percent, a pretty interesting result.
Our next plot will be a correlation heatmap between the 8 sites. The correlations coefficient of two datasets $X$ and $Y$ is computed as follows:
$$ \text{Corr}_{X,Y} = \frac{\sum_i^N (X_i - \bar{X})(Y_i-\bar{Y})} {\sqrt{\sum_i^N (X_i - \bar{X})}\sqrt{\sum_i^N (Y_i - \bar{Y})}} $$Where $N$ is the sample size. $X_i$ and $Y_i$ are the sample values in each datasets.
Here, for us, we have not two by eight datasets and we would like to compute the correlation coefficient of each combination of dataset, making up a correlation matrix. The sample corresponds to the daily traffic totals at each sites.
So, first extract these values from the dataframe into a numpy 2D array:
# Get values of every row of columns 2 and up
Z_dayXsite = df.ix[:,2:].values
# 153 sample days (rows) at 8 sites (columns)
Z_dayXsite.shape
(153, 8)
Next, compute the correlation matrix
# Compute correlation, rows (i.e. days of the year) are our sample space
Corr_site = np.corrcoef(Z_dayXsite,rowvar=0)
# 8 sites correlated with themselves
Corr_site.shape
(8, 8)
The correlation matrix contains 64 entries, one for each permutation (i.e. ordered combinations) of bike counter sites.
Before plotting the correlation matrix, we will need to adjust the margin around the heatmap so that the long site names fit on the tick labels.
# (*) Import Margin
from plotly.graph_objs import Margin
help(Margin) # help!
Help on class Margin in module plotly.graph_objs.graph_objs: class Margin(PlotlyDict) | A dictionary-like object holding plot margin information. | | | Quick method reference: | | Margin.update(changes) | Margin.strip_style() | Margin.get_data() | Margin.to_graph_objs() | Margin.validate() | Margin.to_string() | Margin.force_clean() | | Valid keys: | | l [required=False] (value=number: x >= 0): | Left margin size in pixels. | | r [required=False] (value=number: x >= 0): | Right margin size in pixels. | | b [required=False] (value=number: x >= 0): | Bottom margin size in pixels. | | t [required=False] (value=number: x >= 0): | Top margin size in pixels. | | pad [required=False] (value=number: x >= 0): | The distance between edge of the plot and the bounding rectangle | that encloses the plot. | | autoexpand [required=False] (value=bool: True | False): | Aw, snap! Undocumented! | | Method resolution order: | Margin | PlotlyDict | __builtin__.dict | __builtin__.object | | Methods inherited from PlotlyDict: | | __init__(self, *args, **kwargs) | | force_clean(self, caller=True) | 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. | | get_ordered(self, caller=True) | | 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, caller=True) | 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, caller=True) | 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
In addition, let's first check the range of values of the correlation matrix:
Corr_site.min(), Corr_site.max()
(0.47982343592869092, 1.0)
Next, we overwrite the default minimum and maximum color scale values (with 'zmin'
and 'zmax'
respectively) to round up the color bar's range. So, consider,
# Make data object
my_data = Data([Heatmap(x=sites, # sites on both
y=sites, # axes
z=Corr_site, # correlation as color contours
zauto=False, # N.B. overwrite Plotly default color levels
zmin=0.4, # value of min color level
zmax=1, # value of max color level
scl='YIOrRd', # N.B. light yellow-orange-red colormap
reversescl=True # N.B. inverse colormap order
)])
# Make layout object
my_title = "Fig 5.2a: Bike traffic correlations between different sites in 2013"
my_layout = Layout(title= my_title, # plot title
font= Font(family='Georgia, serif', # global font
color='#635F5D'),
autosize=False, # turn off autosize
height=500, # plot's height in pixels
width=600, # plot's width in pixels
margin= Margin(t=100,b=120,r=100,l=100) # N.B. margin between frame
) # and axis in pixels
# Make Figure object, send to Plotly and show in notebook
my_fig = Figure(data=my_data, layout=my_layout)
py.iplot(my_fig, filename='s5_correlations')
Notice that Plotly automatically tilts the x-axis label to make them fit in the frame. Nice.
As the correlation coefficient of $X$ and $Y$ is the same as the correlation coefficient of $Y$ and $X$, we have a lot of useless information on the above plot. Let's remedy this situation with some inspiration from the Seaborn project and, more specificaly this plot. Thanks!
To convert our previous plot to the Seaborn styling, we must:
# Convert data and labels array to match Seaborn
def make_seaborn(x_old,y_old,z_old):
x_sns = x_old[0:-1] # remove last entry in x-corrd array
y_sns = y_old[-1:0:-1] # remove first entry, reverse order in y-coord array
m,n = z_old.shape # get dimension of original array
tmp = np.empty((m,n)) # init. tmp array
tmp.fill(np.nan) # with NaNs
for i in range(m): # loop through rows
tmp[i,0:i] = z_old[i,0:i] # add items below the diagonal (the unique entries)
tmp = np.flipud(tmp) # reverse order of all columns in tmp array
z_sns = tmp # copy tmp array to outpur variable
return (x_sns,y_sns,z_sns) # return new coodinates in tuple
# Call conversion function, get coordinates for our next plot
sites_x_sns, sites_y_sns, Corr_site_sns = make_seaborn(sites,sites,Corr_site)
# Check position of NaNs in new 2D array
np.isnan(Corr_site_sns)
array([[False, False, False, False, False, False, False, True], [False, False, False, False, False, False, True, True], [False, False, False, False, False, True, True, True], [False, False, False, False, True, True, True, True], [False, False, False, True, True, True, True, True], [False, False, True, True, True, True, True, True], [False, True, True, True, True, True, True, True], [ True, True, True, True, True, True, True, True]], dtype=bool)
Recall that Plotly maps the array's rows to y-axis and the array's columns to x-axis. So when plotted Corr_site_sns
will have non-NaNs values on the lower diagonal as on the Seaborn plot.
Next, we build a custom color scale (or color map or color scheme).
A custom color scale in Plotly is a list of lists linked to the 'scl'
key in Heatmap
, Contour
, Histogram2d
or Histogram2dcontour
where the nested lists have the normalized level (more info below) values as first item and the level colors as second item using whatever color model you prefer.
From this point on, Plotly takes over. The color scale is interpolated in-between the color levels, resulting in a continuous map from values in the 2D array to colors. So,
scl_sns = [[0,"#00008B"], # color of minimun level (from 'zmin')
[0.25,"#6A5ACD"], [0.5,"#FFE6F8"], [0.75, "#C71585"], # in-between
[1, "#8B0000"]] # color of maximum level (from 'zmax')
The 0
color level is the level of the value linked to the 'zmin'
key in Heatmap
. Correspondingly, the 1
color level is the level of the value linked to the 'zmax'
key set in Heatmap
.
By default, the value of 'zmin'
is the 2D array's minimum value of the value of 'zmax'
is its maxmium value. That said, they can be easily overwritten. Consider the following instance of the data object:
# Make new instance of data object
my_data = Data([Heatmap(x=sites_x_sns, # x-labels
y=sites_y_sns, # y-labels
z=Corr_site_sns, # 2D array
scl=scl_sns, # N.B. custom color scales list of lists
zauto=False, # N.B. custom color levels
zmin=0.3, # value of min color level
zmax=1, # value of max color level
)])
Ok, now tilt the axes' labels and add two annotations:
# Add a few style options to XAxis and YAxis objects
def make_axes(tickangle_in):
return dict(autotick=False, # custom ticks
tickangle=tickangle_in, # rotate tick labels
showgrid=False, # remove grid
showline=False) # remove axes line
# Tilt the labels of both axes
my_layout.update(xaxis=XAxis(make_axes(90)))
my_layout.update(yaxis=YAxis(make_axes(0)))
# Add an annotation citing the data source
my_anno_text1 = "Source and info:<br> <a href=\""+url+"\">\
Données ouvertes de la Ville de Montréal</a>"
my_anno1 = make_anno(my_anno_text1,0.9,0.875)
# Add an annotation citing start and end of sample
my_anno_text2 = "Data used:<br>\
April 01, 2013<br>to<br>August 31, 2013"
my_anno2 = make_anno(my_anno_text2,0.8,0.55)
# Update 'annotations' in layout object
my_layout.update(annotations=[my_anno1,my_anno2])
# Update title
my_title = "Fig 5.2b: Bike traffic correlations between different sites"
my_layout.update(title=my_title)
Finally, make a new instance of the figure object and send it to Plotly:
# Make new instance of figure object
my_fig = Figure(data=my_data, layout=my_layout)
# Send figure object to Plotly
py.iplot(my_fig, filename='s5_correlations-seaborn')
Much better. We now have room to spare for some annotations.
From the above plot, all the sites are well-correlated and five of them are almost perfectly correlation (correlation coefficients > 0.9). This means that we do not need to check the 8 sites to evaluate day-to-day traffic fluctuations. In other words, if traffic increases at one site, it is very likely that traffic increases at the 7 other sites.
Positive trends in bike traffic are expected to propage from the most trafficked counter site to the least trafficked counter site over time and vice versa. In our next plot, we attempt to assess this claim with a contour plot of daily bike traffic totals as a function of the date and counter site.
# (*) Import Contour
from plotly.graph_objs import Contour
help(Contour)
Help on class Contour in module plotly.graph_objs.graph_objs: class Contour(PlotlyTrace) | A dictionary-like object for representing a contour plot in plotly. | | Example: | | z = [[0, 1, 0, 1, 0], | [1, 0, 1, 0, 1], | [0, 1, 0, 1, 0],] | y = ['a', 'b', 'c'] | x = [1, 2, 3, 4, 5] | py.plot([Contour(z=z, x=x, y=y)]) | | | Quick method reference: | | Contour.update(changes) | Contour.strip_style() | Contour.get_data() | Contour.to_graph_objs() | Contour.validate() | Contour.to_string() | Contour.force_clean() | | Valid keys: | | z [required=True] (value=matrix-like: list of lists, numpy.matrix): | The data that describes the mapping. The dimensions of the 'z' | matrix are (n x m) where there are 'n' ROWS defining the number of | partitions along the y-axis; this is equal to the length of the 'y' | array. There are 'm' COLUMNS defining the number of partitions along | the x-axis; this is equal to the length of the 'x' array. Therefore, | the color of the cell z[i][j] is mapped to the ith partition of the | y-axis (starting from the bottom of the plot) and the jth partition | of the x-axis (starting from the left of the plot). In Python, a | (non-numpy) matrix is best thought of as a list of lists (of lists, | of lists, etc.). Therefore, running len(z) will give you the number | of ROWS and running len(z[0]) will give you the number of COLUMNS. | If you ARE using numpy, then running z.shape will give you the | tuple, (n, m), e.g., (3, 5). | | x [required=False] (value=array-like of numbers, strings, datetimes): | This array-like value contains the HORIZONTAL labels referring to | the COLUMNS of the 'z' matrix. If strings, the x-labels are spaced | evenly. If the dimensions of z are (n x m), the length of the 'x' | array should be 'm'. | | y [required=False] (value=array-like of numbers, strings, datetimes): | This array-like value contains the VERTICAL labels referring to the | ROWS of the 'z' matrix. If strings, the y-labels are spaced evenly. | If the dimensions of z are (n x m), the length of the 'y' array | should be 'n'. | | name [required=False] (value=string): | The label associated with this trace. This name will appear in the | legend, in the column header in the spreadsheet, and on hover. | | autocontour [required=False] (value=bool: True | False): | If True, the contours settings are set automatically. If False, the | contours settings must be set manually with the contours object. | | ncontours [required=False] (value=bool: True | False): | Speficy the number of countours lines that will appear. | | contours [required=False] (value=Contours object | dictionary-like): | A dictionary-like object defining parameters of the contours in this | plot like spacing, whether or not to show lines, etc. | | For more, run `help(plotly.graph_objs.Contours)` | | line [required=False] (value=Line object | dictionary-like): | Set contour line style (e.g. dash) and width. If showlines=True in | Contour, select line color. Select smoothing level. | | For more, run `help(plotly.graph_objs.Line)` | | scl [required=False] (value=array_like of value-color pairs | 'Greys' | | 'Greens' | 'Bluered' | 'Hot' | 'Picnic' | 'Portland' | 'Jet' | 'RdBu' | | 'Blackbody' | 'Earth' | 'Electric' | 'YIOrRd' | 'YIGnBu'): | The color scale. The strings are pre-defined color scales. For | custom color scales, define a list of color-value pairs, where the | first element of the pair corresponds to a normalized value of z | from 0-1 (i.e. (z-zmin)/(zmax-zmin)), and the second element of | pair corresponds to a color. | | Examples: | ['Greys', [[0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)']], [[0, | 'rgb(8, 29, 88)'], [0.125, 'rgb(37, 52, 148)'], [0.25, 'rgb(34, | 94, 168)'], [0.375, 'rgb(29, 145, 192)'], [0.5, 'rgb(65, 182, | 196)'], [0.625, 'rgb(127, 205, 187)'], [0.75, 'rgb(199, 233, | 180)'], [0.875, 'rgb(237, 248, 217)'], [1, 'rgb(255, 255, | 217)']]] | | reversescl [required=False] (value=bool: True | False): | Aw, snap! Undocumented! | | showscale [required=False] (value=bool: True | False): | Toggle whether or not the color scale associated with this mapping | will be shown alongside the rendered figure. | | colorbar [required=False] (value=ColorBar object | dictionary-like): | This object represents a color bar that will be shown on the figure | where the color is related to the data being shown. | | For more, run `help(plotly.graph_objs.ColorBar)` | | zauto [required=False] (value=bool: True | False): | Set to False to overwrite the default values of 'zmax' and 'zmax'. | | zmin [required=False] (value=number): | The value used as the minimum in the color scale normalization in | 'scl'. The default is the minimum of the 'z' data values. | | zmax [required=False] (value=number): | The value used as the maximum in the color scale normalization in | 'scl'. The default is the minimum of the 'z' data values. | | opacity [required=False] (value=number: x in [0, 1]): | Sets the opacity, or transparency, of this object. Also known as the | alpha channel of colors, if the object's color is given in terms of | 'rgba', this does not need to be defined. | | showlegend [required=False] (value=bool: True | False): | Toggle whether or not this trace will show up in the legend. | | stream [required=False] (value=dictionary-like): | The stream dict that initializes traces as writable-streams, for use | with the real-time streaming API. Learn more here: | https://plot.ly/python/streaming/ | | xaxis [required=False] (value=string: 'x1' | 'x2' | 'x3' | etc.): | This key determines which xaxis the x coordinates in this trace will | reference in the figure. 'x' references layout['xaxis'] and 'x2' | references layout['xaxis2']. 'x1' will always refer to | layout['xaxis'] or layout['xaxis1'], they are the same. | | yaxis [required=False] (value=string: 'y1' | 'y2' | 'y3' | etc.): | This key determines which yaxis the y coordinates in this trace will | reference in the figure. 'y' references layout['yaxis'] and 'y2' | references layout['yaxis2']. 'y1' will always refer to | layout['yaxis'] or layout['yaxis1'], they are the same. | | visible [required=False] (value=bool: True | False): | Toggles whether this will actually be visible in the rendered | figure. | | x0 [required=False] (value=number): | The location of the first coordinate of the x-axis.Use with 'dx' an | alternative to an 'x' list/array. | | dx [required=False] (value=number): | Spacing between x-axis coordinates. Use with 'x0' an alternative to | an 'x' list/array. | | y0 [required=False] (value=number): | The location of the first coordinate of the y-axis.Use with 'dy' an | alternative to an 'y' list/array. | | dy [required=False] (value=number): | Spacing between y-axis coordinates. Use with 'y0' an alternative to | an 'y' list/array. | | xtype [required=False] (value='array' | 'scaled'): | If set to 'scaled' and 'x' is linked to a list/array, then the | horizontal labels are scaled to a list of integers of unit step | starting from 0. | | ytype [required=False] (value='array' | 'scaled'): | If set to 'scaled' and 'y' is linked to a list/array, then the | vertical labels are scaled to a list of integers of unit step | starting from 0. | | type [required=True] (value=contour): | Plotly identifier for this data's trace type. This defines how this | data dictionary will be handled. For example, 'scatter' type expects | x and y data-arrays corresponding to (x, y) coordinates wheras a | 'histogram' only requires a single x or y array and a 'heatmap' type | requires a z matrix. | | Method resolution order: | Contour | PlotlyTrace | PlotlyDict | __builtin__.dict | __builtin__.object | | Methods inherited from PlotlyTrace: | | __init__(self, *args, **kwargs) | | 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 | | ---------------------------------------------------------------------- | Methods inherited from PlotlyDict: | | force_clean(self, caller=True) | 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. | | get_ordered(self, caller=True) | | 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, caller=True) | 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`. | | 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, caller=True) | 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
To better visualize the traffic propagation, the counter sites will be placed on the x-axis in order, from the most trafficked to the least in the yearly total.
So, first, sum the traffic total of all dates from April 1 to August 31:
# Column sum of dataframe, keep columns correps. to sites, get a numpy array
z_site = np.array(df.sum(axis=0).tolist()[2:])
# The dataframe .sum() method ignores non-number (e.g. the date strings)
# while computing the column (with axis=0) sum.
# Show list of sites and total cyclist count
zip(sites, z_site)
[('Berri/<br>de Maisonneuve', '617472'), ('C\xc3\xb4te-Ste-Catherine<br>(parc Beaubien)', '272218'), ('de Maisonneuve/<br>Berri', '393995'), ('de Maisonneuve/<br>Peel', '716427'), ('du Parc/<br>Duluth', '367109'), ('Pierre-Dupuy<br>(Habitat 67)', '273008'), ('Rachel/<br>Marquette', '693354'), ('Laurier<br>(m\xc3\xa9tro)', '414548')]
Next, order the sites from most trafficked to least (the x-axis labels), swap the dataframe's columns accordingly and make a list of dates (the y-axis labels):
# with the datetime module
def convert_in_order(df_in,sites,z_site):
dates = df_in['Date'].tolist() # make list of dates in dataframe
# Get values of every row of columns 2 and up (as in subsection 5.2)
Z_dayXsite = df.ix[:,2:].values
# (1-) Get list of dates in words (e.g. Mon, Jan 1)
dates_in_words = [datetime.datetime.strptime(i,'%d/%m/%Y').strftime('%a, %b %d')
for i in dates]
# (2.1-3.1) Get indices of sorted array in decreasing order
ind_in_order = np.argsort(z_site)[::-1]
# (2-) Shuffle sites list in order
sites_in_order = [sites[i] for i in ind_in_order]
# (3-) Shuffle columns (corresp. to the sites) of 2D array in order
Z_dayXsite_in_order = Z_dayXsite[:,ind_in_order]
# Output coordinates for our plot
return (dates_in_words, sites_in_order, Z_dayXsite_in_order)
# Get plot coordinates
dates_in_words,sites_in_order,Z_dayXsite_in_order = convert_in_order(df,sites,z_site)
Data for contours plot is input in the Contour
object. The Contours
object (N.B. plural) contains the style options for the contours, similar to what XBins
and YBins
are for Histogram
.
Ultimately, the Contours
is meant to be linked to the 'contours'
key in Contour
.
# (*) Import Contours
from plotly.graph_objs import Contours
help(Contours) # run help()
Help on class Contours in module plotly.graph_objs.graph_objs: class Contours(PlotlyDict) | A dictionary-like object for representing a contours object in plotly. | | This object exists inside definitions for a contour plot. | | | Quick method reference: | | Contours.update(changes) | Contours.strip_style() | Contours.get_data() | Contours.to_graph_objs() | Contours.validate() | Contours.to_string() | Contours.force_clean() | | Valid keys: | | showlines [required=Aw, snap! Undocumented!] (value=bool: True | False): | Toggle whether the contour lines appear on the plot. | | start [required=False] (value=number): | Sets the value of the first contour level. | | end [required=False] (value=number): | Sets the value of the last contour level. | | size [required=False] (value=number): | Sets the size of each contour level. | | coloring [required=False] (value=number: x < 'fill' | 'heatmap' | | 'lines' | 'none' ): | Choose coloring method. The default value is 'fill' where coloring | is done even between each contour line. 'heatmap' colors on a grid | point-by-grid point basis. 'lines' colors only the contour lines, | each with respect to the color scale.'none' prints all contour lines | with the same color,choose color in Line. | | Method resolution order: | Contours | PlotlyDict | __builtin__.dict | __builtin__.object | | Methods inherited from PlotlyDict: | | __init__(self, *args, **kwargs) | | force_clean(self, caller=True) | 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. | | get_ordered(self, caller=True) | | 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, caller=True) | 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, caller=True) | 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
To enable custom contours (i.e. by setting 'start'
, 'end'
and 'size'
in Contours
) set autocontour
to False
in Contour
.
By default, Plotly contours are colored uniformly between contour lines, corresponding to 'coloring':'fill'
in Contours
. With the 'heatmap'
value coloring is done on a grid point-by-grid point basis and with lines
only the contour lines are colored with respect to the color scale. Finally, with 'coloring:'none'
contour lines and the areas between them are not colored, use this value to make a contour plot with all contour lines of the same color.
To modify the appearance of the contour lines (e.g. their color), use the Line
object:
# (*) Import Line
from plotly.graph_objs import Line
help(Line)
Help on class Line in module plotly.graph_objs.graph_objs: class Line(PlotlyDict) | A dictionary-like object representing the style of a line in plotly. | | | Quick method reference: | | Line.update(changes) | Line.strip_style() | Line.get_data() | Line.to_graph_objs() | Line.validate() | Line.to_string() | Line.force_clean() | | Valid keys: | | dash [required=Aw, snap! Undocumented!] (value='dash' | 'dashdot' | | 'dot' | 'solid'): | The style of the line. | | color [required=False] (value=str describing color): | The color of the line. | | width [required=False] (value=number: x >= 0): | The width of the line. | | opacity [required=False] (value=number: x in [0, 1]): | Sets the opacity, or transparency, of this object. Also known as the | alpha channel of colors, if the object's color is given in terms of | 'rgba', this does not need to be defined. | | smoothing [required=Aw, snap! Undocumented!] (value=Aw, snap! | Undocumented!): | Only applies to contours | | Method resolution order: | Line | PlotlyDict | __builtin__.dict | __builtin__.object | | Methods inherited from PlotlyDict: | | __init__(self, *args, **kwargs) | | force_clean(self, caller=True) | 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. | | get_ordered(self, caller=True) | | 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, caller=True) | 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, caller=True) | 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
Contour lines are smoothed by default, corresponding to 'smoothing': 1
in Line
. Set 'smoothing'
to a value larger than 1 to smooth the contours more and to a value between 0 and 1 to for less smoothing.
Now, fill in an instance of the contour object with our data:
my_cbartitle = "Daily cyclist count per site"
# Make instance of the colorbar object
my_colorbar = ColorBar(title=my_cbartitle, # colorbar title
titleside='right', # colorbar title at right of colorbar
thickness=30, # colorbar thickness in px
len=0.8, # colorbar length in plot fraction
ticks='outside') # tick outside colorbar
# Make instance of the data object
my_data = Data([Contour(x=sites_in_order, # sites on the x-axis
y=dates_in_words, # dates on the y-axis
z=Z_dayXsite_in_order, # 2D array a f(sites,dates)
scl='Greens', # choose a color scl from the pre-defined
reversescl=True, # and reversed its order
line= Line(smoothing=1.5, # N.B. default is 1
color='#999999', # default is black
width=1), # default is 0.5
colorbar=my_colorbar # link colorbar object
)])
On to the layout,
plot_width = 650 # plot width in px
plot_height = 1000 # plot height in px
my_title = "Fig 5.3: Montral bike traffic daily progression<br>\
from the most trafficked site to the least in 2013<br>"
my_xtitle = 'Sites [from the most trafficked to the least in 2013]'
my_layout = Layout(title=my_title, # plot's title
font= Font(family='Raleway, sans-serif', # global font
color='#635F5D'),
xaxis = XAxis(title=my_xtitle), # x-axis title
yaxis= YAxis(autorange='reversed', # N.B. start y-axis at top
autotick=False, # custom tick
dtick=7), # 1 tick per week
autosize=False, # custom size
height=plot_height,
width=plot_width,
margin= Margin(b=120)) # increase bottom margin
Get a Plotly plot:
# Package data and layout into a figure object, send it to Plotly
my_fig = Figure(data=my_data, layout=my_layout)
py.iplot(my_fig, filename='s5_cyclist-time-progression',
width=plot_width, height=plot_height) # set notebook output frame size
Traffic progressions are noticeable in April, but overall all counter sites got busier at the same time.
The above contour plot contains information about all counter totals between April and September for all 8 sites. Hovering over the contours reveals each daily cyclist count, which on a static figure would be impossible. This is just another example of how Plotly makes graphing come alive.
Our upcoming plot will evaluate the probability distribution of daily cyclist counts at two different sites simultaneously using 2-dimensional histograms. To make things insteresting we choose the two least correlated counter sites.
Roughly speaking, 2-dimensional histograms present the likelihood of two event happening of the same time. In our case, the two events are site 1 getting x cyclists in a day and site 2 getting y cyclists during the same day.
As for 1-dimensional histograms (more in section 4), Plotly does the computations for you. All you need to input are the two samples corresponding to the variables of interest (e.g. the daily cyclist count at each site).
# (*) Import Histogram2d
from plotly.graph_objs import Histogram2d
help(Histogram2d)
Help on class Histogram2d in module plotly.graph_objs.graph_objs: class Histogram2d(PlotlyTrace) | A dictionary-like object for representing a histogram2d plot in plotly. | | Example: | | import numpy as np | x = np.random.randn(500) | y = np.random.randn(500)+1 | py.iplot([Histogram2d(x=x, y=y)]) | | | Quick method reference: | | Histogram2d.update(changes) | Histogram2d.strip_style() | Histogram2d.get_data() | Histogram2d.to_graph_objs() | Histogram2d.validate() | Histogram2d.to_string() | Histogram2d.force_clean() | | Valid keys: | | x [required=True] (value=array-like of numbers, strings, datetimes): | The x data that is binned and plotted as bars along the x-axis. | | y [required=True] (value=array-like of numbers, strings, datetimes): | The y data that is binned and plotted as bars along the y-axis. | | name [required=False] (value=string): | The label associated with this trace. This name will appear in the | legend, in the column header in the spreadsheet, and on hover. | | scl [required=False] (value=array_like of value-color pairs | 'Greys' | | 'Greens' | 'Bluered' | 'Hot' | 'Picnic' | 'Portland' | 'Jet' | 'RdBu' | | 'Blackbody' | 'Earth' | 'Electric' | 'YIOrRd' | 'YIGnBu'): | The color scale. The strings are pre-defined color scales. For | custom color scales, define a list of color-value pairs, where the | first element of the pair corresponds to a normalized value of z | from 0-1 (i.e. (z-zmin)/(zmax-zmin)), and the second element of | pair corresponds to a color. | | Examples: | ['Greys', [[0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)']], [[0, | 'rgb(8, 29, 88)'], [0.125, 'rgb(37, 52, 148)'], [0.25, 'rgb(34, | 94, 168)'], [0.375, 'rgb(29, 145, 192)'], [0.5, 'rgb(65, 182, | 196)'], [0.625, 'rgb(127, 205, 187)'], [0.75, 'rgb(199, 233, | 180)'], [0.875, 'rgb(237, 248, 217)'], [1, 'rgb(255, 255, | 217)']]] | | reversescl [required=False] (value=bool: True | False): | Aw, snap! Undocumented! | | showscale [required=False] (value=bool: True | False): | Toggle whether or not the color scale associated with this mapping | will be shown alongside the rendered figure. | | colorbar [required=False] (value=ColorBar object | dictionary-like): | This object represents a color bar that will be shown on the figure | where the color is related to the data being shown. | | For more, run `help(plotly.graph_objs.ColorBar)` | | zauto [required=False] (value=bool: True | False): | Set to False to overwrite the default values of 'zmax' and 'zmax'. | | zmin [required=False] (value=number): | The value used as the minimum in the color scale normalization in | 'scl'. The default is the minimum of the 'z' data values. | | zmax [required=False] (value=number): | The value used as the maximum in the color scale normalization in | 'scl'. The default is the minimum of the 'z' data values. | | zsmooth [required=False] (value= False | 'best' | 'fast' ): | Choose between algorithms ('best' or 'fast') to smooth data linked | to 'z'. | | autobinx [required=False] (value=bool: True | False): | Toggle whether or not to allow plotly to automatically pick the bin | sizing in the x direction for this histogram. | | autobiny [required=False] (value=bool: True | False): | Toggle whether or not to allow plotly to automatically pick the bin | sizing in the y direction for this histogram. | | xbins [required=False] (value=XBins object | dictionary-like): | A dictionary-like object explaining how the bins should be created | in the x direction for this histogram. | | For more, run `help(plotly.graph_objs.XBins)` | | ybins [required=False] (value=YBins object | dictionary-like): | A dictionary-like object explaining how the bins should be created | in the y direction for this histogram. | | For more, run `help(plotly.graph_objs.YBins)` | | nbinsx [required=False] (value=number: x > 0): | Specifies the number of bins in the x-direction. | | nbinsy [required=False] (value=number: x > 0): | Specifies the number of bins in the y-direction. | | histnorm [required=Aw, snap! Undocumented!] (value='' | 'percent' | | 'probability' | 'density' | 'probability density'): | If histnorm is not specified, or histnorm='' (empty string), the | height of each bar displays the frequency of occurrence, i.e., the | number of times this value was found in the corresponding bin. If | histnorm='percent', the height of each bar displays the percentage | of total occurrences found within the corresponding bin. If | histnorm='probability', the height of each bar displays the | probability that an event will fall into the corresponding bin. If | histnorm='density', the height of each bar is equal to the number of | occurrences in a bin divided by the size of the bin interval such | that summing the area of all bins will yield the total number of | occurrences. If histnorm='probability density', the height of each | bar is equal to the number of probability that an event will fall | into the corresponding bin divided by the size of the bin interval | such that summing the area of all bins will yield 1, i.e. an event | must fall into one of the bins. | | opacity [required=False] (value=number: x in [0, 1]): | Sets the opacity, or transparency, of this object. Also known as the | alpha channel of colors, if the object's color is given in terms of | 'rgba', this does not need to be defined. | | showlegend [required=False] (value=bool: True | False): | Toggle whether or not this trace will show up in the legend. | | xaxis [required=False] (value=string: 'x1' | 'x2' | 'x3' | etc.): | This key determines which xaxis the x coordinates in this trace will | reference in the figure. 'x' references layout['xaxis'] and 'x2' | references layout['xaxis2']. 'x1' will always refer to | layout['xaxis'] or layout['xaxis1'], they are the same. | | yaxis [required=False] (value=string: 'y1' | 'y2' | 'y3' | etc.): | This key determines which yaxis the y coordinates in this trace will | reference in the figure. 'y' references layout['yaxis'] and 'y2' | references layout['yaxis2']. 'y1' will always refer to | layout['yaxis'] or layout['yaxis1'], they are the same. | | visible [required=False] (value=bool: True | False): | Toggles whether this will actually be visible in the rendered | figure. | | stream [required=False] (value=dictionary-like): | The stream dict that initializes traces as writable-streams, for use | with the real-time streaming API. Learn more here: | https://plot.ly/python/streaming/ | | marker [required=False] (value=Marker object | dictionary-like): | Aw, snap! Undocumented! | | For more, run `help(plotly.graph_objs.Marker)` | | line [required=False] (value=Line object | dictionary-like): | Aw, snap! Undocumented! | | For more, run `help(plotly.graph_objs.Line)` | | type [required=True] (value=histogram2d): | Plotly identifier for this data's trace type. This defines how this | data dictionary will be handled. For example, 'scatter' type expects | x and y data-arrays corresponding to (x, y) coordinates wheras a | 'histogram' only requires a single x or y array and a 'heatmap' type | requires a z matrix. | | Method resolution order: | Histogram2d | PlotlyTrace | PlotlyDict | __builtin__.dict | __builtin__.object | | Methods inherited from PlotlyTrace: | | __init__(self, *args, **kwargs) | | 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 | | ---------------------------------------------------------------------- | Methods inherited from PlotlyDict: | | force_clean(self, caller=True) | 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. | | get_ordered(self, caller=True) | | 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, caller=True) | 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`. | | 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, caller=True) | 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
The style keys in Histogram2d
are the same as in Heatmap
.
First, find the two least correlated sites using the correlation matrix Corr_site
computed in subsection 5.2:
# Get 2D index (as a tuple) of the least correlated sites
ind_least_corr = np.unravel_index(Corr_site.argmin(), Corr_site.shape)
# Get 1st site, remove <br> tag from string
site1 = sites[ind_least_corr[0]].replace('<br>','')
z_day1 = Z_dayXsite[:,ind_least_corr[0]]
# And similarly for the 2nd site, remove <br> tag from string
site2 = sites[ind_least_corr[1]].replace('<br>',' ')
z_day2 = Z_dayXsite[:,ind_least_corr[1]]
site1, site2 # the 2 least-correlated sites
('du Parc/Duluth', 'Pierre-Dupuy (Habitat 67)')
Our plot will feature custom axes ranges and bin sizes.
So, let's get an idea of the range of each sample:
z_day1.max(), z_day2.max()
(4103, 4841)
For presentation purposes, the axes' and bins' upper limits will be rounded up to 5000.
Moreover, we will smooth the counters using 'zsmooth
key in Histogram2d
and overlay scatter points of both two sites' daily cyclist counts, plotted against each other. Each scatter point will be label by the date using dates_in_words
list defined in subsection 5.3.
# (*) Import a few more graph objects
from plotly.graph_objs import Scatter, Marker, XBins, YBins
# Select axis and bin range and bin size
my_range = [0,5000]
my_bin_size = 500
my_bins = dict(start=my_range[0], # store them in dictionary
end=my_range[1], # to be places in XBins and YBins instances
size=my_bin_size)
my_cbar_title='Number of occurences from Apr 1 to Aug 31' # colorbar title
# Make instance of Histogram2d object
# with no histogram normalization (the default)
my_hist2d = Histogram2d(x=z_day1, # sample of the x-axis
y=z_day2, # sample of the y-axis
xbins= XBins(my_bins), # custom x-axis bins
ybins= YBins(my_bins), # custom y-axis bins
zsmooth='best', # N.B. apply smoothing to contours
scl='Portland', # N.B. choose a pre-defined color scale
colorbar= ColorBar(title=my_cbar_title,# colorbar title
titleside='right', # title right of colorbar
ticks='outside')) # ticks outside colorbar
# Make instance of Scatter
my_scatter = Scatter(x=z_day1, # x coordinates
y=z_day2, # y coordinates
mode='markers', # just marker pts
name='', # no name
text=dates_in_words, # text label corresp. to date
marker= Marker(size=5, # marker size
color='#e0e0e0')) # and color
# Package in Data, plot scatter on top of 2d histogram
my_data = Data([my_hist2d, my_scatter])
On to the latyout:
# Define figure and axis titles
my_title = 'Fig 5.4a: Joint frequency distribution<br>\
of daily cyclist counts at two Montreal sites in 2013'
my_xtitle = 'Daily cyclist count at {}'.format(site1)
my_ytitle = 'Daily cyclist count at {}'.format(site2)
# Make instance of Layout
my_layout = Layout(title=my_title, # figure title
font= Font(family='PT Sans Narrow, sans-serif', # global font
size=13),
xaxis= XAxis(title=my_xtitle, # x-axis title
range=my_range, # x-axis range
zeroline=False), # remove x=0 line
yaxis= YAxis(title=my_ytitle, # y-axis title
range=my_range, # y-axis range
zeroline=False), # remove y=0 line
showlegend=False, # remove legend
autosize=False, # custom size
width=650, # figure width
height=520) # and height
# Add an annotation citing the data source
my_anno_text = "Source and info: <a href=\""+url+"\">\
Données ouvertes de la Ville de Montréal</a>"
my_layout.update(annotations=[make_anno(my_anno_text,1,1.055)])
Finally, package data and layout object into an instance of Figure
and send it to Plotly:
# Make instance of figure object
my_fig = Figure(data=my_data, layout=my_layout)
# Define filename in relation to the sites chosen, call Plotly
my_filename = 's5_hist2d-sites-{}-{}'.format(ind_least_corr[0],ind_least_corr[1])
py.iplot(my_fig, filename=my_filename)
Notice that there are a few hotspots of probability. By hovering over the scatter points, we notice that the Pierre-Dupuy site gets most of its traffic during weekends and holidays.
Next, we add two subplots to the above figure showing 1D histograms of daily cyclist counts for each of the two counter site (i.e. their marginal distibutions).
From our current instance of the figure object, we first adjust the domains of the axes in place and add one x-axis and one y-axis:
# (*) Import Histogram
from plotly.graph_objs import Histogram
# Adjust the existing axes
my_layout['xaxis'].update(domain=[0, 0.7]) # decrease domain of x-axis1 (norm. coord.)
my_layout['yaxis'].update(domain=[0, 0.7], # decrease domain of y-axis1
showgrid=False) # remove vertical grid lines
# Set up new axes
my_layout.update(xaxis2= XAxis(domain=[0.75, 1], # domain of x-axis2
zeroline=False, # remove x=0 line
showgrid=True)) # show horizontal grid line
my_layout.update(yaxis2= YAxis(domain=[0.75, 1], # domain of y-axis2
zeroline=False, # remove y=0 line
showgrid=True)) # show vertical line
# Change location of the annotation citing the data source
my_anno_text = "Source and info:<br> <a href=\""+url+"\">\
Données ouvertes</a><br>de la Ville de Montréal"
my_layout['annotations'][0].update(make_anno(my_anno_text,0.98,0.95))
Next, make two instances of Histogram
(N.B. the 1D version) and append to the current instance of the data object:
# Make instance of Histogram, with vertical bins and no normalization
my_histx = Histogram(x=z_day1, # x sample, bind bins to x-axis
name='', # no name on hover
xbins= XBins(my_bins), # use same bins as in the 2D histogram
marker= Marker(color="rgb(242,211,56)"), # choose bin color
xaxis='x1', # bind x coords to xaxis1
yaxis='y2') # bind y coords to yaxis2
# Make instance of Histogram, with horizontal bins and no normalization
my_histy = Histogram(y=z_day2, # y sample, bind bins to y-axis
name='', # no name on hover
ybins= YBins(my_bins), # use same bins as in the 2D histogram
marker= Marker(color="rgb(242,211,56)"), # choose bin color
xaxis='x2', # bind x coords to xaxis2
yaxis='y1') # bind y coords to yaxis2
# Append data object
my_data += [my_histx, my_histy]
Tweak the colorbar's appearance, update the figure's titls and call Plotly:
# Updata colorbar position, length and thickness
my_data[0]['colorbar'].update(x=0.99,y=0.35,len=0.7,thickness=20)
# Update title
my_title = 'Fig 5.4b: Joint frequency distribution<br>\
of daily cyclist counts at two Montreal sites in 2013'
my_layout.update(title=my_title)
# Mkae new instance of figure object, send it to Plotly
my_fig = Figure(data=my_data, layout=my_layout)
my_filename = 's5_hist2dsplt-sites-{}-{}'.format(ind_least_corr[0],ind_least_corr[1])
py.iplot(my_fig, filename=my_filename)
The axes are shared (try zooming on the 2D histogram). It is interesting to see that the distribution of the Pierre Dupuy site is much more skewed than Parc/Duluth.
Plotly allows users to plot 2D histograms of similar in appearance to ones generated by the Contour
graph object using Histogram2dContour
,
# (*) Import Histogram2dContour
from plotly.graph_objs import Histogram2dContour
help(Histogram2dContour)
Help on class Histogram2dContour in module plotly.graph_objs.graph_objs: class Histogram2dContour(PlotlyTrace) | A dict-like object for representing a histogram2d-contour plot in plotly. | | Example: | | import numpy as np | x = np.random.randn(500) | y = np.random.randn(500)+1 | py.iplot([Histogram2dcountour(x=x, y=y)]) | | | Quick method reference: | | Histogram2dContour.update(changes) | Histogram2dContour.strip_style() | Histogram2dContour.get_data() | Histogram2dContour.to_graph_objs() | Histogram2dContour.validate() | Histogram2dContour.to_string() | Histogram2dContour.force_clean() | | Valid keys: | | x [required=True] (value=array-like of numbers, strings, datetimes): | The x data that is binned and plotted as bars along the x-axis. | | y [required=True] (value=array-like of numbers, strings, datetimes): | The y data that is binned and plotted as bars along the y-axis. | | name [required=False] (value=string): | The label associated with this trace. This name will appear in the | legend, in the column header in the spreadsheet, and on hover. | | autocontour [required=False] (value=bool: True | False): | If True, the contours settings are set automatically. If False, the | contours settings must be set manually with the contours object. | | ncontours [required=False] (value=bool: True | False): | Speficy the number of countours lines that will appear. | | contours [required=False] (value=Contours object | dictionary-like): | A dictionary-like object defining parameters of the contours in this | plot like spacing, whether or not to show lines, etc. | | For more, run `help(plotly.graph_objs.Contours)` | | line [required=False] (value=Line object | dictionary-like): | Set contour line style (e.g. dash) and width. If showlines=True in | Contour, select line color. Select smoothing level. | | For more, run `help(plotly.graph_objs.Line)` | | scl [required=False] (value=array_like of value-color pairs | 'Greys' | | 'Greens' | 'Bluered' | 'Hot' | 'Picnic' | 'Portland' | 'Jet' | 'RdBu' | | 'Blackbody' | 'Earth' | 'Electric' | 'YIOrRd' | 'YIGnBu'): | The color scale. The strings are pre-defined color scales. For | custom color scales, define a list of color-value pairs, where the | first element of the pair corresponds to a normalized value of z | from 0-1 (i.e. (z-zmin)/(zmax-zmin)), and the second element of | pair corresponds to a color. | | Examples: | ['Greys', [[0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)']], [[0, | 'rgb(8, 29, 88)'], [0.125, 'rgb(37, 52, 148)'], [0.25, 'rgb(34, | 94, 168)'], [0.375, 'rgb(29, 145, 192)'], [0.5, 'rgb(65, 182, | 196)'], [0.625, 'rgb(127, 205, 187)'], [0.75, 'rgb(199, 233, | 180)'], [0.875, 'rgb(237, 248, 217)'], [1, 'rgb(255, 255, | 217)']]] | | reversescl [required=False] (value=bool: True | False): | Aw, snap! Undocumented! | | showscale [required=False] (value=bool: True | False): | Toggle whether or not the color scale associated with this mapping | will be shown alongside the rendered figure. | | colorbar [required=False] (value=ColorBar object | dictionary-like): | This object represents a color bar that will be shown on the figure | where the color is related to the data being shown. | | For more, run `help(plotly.graph_objs.ColorBar)` | | zauto [required=False] (value=bool: True | False): | Set to False to overwrite the default values of 'zmax' and 'zmax'. | | zmin [required=False] (value=number): | The value used as the minimum in the color scale normalization in | 'scl'. The default is the minimum of the 'z' data values. | | zmax [required=False] (value=number): | The value used as the maximum in the color scale normalization in | 'scl'. The default is the minimum of the 'z' data values. | | autobinx [required=False] (value=bool: True | False): | Toggle whether or not to allow plotly to automatically pick the bin | sizing in the x direction for this histogram. | | autobiny [required=False] (value=bool: True | False): | Toggle whether or not to allow plotly to automatically pick the bin | sizing in the y direction for this histogram. | | xbins [required=False] (value=XBins object | dictionary-like): | A dictionary-like object explaining how the bins should be created | in the x direction for this histogram. | | For more, run `help(plotly.graph_objs.XBins)` | | ybins [required=False] (value=YBins object | dictionary-like): | A dictionary-like object explaining how the bins should be created | in the y direction for this histogram. | | For more, run `help(plotly.graph_objs.YBins)` | | nbinsx [required=False] (value=number: x > 0): | Specifies the number of bins in the x-direction. | | nbinsy [required=False] (value=number: x > 0): | Specifies the number of bins in the y-direction. | | histnorm [required=Aw, snap! Undocumented!] (value='' | 'percent' | | 'probability' | 'density' | 'probability density'): | If histnorm is not specified, or histnorm='' (empty string), the | height of each bar displays the frequency of occurrence, i.e., the | number of times this value was found in the corresponding bin. If | histnorm='percent', the height of each bar displays the percentage | of total occurrences found within the corresponding bin. If | histnorm='probability', the height of each bar displays the | probability that an event will fall into the corresponding bin. If | histnorm='density', the height of each bar is equal to the number of | occurrences in a bin divided by the size of the bin interval such | that summing the area of all bins will yield the total number of | occurrences. If histnorm='probability density', the height of each | bar is equal to the number of probability that an event will fall | into the corresponding bin divided by the size of the bin interval | such that summing the area of all bins will yield 1, i.e. an event | must fall into one of the bins. | | opacity [required=False] (value=number: x in [0, 1]): | Sets the opacity, or transparency, of this object. Also known as the | alpha channel of colors, if the object's color is given in terms of | 'rgba', this does not need to be defined. | | showlegend [required=False] (value=bool: True | False): | Toggle whether or not this trace will show up in the legend. | | xaxis [required=False] (value=string: 'x1' | 'x2' | 'x3' | etc.): | This key determines which xaxis the x coordinates in this trace will | reference in the figure. 'x' references layout['xaxis'] and 'x2' | references layout['xaxis2']. 'x1' will always refer to | layout['xaxis'] or layout['xaxis1'], they are the same. | | yaxis [required=False] (value=string: 'y1' | 'y2' | 'y3' | etc.): | This key determines which yaxis the y coordinates in this trace will | reference in the figure. 'y' references layout['yaxis'] and 'y2' | references layout['yaxis2']. 'y1' will always refer to | layout['yaxis'] or layout['yaxis1'], they are the same. | | visible [required=False] (value=bool: True | False): | Toggles whether this will actually be visible in the rendered | figure. | | stream [required=False] (value=dictionary-like): | The stream dict that initializes traces as writable-streams, for use | with the real-time streaming API. Learn more here: | https://plot.ly/python/streaming/ | | marker [required=False] (value=Marker object | dictionary-like): | Aw, snap! Undocumented! | | For more, run `help(plotly.graph_objs.Marker)` | | type [required=True] (value=histogram2dcontour): | Plotly identifier for this data's trace type. This defines how this | data dictionary will be handled. For example, 'scatter' type expects | x and y data-arrays corresponding to (x, y) coordinates wheras a | 'histogram' only requires a single x or y array and a 'heatmap' type | requires a z matrix. | | Method resolution order: | Histogram2dContour | PlotlyTrace | PlotlyDict | __builtin__.dict | __builtin__.object | | Methods inherited from PlotlyTrace: | | __init__(self, *args, **kwargs) | | 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 | | ---------------------------------------------------------------------- | Methods inherited from PlotlyDict: | | force_clean(self, caller=True) | 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. | | get_ordered(self, caller=True) | | 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, caller=True) | 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`. | | 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, caller=True) | 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
which shares the same style keys as Contour
(more in subsection 5.3).
Next, we take a color scheme from the popular ColorBrewer website and convert it to Plotly syntax. Thanks to the colorbrewer Python package, ColorBrewer color schemes can be easily importing in a Python/IPython session. You can download the package using pip:
$ pip install colorbrewer
As we saw previously, a custom color scale in Plotly is simply a list of lists linked to the 'scl'
key where the nested lists have the normalized level values as first item and the level colors as second item. So, consider the following function
import colorbrewer as cb # import colorbrewer
# uses numpy as well
def convert_cb_to_scl(cb_color,N=5):
'''
cb_color (positional): colorbrewer color dictionary
N (keyword): number of colors in color scale
'''
colors = cb_color[N] # get list of N color tuples from cb dict
levels = np.linspace(0,1,N).tolist() # get list of N levels
# Make color scale list of lists, conveting each tuple to 'rgb( , , )'
scl_cb = []
scl_cb += [[i, "rgb("+','.join(map(str,color))+")"]
for i,color in zip(levels,colors)]
return scl_cb
Now, choose a color scheme on colorbrewer2.org. The names are listed near the EXPORT
button in the middle of the page,
# Convert the Purples colorbrewer scale to Plotly syntax
scl_cb = convert_cb_to_scl(cb.Purples)
and fill in an instance of Histogram2dContour
. For this plot, color only the contour lines by setting 'coloring':'lines'
in Contours
.
my_cbar_title='Number of occurences from Apr 1 to Aug 31' # colorbar title
# Make instance of Histogram2dContour object
# with no histogram normalization (the default)
my_data = Data([Histogram2dContour(
x=z_day1, # sample of the x-axis
y=z_day2, # sample of the y-axis
xbins= XBins(my_bins), # custom x-axis bins (as in fig 5.4a & 5.4b)
ybins= YBins(my_bins), # custom y-axis bins
scl= scl_cb, # N.B. colorbrewer color scale
colorbar= ColorBar(title=my_cbar_title, # colorbar title
titleside='right', # title below colorbar
autotick=False, # custom ticks
dtick=1, # 1 tick for every number of occurences
ticks=''), # no colorbar ticks
contours= Contours(coloring='lines'), # N.B. color only the lines
line= Line(width=3))]) # N.B. increse line width
With a similar layout to fig 5.4a:
# Define figure and axis titles
my_title = 'Fig 5.4c: Joint frequency distribution<br>\
of daily cyclist counts at two Montreal sites in 2013'
my_xtitle = 'Daily cyclist count at {}'.format(site1)
my_ytitle = 'Daily cyclist count at {}'.format(site2)
# Make instance of Layout
my_layout = Layout(title=my_title, # figure title
font= Font(family='PT Sans Narrow, sans-serif', # global font
size=13),
xaxis= XAxis(title=my_xtitle, # x-axis title
range=my_range, # x-axis range
zeroline=False), # remove x=0 line
yaxis= YAxis(title=my_ytitle, # y-axis title
range=my_range, # y-axis range
zeroline=False), # remove y=0 line
showlegend=False, # remove legend
autosize=False, # custom size
width=650, # figure width
height=520) # and height
# Add an annotation citing the data source
my_anno_text = "Source and info: <a href=\""+url+"\">\
Données ouvertes de la Ville de Montréal</a>"
my_layout.update(annotations=[make_anno(my_anno_text,1,1.055)])
Finally, send the figure object to Plotly and get a plot:
my_fig = Figure(data=my_data, layout=my_layout)
my_filename = 's5_hist2contour-sites-{}-{}'.format(ind_least_corr[0],ind_least_corr[1])
py.iplot(my_fig, filename=my_filename)
Section 6 --- Convert your Matplotlib plots to Plotly
Section 4 --- Histograms & Box Plots
About Plotly
About the User Guide
Big thanks to
from IPython.display import display, HTML
url = 'https://raw.githubusercontent.com/plotly/python-user-guide/master/custom.css'
display(HTML(urllib2.urlopen(url).read()))