Plotly.py 4.0 is here: Offline Only, Express First, Displayable Anywhere
Plotly.py is the library that powers graphs and maps for Dash. Version 4.0 of Plotly.py (also known as the plotly
module) is now available for download from PyPI. It includes some exciting new features and changes, including a switch to “offline” mode by default, the inclusion of Plotly Express as the recommended entry point into the library, and a new rendering framework compatible with not only Jupyter notebooks but other notebook systems such as Colab, Azure and Kaggle notebooks, as well as popular IDEs such as PyCharm, VSCode, Spyder and others.
To upgrade to the latest version, you can run pip install plotly==4.1.0
or conda install -c plotly plotly==4.1.0
. More details can be found in our Getting Started and Migrating to Version 4 guides. Read on for a detailed explanation of what has changed and why, or check out the changelog for an itemized list.
Offline Only
Prior versions of plotly
contained functionality for creating figures in both “online” and “offline” modes. In “online” mode, figures were uploaded to an instance of Plotly’s Chart Studio service and then displayed, whereas in “offline” mode figures were rendered locally. This duality has been a common source of confusion for several years, and so in version 4 we are making some important changes to help clear this up.
Starting with this version, the only supported mode of operation in the plotly
package is “offline” mode, which requires no internet connection, no account, no authentication tokens, and no payment of any kind. Support for “online” mode has been moved into a separately-installed package called chart-studio
.
Version 4 of
plotly
includes no code or functionality for uploading figures or data to any cloud service.
Express First
Earlier this year we released a standalone library called Plotly Express aimed at making it significantly easier and faster to create plotly
figures from tidy data—as easy as a single line of Python. Plotly Express was extremely well-received by the community and starting with version 4, plotly
now includes Plotly Express built-in (accessible as plotly.express
) and our documentation has been reworked to include examples using Plotly Express at the top of every applicable page, and to provide examples of how to customize figures generated with Plotly Express.
plotly.express
is toplotly
whatseaborn
is tomatplotlib
Please note that if you’ve already started using the standalone plotly_express
package, then you can upgrade to the latest version 0.4.0 right now, which uses plotly.express
under the hood.
Creating figures with Plotly Express is as easy as import plotly.express as px
and then passing your tidy Pandas data frame to the appropriate figure-generation function such as px.scatter()
or px.bar()
. Plotly Express supports a wide variety of charts, including otherwise verbose-to-create animations, facetted plots and multidimensional plots like Scatterplot Matrices (SPLOMs), Parallel Coordinates and Parallel Categories plots.
Displayable Anywhere
In addition to “offline” mode having become the default and only behavior, the plotly.offline
package has been reimplemented on top of a new extensible renderers framework which enables Plotly figures to be displayed not only in Jupyter notebooks, but just about anywhere. Out of the box, Plotly figures now have the ability to display themselves in the following contexts:
- JupyterLab & classic Jupyter notebook
- Other notebooks like Colab, nteract, Azure & Kaggle
- IDEs and CLIs like VSCode, PyCharm, QtConsole & Spyder
- Other contexts such as
sphinx-gallery
- Dash apps (with
dash_core_components.Graph()
) - Static raster and vector files (with
fig.write_image()
) - Standalone interactive HTML files (with
fig.write_html()
) - Embedded into any website (with
fig.to_json()
and Plotly.js)
Additional renderers can be added to the framework as new target contexts arise, and renderers can be combined to produce sophisticated context-dependent static-vs-interactive behaviors.
As you might notice in our documentation, although the previously-recommended style of plotly.offline.iplot(figure)
still works, the version 4 recommended way to imperatively display figures is to call figure.show()
, or you can simply let them display themselves by having a statement that returns a figure as the last statement in your notebook cell. Similarly, for exporting figure as HTML files we recommend moving away from plotly.offline.plot(figure)
towards the new figure.write_html()
method.
A New Default Theme
We introduced theming support in version 3.4. Since that release, we have iterated on the design of the built-in "plotly"
theme, and we made this theme the default in the initial release of Plotly Express. In version 4, we are making this theme the default for all figures created with plotly
. See the new theming and templates documentation page for information on configuring the default theme (including how to restore the old defaults!) and creating your own themes.
New Figure Update Methods
One of our goals for the integration of Plotly Express was to make it easy for users to start with Plotly Express for data exploration, and then tweak and refine the resulting figures with all of the customization support built into plotly
.
To this end, version 4 introduces a suite of new figure methods for updating figures after they have been constructed. These functions all return a reference to the calling figure, and are designed to support being chained together (which makes them handy to use with Dash in the middle of a layout
definition). We’ve also introduced “magic underscore notation” to make it easier and less verbose to update nested figure properties — this was a suggestion that came out of our Julia community! See the new Creating and Updating Figures page for full details, or check out this simple example of three equivalent ways to change legend orientation:
# the old way: one .update() method, deeply nested arguments
fig.update(layout=go.Layout(legend=dict(orientation="h"))# the new way: a dedicated update_layout method
fig.update_layout(legend=dict(orientation="h"))# the new new way: with magic underscores
fig.update_layout(legend_orientation="h")
Here’s an example of how to use the new update methods in a chain, with some magic underscores, to customize a figure created with Plotly Express by modifying the traces, axes and layout parameters:
import plotly.express as px
df = px.data.tips()(px.bar(df, x="size", y="tip", facet_row="time", facet_col="day",
color="sex", title="Tips by Payer Sex, Party Size, Day and Meal")
.update_traces(marker_line_width=0.5)
.update_yaxes(tickprefix="$")
.update_xaxes(type="category")
.update_layout(title_font_size=24) )
More Flexible Subplots
The make_subplots
function is used to create figures with custom subplot layouts, and it has received a lot of attention for version 4. In addition to fixing many bugs, make_subplots
now supports all subplot and trace types: 2D, 3D, polar, ternary, maps, pie charts, sunbursts, Sankey diagrams etc. See the subplots documentation page for more information. The make_subplots
function now also supports easy creation of dual-Y-axis plots.
The new figure update methods described above all support row
, col
, and secondary_y
keyword arguments to be able to target in which subplot or on which Y-axis a trace should be added, or which exact axis should be modified. In keeping with the theme of this release, the Plotly Express internals were ported to use the new make_subplots
functionality, so figures created with Plotly Express can be edited using these keyword arguments.
Here is an example that creates and populates a 2 x 2 subplot grid containing 4 different subplot types:
from plotly.subplots import make_subplotsfig = make_subplots(rows=2, cols=2,
specs=[[{"type": "xy"}, {"type": "polar"}],
[{"type": "domain"}, {"type": "scene"}]])fig.add_bar(row=1, col=1, y=[2, 3, 1], )
fig.add_pie(row=2, col=1, values=[2, 3, 1])
fig.add_barpolar(row=1, col=2, theta=[0, 45, 90], r=[2, 3, 1])
fig.add_scatter3d(row=2, col=2, x=[2, 3], y=[0, 0], z=[0.5, 1])
fig.update_layout(height=700, showlegend=False)
fig.show()
And here’s an example of a dual-Y-axis chart with matching data and tick label colors:
from plotly.subplots import make_subplotsfig = make_subplots(specs=[[{"secondary_y": True}]])fig.add_scatter(secondary_y=False, x=[1, 2, 3], y=[40, 50, 60],
marker_color="MediumSlateBlue", name="Pressure")fig.add_scatter(secondary_y=True, x=[2, 3, 4], y=[4, 5, 6],
marker_color="DarkOrange", name="Temperature")fig.update_yaxes(secondary_y=False,
tickfont_color="MediumSlateBlue", title="KPa")fig.update_yaxes(secondary_y=True,
tickfont_color="DarkOrange", title="° Celsius")fig.update_layout(title_text="A dual-Y-axis chart")
fig.show()
JupyterLab 1.0 Support
The @jupyterlab/plotly-extension
extension for rendering plotly
figures in JupyterLab has been replaced by a new jupyterlab-plotly
extension that will now be maintained and updated as a part of the Plotly.py project. Big thanks to the JupyterLab community for writing and maintain the original extension!
The new extension improves the load time of notebooks that contain lots of Plotly figures compared to the original extension. This is done by displaying saved figures as static images initially. These static images are then replaced with live Plotly.js figures when a user hovers over the plots.
The plotlywidget
JupyterLab extension for rendering FigureWidget figures has been updated to support JupyterLab 1.0.
A smaller package: 4.7MB down from 27.4MB
In order to reduce the size of the core plotly
distribution package, the bundled geographic shape files used by the create_choropleth
figure factory have been moved to a new optional plotly-geo
distribution package. This change reduces the size of the plotly
source package from 27.4 MB down to 4.7 MB.
Non-breaking: graph_objs
to graph_objects
The graph_objs
submodule is now also available as the easier-to-pronounce graph_objects
module. The graph_objs
submodule is still supported for backward compatibility, but going forward we recommend using the following import statement to access the graph object classes:
import plotly.graph_objects as go
Still and Always 100% Dash-Compatible
Every plotly
figure is still 100% Dash-compatible, and we hope that the new functionality will make it even easier to bring rich, compelling analytical applications into production. Here’s an example of a simple Dash app that uses some of plotly
's new features such as Plotly Express, chained update methods and magic underscores:
import dash
import dash_core_components as dcc
import plotly.express as pxdef dynamic_layout():
df = px.data.tips() # could be a database query instead!
return dcc.Graph(figure=px.bar(df, x="day", y="tip")
.update_yaxes(tickprefix="$")
.update_layout(legend_orientation="h"))app = dash.Dash(__name__)
app.layout = dynamic_layout
app.run_server()
Ready to get started?
To upgrade to the latest version, you can run pip install plotly==4.1.0
or conda install -c plotly plotly==4.1.0
. More details can be found in our Getting Started and Migrating to Version 4 guides or check out the changelog for an itemized list.
Thanks
Like all Plotly.py releases, this was a team effort that built on the strong foundations laid by the Plotly.js team. Special thanks to lead maintainer Jon Mease for his steady hand at the helm of the Plotly.py ship, to Nicolas Kruchten for Plotly Express, to Emmanuelle Gouillart for her work on documentation, and to Chris Parmer & Fernando Pérez for advice and support. Finally, we’d like to thank our user community for all of the pull requests, bug reports and suggestions!