The Figure Data Structure in Python
The structure of a figure - data, traces and layout explained.
New to Plotly?
Plotly is a free and open-source graphing library for Python. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.
Overview¶
The plotly
Python package exists to create, manipulate and render graphical figures (i.e. charts, plots, maps and diagrams) represented by data structures also referred to as figures. The rendering process uses the Plotly.js JavaScript library under the hood although Python developers using this module very rarely need to interact with the Javascript library directly, if ever. Figures can be represented in Python either as dicts or as instances of the plotly.graph_objects.Figure
class, and are serialized as text in JavaScript Object Notation (JSON) before being passed to Plotly.js.
Note: the recommended entry-point into the plotly package is the high-level plotly.express module, also known as Plotly Express, which consists of Python functions which return fully-populated
plotly.graph_objects.Figure
objects. This page exists to document the architecture of the data structure that these objects represent, for users who wish to understand more about how to customize them, or assemble them from otherplotly.graph_objects
components.
Viewing the underlying data structure for any plotly.graph_objects.Figure
object, including those returned by Plotly Express, can be done via print(fig)
or, in JupyterLab, with the special fig.show("json")
renderer. Figures also support fig.to_dict()
and fig.to_json()
methods. print()
ing the figure will result in the often-verbose layout.template
key being represented as ellipses '...'
for brevity.
import plotly.express as px
fig = px.line(x=["a","b","c"], y=[1,3,2], title="sample figure")
print(fig)
fig.show()
Accessing figure structures in Dash¶
Dash is the best way to build analytical apps in Python using Plotly figures. To run the app below, run pip install dash
, click "Download" to get the code and run python app.py
.
Get started with the official Dash docs and learn how to effortlessly style & deploy apps like this with Dash Enterprise.
Sign up for Dash Club → Free cheat sheets plus updates from Chris Parmer and Adam Schroeder delivered to your inbox every two months. Includes tips and tricks, community apps, and deep dives into the Dash architecture. Join now.
Figures as Trees of Attributes¶
Plotly.js supports inputs adhering to a well-defined schema, whose overall architecture is explained in this page and which is exhaustively documented in the Figure Reference (which is itself generated from a machine-readable JSON representation of the schema). Figures are represented as trees with named nodes called "attributes". The root node of the tree has three top-level attributes: data
, layout
and frames
(see below).
Attributes are referred to in text and in the Figure Reference by their full "path" i.e. the dot-delimited concatenation of their parents. For example "layout.width"
refers to the attribute whose key is "width"
inside a dict which is the value associated with a key "layout"
at the root of the figure. If one of the parents is a list rather than a dict, a set of brackets is inserted in the path when referring to the attribute in the abstract, e.g. "layout.annotations[].text"
. Finally, as explained below, the top-level "data" attribute defines a list of typed objects called "traces" with the schema dependent upon the type, and these attributes' paths are listed in the Figure Reference as "data[type=scatter].name"
.
The plotly.graph_objects
module contains an automatically-generated hierarchy of Python classes which represent non-leaf attributes in the figure schema and provide a Pythonic API for them. When manipulating a plotly.graph_objects.Figure
object, attributes can be set either directly using Python object attributes e.g. fig.layout.title.font.family="Open Sans"
or using update methods and "magic underscores" e.g. fig.update_layout(title_font_family="Open Sans")
When building a figure, it is not necessary to populate every attribute of every object. At render-time, the JavaScript layer will compute default values for each required unspecified attribute, depending upon the ones that are specified, as documented in the Figure Reference. An example of this would be layout.xaxis.range
, which may be specified explicitly, but if not will be computed based on the range of x
values for every trace linked to that axis. The JavaScript layer will ignore unknown attributes or malformed values, although the plotly.graph_objects
module provides Python-side validation for attribute values. Note also that if the layout.template
key is present (as it is by default) then default values will be drawn first from the contents of the template and only if missing from there will the JavaScript layer infer further defaults. The built-in template can be disabled by setting layout.template="none"
.
The Top-Level data
Attribute¶
The first of the three top-level attributes of a figure is data
, whose value must be a list of dicts referred to as "traces".
- Each trace has one of more than 40 possible types (see below for a list organized by subplot type, including e.g.
scatter
,bar
,pie
,surface
,choropleth
etc), and represents a set of related graphical marks in a figure. Each trace must have atype
attribute which defines the other allowable attributes. - Each trace is drawn on a single subplot whose type must be compatible with the trace's type, or is its own subplot (see below).
- Traces may have a single legend entry, with the exception of pie and funnelarea traces (see below).
- Certain trace types support continuous color, with an associated colorbar, which can be controlled by attributes either within the trace, or within the layout when using the coloraxis attribute.
The Top-Level layout
Attribute¶
The second of the three top-level attributes of a figure is layout
, whose value is referred to in text as "the layout" and must be a dict, containing attributes that control positioning and configuration of non-data-related parts of the figure such as:
- Dimensions and margins, which define the bounds of "paper coordinates" (see below)
- Figure-wide defaults: templates, fonts, colors, hover-label and modebar defaults
- Title and legend (positionable in container and/or paper coordinates)
- Color axes and associated color bars (positionable in paper coordinates)
- Subplots of various types on which can be drawn multiple traces and which are positioned in paper coordinates:
xaxis
,yaxis
,xaxis2
,yaxis3
etc: X and Y cartesian axes, the intersections of which are cartesian subplotsscene
,scene2
,scene3
etc: 3d scene subplotsternary
,ternary2
,ternary3
,polar
,polar2
,polar3
,geo
,geo2
,geo3
,map
,map2
,map3
,smith
,smith2
etc: ternary, polar, geo, map or smith subplots
- Non-data marks which can be positioned in paper coordinates, or in data coordinates linked to 2d cartesian subplots:
annotations
: textual annotations with or without arrowsshapes
: lines, rectangles, ellipses or open or closed pathsimages
: background or decorative images
- Controls which can be positioned in paper coordinates and which can trigger Plotly.js functions when interacted with by a user:
updatemenus
: single buttons, toggles and dropdown menussliders
: slider controls
The Top-Level frames
Attribute¶
The third of the three top-level attributes of a figure is frames
, whose value must be a list of dicts that define sequential frames in an animated plot. Each frame contains its own data attribute as well as other parameters. Animations are usually triggered and controlled via controls defined in layout.sliders and/or layout.updatemenus
The config
Object¶
At render-time, it is also possible to control certain figure behaviors which are not considered part of the figure proper i.e. the behavior of the "modebar" and how the figure relates to mouse actions like scrolling etc. The object that contains these options is called the config
, and has its own documentation page. It is exposed in Python as the config
keyword argument of the .show()
method on plotly.graph_objects.Figure
objects.
Positioning With Paper, Container Coordinates, or Axis Domain Coordinates¶
Various figure components configured within the layout of the figure support positioning attributes named x
or y
, whose values may be specified in "paper coordinates" (sometimes referred to as "plot fractions" or "normalized coordinates"). Examples include layout.xaxis.domain
or layout.legend.x
or layout.annotation[].x
.
Positioning in paper coordinates is not done in absolute pixel terms, but rather in terms relative to a coordinate system defined with an origin (0,0)
at (layout.margin.l, layout.margin.b)
and a point (1,1)
at (layout.width-layout.margin.r, layout.height-layout.margin.t)
(note: layout.margin
values are pixel values, as are layout.width
and layout.height
). Paper coordinate values less than 0 or greater than 1 are permitted, and refer to areas within the plot margins.
To position an object in "paper" coordinates, the corresponding axis reference
is set to "paper"
. For instance a shape's xref
attribute would be set to
"paper"
so that the x
value of the shape refers to its position in paper
coordinates.
Note that the contents of the layout.margin
attribute are by default computed based on the position and dimensions of certain items like the title or legend, and may be made dependent on the position and dimensions of tick labels as well when setting the layout.xaxis.automargin
attribute to True
. This has the effect of automatically increasing the margin values and therefore shrinking the physical area defined between the (0,0)
and (1,1)
points. Positioning certain items at paper coordinates less than 0 or greater than 1 will also trigger this behavior. The layout.width
and layout.height
, however, are taken as givens, so a figure will never grow or shrink based on its contents.
The figure title may be positioned using "container coordinates" which have (0,0)
and (1,1)
anchored at the bottom-left and top-right of the figure, respectively, and therefore are independent of the values of layout.margin.
Furthermore, shapes, annotations, and images can be placed relative to an axis's
domain so that, for instance, an x
value of 0.5
would place the object
halfway along the x-axis, regardless of the domain as specified in the
layout.xaxis.domain
attribute. This behavior can be specified by adding
' domain'
to the axis reference in the axis referencing attribute of the object.
For example, setting yref = 'y2 domain'
for a shape will refer to the length
and position of the axis named y2
.
2D Cartesian Trace Types and Subplots¶
The most commonly-used kind of subplot is a two-dimensional Cartesian subplot. Traces compatible with these subplots support xaxis
and yaxis
attributes whose values must refer to corresponding objects in the layout portion of the figure. For example, if xaxis="x"
, and yaxis="y"
(which is the default) then this trace is drawn on the subplot at the intersection of the axes configured under layout.xaxis
and layout.yaxis
, but if xaxis="x2"
and yaxis="y3"
then the trace is drawn at the intersection of the axes configured under layout.xaxis2
and layout.yaxis3
. Note that attributes such as layout.xaxis
and layout.xaxis2
etc do not have to be explicitly defined, in which case default values will be inferred. Multiple traces of different types can be drawn on the same subplot.
X- and Y-axes support the type
attribute, which enables them to represent continuous values (type="linear"
, type="log"
), temporal values (type="date"
) or categorical values (type="category"
, type="multicategory
). Axes can also be overlaid on top of one another to create dual-axis or multiple-axis charts. 2-d cartesian subplots lend themselves very well to creating "small multiples" figures, also known as facet or trellis plots.
The following trace types are compatible with 2d-cartesian subplots via the xaxis
and yaxis
attributes:
- scatter-like trace types:
scatter
andscattergl
, which can be used to draw scatter plots, line plots and curves, time-series plots, bubble charts, dot plots and filled areas and also support error bars bar
,funnel
,waterfall
: bar-like trace types which can also be used to draw timelines and Gantt chartshistogram
: an aggregating bar-like trace typebox
andviolin
: 1-dimensional distribution-like trace typeshistogram2d
andhistogram2dcontour
: 2-dimensional distribution-like density trace typesimage
,heatmap
andcontour
: matrix trace typesohlc
andcandlestick
: stock-like trace typescarpet
: a special trace type for building carpet plots, in that other traces can use as subplots (see below)splom
: multi-dimensional scatter plots which implicitly refer to many 2-d cartesian subplots at once.
3D, Polar, Ternary and Smith Trace Types and Subplots¶
Beyond 2D cartesian subplots, figures can include three-dimensional cartesian subplots, polar subplots, ternary subplots and smith subplots. The following trace types support attributes named scene
, polar
, smith
or ternary
, whose values must refer to corresponding objects in the layout portion of the figure i.e. ternary="ternary2"
etc. Note that attributes such as layout.scene
and layout.ternary2
etc do not have to be explicitly defined, in which case default values will be inferred. Multiple traces of a compatible type can be placed on the same subplot.
The following trace types are compatible with 3D subplots via the scene
attribute, which contains special camera controls:
scatter3d
, which can be used to draw individual markers, 3d bubble charts and lines and curvessurface
andmesh
: 3d surface trace typescone
andstreamtube
: 3d vector field trace typesvolume
andisosurface
: 3d volume trace types
The following trace types are compatible with polar subplots via the polar
attribute:
- scatter-like trace types:
scatterpolar
andscatterpolargl
, which can be used to draw individual markers, curves and filled areas (i.e. radar or spider charts) barpolar
: useful for wind roses and other polar bar charts
The following trace types are compatible with ternary subplots via the ternary
attribute:
scatterternary
, which can be used to draw individual markers, curves and filled areas
The following trace types are compatible with smith subplots via the smith
attribute:
scattersmith
, which can be used to draw individual markers, curves and filled areas
Map Trace Types and Subplots¶
Figures can include two different types of map subplots: geo subplots for outline maps and tile-based maps. The following trace types support attributes named geo
or map
, whose values must refer to corresponding objects in the layout i.e. geo="geo2"
etc. Note that attributes such as layout.geo2
and layout.map
etc do not have to be explicitly defined, in which case default values will be inferred. Multiple traces of a compatible type can be placed on the same subplot.
The following trace types are compatible with geo subplots via the geo
attribute:
scattergeo
, which can be used to draw individual markers, line and curves and filled areas on outline mapschoropleth
: colored polygons on outline maps
The following trace types are compatible with tile map subplots via the map
attribute:
scattermap
, which can be used to draw individual markers, lines and curves and filled areas on tile mapschoroplethmap
: colored polygons on tile mapsdensitymap
: density heatmaps on tile maps
Traces Which Are Their Own Subplots¶
Certain trace types cannot share subplots, and hence have no attribute to map to a corresponding subplot in the layout. Instead, these traces are their own subplot and support a domain
attribute for position, which enables the trace to be positioned in paper coordinates (see below). With the exception of pie
and funnelarea
, such traces also do not support legends (see below)
The following trace types are their own subplots and support a domain attribute:
pie
andfunnelarea
: one-level part-to-whole relationships with legend itemssunburst
andtreemap
: hierarchical multi-level part-to-whole relationshipsparcoords
andparcats
: continuous and categorical multidimensional figures with parallel coordinates and parallel setssankey
: flow diagramstable
: text-based tablesindicator
: big numbers, gauges, and bullet charts
Carpet Trace Types and Subplots¶
Certain trace types use traces of type carpet
as a subplot. These support a carpet
attribute whose value must match the value of the carpet
attribute of the carpet
trace they are to be drawn on. Multiple compatible traces can be placed on the same carpet
trace.
The following trace types are compatible with carpet
trace subplots via the carpet
attribute:
scattercarpet
, which can be used to draw individual markers, curves and filled areascontourcarpet
Trace Types, Legends and Color Bars¶
Traces of most types can be optionally associated with a single legend item in the legend. Whether or not a given trace appears in the legend is controlled via the showlegend
attribute. Traces which are their own subplots (see above) do not support this, with the exception of traces of type pie
and funnelarea
for which every distinct color represented in the trace gets a separate legend item. Users may show or hide traces by clicking or double-clicking on their associated legend item. Traces that support legend items also support the legendgroup
attribute, and all traces with the same legend group are treated the same way during click/double-click interactions.
The fact that legend items are linked to traces means that when using discrete color, a figure must have one trace per color in order to get a meaningful legend. Plotly Express has robust support for discrete color to make this easy.
Traces which support continuous color can also be associated with color axes in the layout via the coloraxis
attribute. Multiple traces can be linked to the same color axis. Color axes have a legend-like component called color bars. Alternatively, color axes can be configured within the trace itself.
What About Dash?¶
Dash is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.
Learn about how to install Dash at https://dash.plot.ly/installation.
Everywhere in this page that you see fig.show()
, you can display the same figure in a Dash application by passing it to the figure
argument of the Graph
component from the built-in dash_core_components
package like this:
import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure() # or any Plotly Express function e.g. px.bar(...)
# fig.add_trace( ... )
# fig.update_layout( ... )
from dash import Dash, dcc, html
app = Dash()
app.layout = html.Div([
dcc.Graph(figure=fig)
])
app.run_server(debug=True, use_reloader=False) # Turn off reloader if inside Jupyter