Section 1 is divided as follows:
Check which version is installed on your machine and please upgrade if needed.
# (*) Import plotly package
import plotly
# Check plolty version (if not latest, please upgrade)
plotly.__version__
'1.9.5'
For our first plot in this section, we use data from this Quartz graph:
# Embed Plotly graph in notebook
# Quartz is username of the graph's maker,
# 7 is the graph's unique id number
tls.embed('Quartz', '7')
# Or any of:
# tls.embed('Quartz', 7)
# tls.embed('https://plotly.com/~Quartz/7')
The above graph was featured in this Quartz story.
Our first plot will present that the data using lines and points instead of bars (more on Plotly bar charts in section 2). As we will see, Plotly's syntax makes converting a graph from one plot type to another a breeze.
So first, pull down the figure object from Plotly's servers into this IPython session using the get_figure
function:
# Get figure object from Plotly's servers
# Quartz is username of the graph's maker,
# 7 is the graph's unique id number (either a string or an integer)
Quartz7 = py.get_figure('Quartz', '7')
print(Quartz7.to_string()) # print in notebook
Figure( data=Data([ Bar( x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2..', ], y=[u'1.1', u'1.5', u'2.1', u'2.8', u'3.4', u'4.1', u'5.0', '..' ], name=u'China', marker=Marker( color=u'rgb(222, 113, 88)' ) ), Bar( x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2..', ], y=[u'1.3', u'1.2', u'1.3', u'1.4', u'1.5', u'1.5', u'1.5', '..' ], name=u'U.S.', marker=Marker( color=u'rgb(84, 172, 234)' ) ) ]), layout=Layout( title=u'<br> #OF UNIVERSITY GRADUATES IN CHINA VS. U.S. (MILLIONS)', titlefont=Font( family=u'', size=0, color=u'' ), font=Font( family=u"'Open sans', verdana, arial, sans-serif", size=12, color=u'rgb(33, 33, 33)' ), showlegend=True, autosize=False, width=700, height=400, xaxis=XAxis( title=u"<i>Data: Solidiance's Analysis</i>", titlefont=Font( family=u'', size=0, color=u'' ), range=[2000.5, 2014.1492895382241], domain=[0, 1], type=u'linear', rangemode=u'normal', autorange=True, showgrid=False, zeroline=False, showline=True, autotick=True, nticks=17, ticks=u'', showticklabels=True, tick0=2001, dtick=1, ticklen=5, tickwidth=1, tickcolor=u'#000', tickangle=u'auto', tickfont=Font( family=u'', size=0, color=u'' ), exponentformat=u'e', showexponent=u'all', mirror=False, gridcolor=u'#ddd', gridwidth=1, zerolinecolor=u'#000', zerolinewidth=1, linecolor=u'#000', linewidth=1, anchor=u'y', overlaying=False, position=0 ), yaxis=YAxis( title=u'', titlefont=Font( family=u'', size=0, color=u'' ), range=[0, 8.1], domain=[0, 1], type=u'linear', rangemode=u'nonnegative', autorange=False, showgrid=True, zeroline=False, showline=True, autotick=True, nticks=0, ticks=u'', showticklabels=True, tick0=0, dtick=2, ticklen=5, tickwidth=1, tickcolor=u'#000', tickangle=u'auto', tickfont=Font( family=u'', size=0, color=u'' ), exponentformat=u'e', showexponent=u'all', mirror=False, gridcolor=u'#ddd', gridwidth=1, zerolinecolor=u'#000', zerolinewidth=1, linecolor=u'#000', linewidth=1, anchor=u'x', overlaying=False, position=0 ), legend=Legend( x=0.001851851851851852, y=0.9863636363636363, traceorder=u'normal', font=Font( family=u'', size=0, color=u'' ), bgcolor=u'rgba(255, 255, 255, 0)', bordercolor=u'rgba(0, 0, 0, 0)', borderwidth=1, xanchor=u'auto', yanchor=u'auto' ), annotations=Annotations([ Annotation( x=2001.7, y=2.4299999999999997, xref=u'x', yref=u'y', text=u'Source: <a href="http://qz.com/187350/six-charts-tha..', showarrow=True, font=Font( family=u'', size=0, color=u'' ), xanchor=u'auto', yanchor=u'auto', align=u'center', arrowhead=1, arrowsize=1, arrowwidth=0, arrowcolor=u'rgba(0, 0, 0, 0)', ax=446, ay=114.98332977294922, textangle=0, bordercolor=u'', borderwidth=1, borderpad=1, bgcolor=u'rgba(0,0,0,0)', opacity=1 ) ]), margin=Margin( l=80, r=80, b=80, t=100, pad=0, autoexpand=True ), paper_bgcolor=u'#fff', plot_bgcolor=u'#fff', hovermode=u'x', dragmode=u'zoom', separators=u'.,', barmode=u'group', bargap=0.1, bargroupgap=0.15, boxmode=u'overlay', boxgap=0.3, boxgroupgap=0.3, hidesources=False ) )
Recall that a Plotly figure object is divided into a data object (storing data and style options associated with each trace) and a layout object (storing information associated with the axes, legend, annotations and other layout features).
In this case, here, the data object contains two bar objects: one with data for China and one with data for the USA.
Data objects are list-like, the ordering determines the order at which the individual traces are plotted. This has an impact on a graph's appearance if two or more traces have overlapping coordinates. By virtue of the ordering, the last trace listed in the data object appears in the foreground.
So, take note that in the Quartz7
figure object, the trace corresponding to China's numbers is the first item in the data object.
Now, using the get_data()
figure object method, retrieve the data from the figure object:
# Retrieve data from figure object (get a dictionary in return)
Quartz7_data = Quartz7.get_data()
Quartz7_data # show in notebook
{'data': [{'name': u'China', 'x': [u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'2008', u'2009', u'2010', u'2011', u'2012'], 'y': [u'1.1', u'1.5', u'2.1', u'2.8', u'3.4', u'4.1', u'5.0', u'5.6', u'6.1', u'6.3', u'6.6', u'6.8']}, {'name': u'U.S.', 'x': [u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'2008', u'2009', u'2010', u'2011', u'2012'], 'y': [u'1.3', u'1.2', u'1.3', u'1.4', u'1.5', u'1.5', u'1.5', u'1.6', u'1.6', u'1.7', u'1.7', u'1.8']}], 'layout': [{}]}
Quartz7_data
is a dictionary, not a Python graph object (try running type(Quartz7_data)
to see it yourself).
Notice that both traces' 'name'
keys and their associated values are part of the Quartz7_data
dictionary. Values linked to 'name'
are the labels in the legend. They also appear on hover next to the scatter points' coordinates.
More clearly, the two items in the list of traces are:
Quartz7_data['data'][0] # show dictionary associated with data for China
{'name': u'China', 'x': [u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'2008', u'2009', u'2010', u'2011', u'2012'], 'y': [u'1.1', u'1.5', u'2.1', u'2.8', u'3.4', u'4.1', u'5.0', u'5.6', u'6.1', u'6.3', u'6.6', u'6.8']}
Quartz7_data['data'][1] # show dictionary associated with data for the USA
{'name': u'U.S.', 'x': [u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'2008', u'2009', u'2010', u'2011', u'2012'], 'y': [u'1.3', u'1.2', u'1.3', u'1.4', u'1.5', u'1.5', u'1.5', u'1.6', u'1.6', u'1.7', u'1.7', u'1.8']}
Our task now is to place the dictionaries associated with data for China and data for the USA inside two different instances of the scatter object.
Before doing so, we call help on Scatter
(from plotly.graph_objs
):
help(Scatter) # call help!
# notice 'mode'
Help on class Scatter in module plotly.graph_objs.graph_objs: class Scatter(PlotlyDict) | Valid attributes for 'scatter' at path [] under parents (): | | ['textposition', 'uid', 'stream', 'ysrc', 'hoverinfo', 'xsrc', | 'visible', 'marker', 'y0', 'tsrc', 'line', 'fill', 'showlegend', | 'error_x', 'error_y', 'rsrc', 'xaxis', 'text', 'type', 't', 'opacity', | 'textfont', 'legendgroup', 'textpositionsrc', 'textsrc', 'dx', 'dy', | 'x0', 'name', 'yaxis', 'connectgaps', 'r', 'mode', 'y', 'x', | 'fillcolor'] | | Run `<scatter-object>.help('attribute')` on any of the above. | '<scatter-object>' is the object at [] | | Method resolution order: | Scatter | PlotlyDict | __builtin__.dict | PlotlyBase | __builtin__.object | | Methods inherited from PlotlyDict: | | __copy__(self) | | __deepcopy__(self, memodict={}) | | __dir__(self) | Dynamically return the existing and possible attributes. | | __getattr__(self, key) | Python only calls this when key is missing! | | __getitem__(self, key) | Calls __missing__ when key is not found. May mutate object. | | __init__(self, *args, **kwargs) | | __missing__(self, key) | Mimics defaultdict. This is called from __getitem__ when key DNE. | | __setattr__(self, key, value) | Maps __setattr__ onto __setitem__ | | __setitem__(self, key, value, _raise=True) | Validates/Converts values which should be Graph Objects. | | force_clean(self, **kwargs) | Recursively remove empty/None values. | | get_data(self, flatten=False) | Returns the JSON for the plot with non-data elements stripped. | | get_ordered(self, **kwargs) | Return a predictable, OrderedDict version of self. | | help(self, attribute=None, return_help=False) | Print help string for this object or an attribute of this object. | | :param (str) attribute: A valid attribute string for this object. | :param (bool) return_help: Return help_string instead of printing it? | :return: (None|str) | | strip_style(self) | Recursively 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 graph_objs_meta.json. Note that a key tagged as | style, but with an array as a value may still be considered data. | | to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80) | Returns a formatted string showing graph_obj constructors. | | :param (int) level: The number of indentations to start with. | :param (int) indent: The indentation amount. | :param (str) eol: The end of line character(s). | :param (bool) pretty: Curtail long list output with a '..' ? | :param (int) max_chars: The max characters per line. | | Example: | | print(obj.to_string()) | | 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. | | ---------------------------------------------------------------------- | Data descriptors inherited from PlotlyDict: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | 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 | | __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) | | __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 | | ---------------------------------------------------------------------- | Methods inherited from PlotlyBase: | | to_graph_objs(self, **kwargs) | Everything is cast into graph_objs. Here for backwards compat. | | validate(self) | Everything is *always* validated now. keep for backwards compat.
Pay special attention to the 'mode'
key. It accepts as values 'lines'
, 'markers'
, 'text'
and any sets of these three, determining how the coordinates are displayed.
'markers'
, coordinates are display as free (i.e. scatter, unlinked) points,'lines'
, coordinates are linked with lines,'text'
, text linked to the 'text'
in Scatter
is display on top of the coordinates (more in subsection 1.4).Then, for example, the set 'lines+markers'
(or 'markers+lines'
, order is unimportant) corresponds to points at the coordinates together with lines in-between them. Another possibility is 'lines+markers+text'
which displays points at the coordinates, lines in-between them as well as text at the coordinates.
We choose to set 'mode'
to 'lines+markers'
for the China Scatter
instance and set 'mode'
to 'markers'
for the USA Scatter
instance.
The China scatter trace object is then:
# Make scatter trace object with data for China
trace_china = Scatter(
Quartz7_data['data'][0], # (!) 'name', 'x' and 'y' as in original figure
mode='markers+lines' # marker pts and lines (the default here)
)
print(trace_china.to_string())
Scatter( x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'..', ], y=[u'1.1', u'1.5', u'2.1', u'2.8', u'3.4', u'4.1', u'5.0', u'5.6', '..' ], mode='markers+lines', name=u'China' )
Correspondingly, the USA scatter trace object is:
# Make instance of Scatter object with data for the USA
trace_usa = Scatter(
Quartz7_data['data'][1], # (!) 'name', 'x' and 'y' as in original figure
mode='markers', # show marker pts only
marker=Marker(
symbol='square' # show square marker pts
)
)
print(trace_usa.to_string())
Scatter( x=[u'2001', u'2002', u'2003', u'2004', u'2005', u'2006', u'2007', u'..', ], y=[u'1.3', u'1.2', u'1.3', u'1.4', u'1.5', u'1.5', u'1.5', u'1.6', '..' ], mode='markers', name=u'U.S.', marker=Marker( symbol='square' ) )
Next, package these two scatter trace objects using a data object:
# Make data object containing two traces
data = Data([trace_china, trace_usa])
Add our own title for this figure in the layout object:
# Make a layout object
layout = Layout(title='Fig 1: Number of university graduates [in millions]')
Recall that all the information about any Plotly figure is contained in a lone figure JSON object. From Plotly's Python API, Data and layout are brought together with Figure
:
# Make a figure object
fig = Figure(data=data, layout=layout)
Finally, send fig
to Plotly using the iplot()
method attached a file name and get the resulting plot directly in this notebook:
# (@) Send figure object to Plotly and show result in notebook
py.iplot(fig, filename='s1_grad-china-usa')
All that's it.
We just converted an existing Plotly bar charts into a scatter plot.
Hover over the scatter points with your cursor and see how Plotly's interactibility is ideal to compare two y-coordinates for a given x-coordinate.
If you want more examples and information regarding how to make scatter and line plots, you can refer to the following links for Line Charts and Scatter Plots.
The way figures made from the API are saved is determined by the fileopt
keyword argument in py.plot()
and py.iplot()
. We encourage user to always specify a file name for each Plotly figure made, using the filename
keyword, in order to better track of them.
The fileopt
keyword argument can take on four values: 'new'
, 'overwrite'
, 'append'
and 'extend'
. For now, take note that by default, if filename
is set then fileopt
corresponds to 'overwrite'
. That is,
>>> py.plot(fig, filename='some-figure')
followed by
>>> py.plot(fig2, filename='some-figure')
will overwrite the figure made with the figure object fig
with a figure made with fig2
. Alternatively,
>>> py.plot(fig,filename='s1_grad-china-usa', fileopt='new')
creates a new file named s1_grad-china-usa (1)
if s1_grad-china-usa
already exist on your Plotly account. Your workspace would look something like:
If s1_grad-china-usa (1)
already existed then the new file would have been named s1_grad-china-usa (2)
and so on.
In addition, Plotly allows users to create folders of files. For example,
>>> py.plot(fig, filename='some-folder/some-figure')
saves the generated figure in a file named some-figure
in a folder named some-folder
(that Plotly automatically creates if it does not exist).
By default, Plotly figures made from the Python API are public meaning that anyone is allow to see them. To make a private figure simply add world_readable=False
to your py.plot()
or py.iplot
call, for example:
>>> py.plot(fig, filename='private-fig', world_readable=False)
Importing a Plotly figure as an image to your hard drive can be done either from the Workspace or the directly from an Python/IPython session.
To import a Plotly figure from the workspace,
where you can choose the image's size and format.
Imports from an Python/IPython session are done by making a call to Plotly's image server with the plotly.plotly.image
class:
help(py.image) # call help!
Help on class image in module plotly.plotly.plotly: class image | Helper functions wrapped around plotly's static image generation api. | | Class methods defined here: | | ishow(cls, figure_or_data, format='png', width=None, height=None) from __builtin__.classobj | Display a static image of the plot described by `figure` | in an IPython Notebook. | | save_as(cls, figure_or_data, filename, format=None, width=None, height=None) from __builtin__.classobj | Save a static image of the plot described by `figure` locally as `filename`. | Valid image formats are 'png', 'svg', 'jpeg', and 'pdf'. | The format is taken as the extension of the filename or as the supplied format. | | ---------------------------------------------------------------------- | Static methods defined here: | | get(figure_or_data, format='png', width=None, height=None) | Return a static image of the plot described by `figure`. | | Valid formats: 'png', 'svg', 'jpeg', 'pdf'
For instance,
>>> py.image.save_as(fig, filename='some-fig.svg')
where fig
is the figure object, either defined in the current Python/IPython session or retrieved by
>>> fig = py.get_figure('plotly-username', figure_id)
For more on sharing, you are invited to watch the following video:
from IPython.display import VimeoVideo
VimeoVideo('94003080', width='100%', height='350')
In this subsection, we start from a figure showcasing a great data, but lacking some style:
tls.embed('BrianVancil', 8, width=1100)
# (-) You can adjust the width the notebook cell with
# 'width' keyword argument.
Plotly's web GUI allows users to modify the appearance of the figure in real-time, that is without having to run, rerun and re-rerun code to get the desired results.
Together with py.get_figure()
, this method is also reproducible.
Watch the following video to see an example of how to transform a figure's apperance using the Workspace:
from IPython.display import YouTubeVideo
YouTubeVideo('YEM6QMSylfU', width='100%', height='350')
Note that some the UI elements in the above video are out-of-date; however, the graph editing would be done the same way on the current plot.ly/plot.
The resulting figure is:
tls.embed("https://plotly.com/~etpinard/329/", width=1100)
We hope you think that the above looks better than the original.
# (@) Retrieve figure object using the figure's URL
fig = py.get_figure("https://plotly.com/~etpinard/329")
Take a look at the 'name'
key of are two traces:
fig['data'][0]['name']
u'<b>Data from Freedman et al.</b><br><em>"FINAL RESULTS FROM THE HUBBLE SPACE TELESCOPE<br>KEY PROJECT TO MEASURE THE HUBBLE CONSTANT"</em>'
fig['data'][1]['name']
u'$\\text{Linear fit:} \\; v = (72.1 \\text{km/s/Mpc}) r + 65.7 \\text{km/s}$'
Plotly uses a subset of HTML tags to do things like newline (<br>
), bold (<b></b>
), italics (<i></i>
), hyperlinks (<a href='...'></a>
). Tags <em>
, <sup>
, <sub>
,
<span>
are also supported, making it easy to style text shown the plot's title, the axes' titles, annotations and anywhere else in a Plotly figure.
A few examples of colors set in the previous figure:
fig['data'][1]['line']['color']
u'rgb(204, 65, 37)'
fig['layout']['plot_bgcolor']
u'rgb(217, 217, 217)'
fig['layout']['xaxis']['gridcolor']
u'rgb(255, 255, 255)'
All Plotly colors are specified as strings (i.e. inside ''
or ""
in Python).
Although the above all are set in the red-green-blue color model (e.g. 'rgb(0,139,139)
), Plotly also accepts red-green-blue-alpha (e.g. 'rgba(0,139,139,0.5)'
), Hex (e.g. '#008b8b'
) and numerous pre-defined color names (e.g. 'blue'
, 'red'
, 'yellow'
, the full list can be found here here).
Later in section 3 on Bubble Charts, we will see that the 'color'
without the Marker
object of trace objects such as Scatter
and Bar
can be links to lists of colors.
Axis and legend style options are set through the 'xaxis'
(or 'xaxis1'
), 'yaxis'
(or 'yaxis1'
) and 'legend'
keys in the layout object. For instance,
print(fig['layout']['xaxis'].to_string())
XAxis( title=u'<b>Distance</b> \xa0[Mpc]', titlefont=Font( family=u'', size=0, color=u'' ), range=[0, 23.39607843137255], domain=[0, 1], type=u'linear', rangemode=u'tozero', autorange=True, showgrid=True, zeroline=False, showline=False, autotick=False, nticks=0, ticks=u'outside', showticklabels=True, tick0=0, dtick=2, ticklen=8, tickwidth=1.5, tickcolor=u'#444', tickangle=u'auto', tickfont=Font( family=u'', size=0, color=u'' ), exponentformat=u'B', showexponent=u'all', mirror=False, gridcolor=u'rgb(255, 255, 255)', gridwidth=1.5, zerolinecolor=u'#444', zerolinewidth=1, linecolor=u'#444', linewidth=1, anchor=u'y', overlaying=False, position=0 )
print(fig['layout']['yaxis'].to_string())
YAxis( title=u'<b>Radial velocity</b> \xa0[km/s]', titlefont=Font( family=u'', size=0, color=u'' ), range=[-221.13855421686748, 2148.1385542168673], domain=[0, 1], type=u'linear', rangemode=u'tozero', autorange=True, showgrid=True, zeroline=False, showline=False, autotick=True, nticks=0, ticks=u'outside', showticklabels=True, tick0=0, dtick=500, ticklen=8, tickwidth=1.5, tickcolor=u'#444', tickangle=u'auto', tickfont=Font( family=u'', size=0, color=u'' ), exponentformat=u'B', showexponent=u'all', mirror=False, gridcolor=u'rgb(255, 255, 255)', gridwidth=1.5, zerolinecolor=u'#444', zerolinewidth=1, linecolor=u'#444', linewidth=1, anchor=u'x', overlaying=False, position=0 )
print(fig['layout']['legend'].to_string())
Legend( x=0.010260457774269928, y=0.9551820728291316, traceorder=u'normal', font=Font( family=u'', size=0, color=u'' ), bgcolor=u'rgba(0, 0, 0, 0)', bordercolor=u'#444', borderwidth=0, xanchor=u'left', yanchor=u'top' )
The above three layout keys are linked to the XAxis
, YAxis
and Legend
graph objects respectively (which are all dictionary-like). You are invited to call help on each of them.
More closely, note that the legend position is assigned using normalized coordinates with respect to the axis frame. For example,
>>> Legend(x=0, y=1)
would place the legend at the top-left corner;
>>> Legend(x=0, y=0)
would place the legend at the bottom-left.
Modifying the size of a figure is done using three keys in the layout object. These are:
fig['layout']['autosize']
False
fig['layout']['width']
1110
fig['layout']['height']
525
where 'autosize'
must be set to False
for 'width'
and 'height'
to have an effect.
Both 'width'
and 'height'
are measured in pixels.
As an example, adjust the size of our previous figure while keeping the width-height ratio the same:
# Compute width-heigth ratio
ratio = float(fig['layout']['width']) / fig['layout']['height']
# (-) One of the components must be a float so that the division yields a float
new_width = 650 # set new width (in pixels)
new_height = int(new_width/ratio) # (!) set new height, must be an integer
# Update layout object
fig['layout'].update(
autosize=False, # allow custom size (set already, only for completeness here)
width=new_width, # link new width value
height=new_height, # link new height value
font=Font(size=7), # update global font size
titlefont=Font(size=12) # as well as the title font size
)
# (@) Send figure object to Plotly and show result in notebook
py.iplot(fig, filename='s1_hubble', height=new_height)
# (-) adjust height of output cell with 'height'
To sum up, styling a Plotly figure requires nothing more than filling in keys with values in appropriate graph objects. By the time you are done reading the User Guide, you will have seen in action (almost) all of Plotly's style options.
About Plotly
About the User Guide
Big thanks to
# CSS styling within IPython notebook
from IPython.display import display, HTML
display(HTML(open('../custom.css').read()))