Update : version 2.13.0 has been released since this was posted.
We’re excited to announce that Dash 2.11.0 has been released
pip install dash==2.11.0
Official Changelog Dash v2.11.0
Highlights
Dash in Jupyter Environments
Dash 2.11 and later supports running Dash apps in classic Jupyter Notebooks and in JupyterLab without the need to update the code or use the additional JupyterDash
library. If you are using an earlier version of Dash, you can run Dash apps in a notebook using JupyterDash.
Display Modes
There are 4 display modes. When you run an app in a notebook cell, it displays inline by default.
Inline Mode -
Code for sample app:
from dash import Dash, html, dash_table, dcc, callback, Output, Input
import pandas as pd
import plotly.express as px
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')
app = Dash(__name__)
# App layout
app.layout = html.Div([
html.Div(children='My Dash App'),
html.Hr(),
dcc.RadioItems(options=['pop', 'lifeExp', 'gdpPercap'], value='lifeExp', id='my-final-radio-item-example', inline=True),
dash_table.DataTable(data=df.to_dict('records'), page_size=6),
dcc.Graph(figure={}, id='my-final-graph-example')
])
@callback(
Output(component_id='my-final-graph-example', component_property='figure'),
Input(component_id='my-final-radio-item-example', component_property='value')
)
def update_graph(col_chosen):
fig = px.histogram(df, x='continent', y=col_chosen, histfunc='avg')
return fig
# Run the app
if __name__ == '__main__':
app.run()
External Mode -
By using external
mode, you can configure it to display a link that allows you to view the app.
app.run(jupyter_mode="external")
Tab mode -
Use tab
mode to automatically open the app in a new browser tab:
app.run(jupyter_mode="tab")
Jupyterlab mode -
In jupyterlab
mode, the notebook displays the app in a separate tab in JupyterLab.
app.run(jupyter_mode="jupyterlab")
JupyterLab version 3 is required to run a Dash app in a Jupyterlab mode.
Please note that Multi-page apps using Dash Pages are not supported in notebooks.
You can read more about Dash in Jupyter customization features and troubleshooting in the docs.
Flask and Werkzeug upper bound version
Since day 1, Dash has used Flask as its web server. We’re incredibly grateful to have this excellent package to build on, and grateful for all the hard work of the folks maintaining it! And in the spirit of openness and our place as just one library of many in the Python ecosystem, we’ve always required only a minimum version for Flask, so that if you integrate Dash with a larger Flask app you can use whatever version of Flask you want, whatever version your host app already uses.
Unfortunately, this has caused us problems: a new version of Flask (or its matched WSGI utility Werkzeug) changes something we were using, either in Dash itself or in one of the many add-on libraries, either in the open-source world or in our enterprise offerings, and apps that were previously working suddenly fail.
So in order to make all of those standalone Dash apps more robust and maintainable, we’ve decided to lock Flask and Werkzeug to versions that we know work with Dash and all the other packages maintained by Plotly.
Starting from Dash v2.10.2, we’ve set Flask and Werkzeug version upper bound to <2.3
.
If you specifically ask for the latest Flask (any newly-released version of Flask that we haven’t yet approved) alongside Dash with no version, you’ll get pushed back to
dash==2.9.3
, the last version without an upper bound on Flask. To avoid this and still pin a Flask version, we recommend setting a minimum Dash version at least 2.10, so that instead of getting the older Dash you’ll be alerted to the conflict:
> pip install "dash>=2.10" "Flask>=2.3"
Collecting dash>=2.10
Downloading dash-2.10.0-py3-none-any.whl (10.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.3/10.3 MB 17.3 MB/s eta 0:00:00
Collecting Flask>=2.3
Using cached Flask-2.3.2-py3-none-any.whl (96 kB)
INFO: pip is looking at multiple versions of dash to determine which version is compatible with other requirements. This could take a while.
ERROR: Cannot install Flask>=2.3 and dash==2.10.0 because these package versions have conflicting dependencies.
The conflict is caused by:
The user requested Flask>=2.3
dash 2.10.0 depends on Flask<=2.2.3 and >=1.0.4
To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip attempt to solve the dependency conflict
Plotly.py & dcc.Graph Updates
Updated Plotly.js to from version 2.20.0 to version 2.24.2.
The version of Plotly.js that is built in here is the same one that is bundled with the recently released Plotly.py 5.15.0, so we recommend that you upgrade to Plotly 5.15.0 to get the full benefit of all of these libraries working together.
pip install plotly==5.15.0
Official Changelog Plotly v5.15.0
There have been many developments in the world of Plotly.py and dcc.Graph recently. To highlight just a few:
dcc.Graph - Label Aliases
If you’ve ever wanted to change the labels displayed on axes without changing the underlying data, you can now do this with label aliases . In the following heatmap, the underlying data has country codes in the LOCATION column. Using labelalias
on the y axis, we swap out the codes (e.g. “FRA”) for the full country names (e.g. “France”). It also works on colorbars. Here we’ve also made a small adjustment to the colorbar text, swapping out the “10” value on the colorbar for “10%”.
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/add-commutes-data/unemployment_data_europe_oecd.csv"
)
filtered_df = df[df["LOCATION"].isin(df["LOCATION"].unique()[:7])]
fig = go.Figure(
data=go.Heatmap(
x=filtered_df["TIME"],
y=filtered_df["LOCATION"],
z=filtered_df["Value"],
colorscale="Viridis_r",
colorbar=dict(labelalias={10: "10%"}),
),
layout=go.Layout(title="% Unemployment Rate by Country"),
)
fig.update_yaxes(
title="Country",
labelalias=dict(
DEU="Germany",
FRA="France",
FIN="Finland",
DNK="Denmark",
CZE="Czech Republic",
BEL="Belgium",
AUT="Austria",
),
)
fig.show()
Labels on Shapes
Plotly.py now supports adding labels to shapes. In the following example, we add a rectangle and line shape to a graph and then add a label to both. Each label is customized with a textposition
and font
size
. See the documentation for more examples.
import plotly.express as px
df = px.data.stocks(indexed=True)
fig = px.line(df)
fig.add_shape(
type="rect",
x0="2018-09-24",
y0=0,
x1="2018-12-18",
y1=3,
line_width=0,
label=dict(text="Decline", textposition="top center", font=dict(size=20)),
fillcolor="lightgreen",
opacity=0.25,
)
fig.add_shape(
type="line",
x0=min(df.index),
y0=1,
x1=max(df.index),
y1=1,
line_width=2,
line_dash="dot",
label=dict(
text="Jan 1 2018 Baseline",
textposition="end",
font=dict(size=20),
yanchor="top",
),
)
fig.show()
Texttemplate on Shapes and Shape Formulas
The text on shapes can now dynamically update based on properties of the shape with texttemplate. In the texttemplate
you have access to raw variables based on the shape definition (x0
, x1
, y0, and
y1) as well as some calculated variables, including width
, height
, length
, and slope
.
In the following example, we use the calculated variable dy
(which is y1
-y0
) in the first subplot to show the change on the y axis from one point on the graph to another. On the second subplot, we use another calculated variable, dx
(which is x1
-x0
), to show the change on the x axis. Dates axes return values in milliseconds, so we divide by 86400000 to get the number of days.
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/add-commutes-data/unemployment_data_europe_oecd.csv"
)
filtered_df = df[df["LOCATION"].isin(df["LOCATION"].unique()[8:20])]
filtered_one_country = filtered_df.loc[df['LOCATION']=='IRL']
fig = make_subplots(rows=1, cols=2)
fig.add_trace(
go.Scatter(x=filtered_one_country["TIME"], y=filtered_one_country["Value"],
), row=1, col=1)
fig.add_trace(
go.Heatmap(
x=filtered_df["TIME"],
y=filtered_df["LOCATION"],
z=filtered_df["Value"],
colorscale="Viridis_r",
),
row=1, col=2
)
fig.add_shape(
type="line",
xref="x2",
x0="2009-01-01",
y0=4.5,
x1="2015-06-01",
y1=4.5,
line_width=4,
label=dict(texttemplate="Days above 10%: %{dx/86400000}", font=dict(size=12, color="white")),
fillcolor="black",
)
fig.add_shape(
type="line",
xref="x",
x0="2012-09-01",
y0=16.1,
x1="2020-04-01",
y1=5,
line_width=4,
label=dict(texttemplate="Change from peak: %{dy:.2f}", textposition="top center", font=dict(size=10)),
fillcolor="grey",
)
fig.update_layout(title_text="Subplots with Texttemplate")
fig.show()
It also works on new shapes. In the following example, we enable drawing lines on the figure (in the config
of fig.show
, we add drawline
to modeBarButtonsToAdd
, which adds the drawline button to the modebar), and define a texttemplate
for shapes that shows the calculated variable dy
.
For more detail on the calculated variables available, see the variables in shape label text section in the docs .
import plotly.graph_objects as go
from plotly import data
df = data.stocks()
fig = go.Figure(
data=go.Scatter(
x=df.date,
y=df.GOOG,
line=dict(color="#4285F4"),
),
layout=go.Layout(
yaxis=dict(title="Price in USD"),
newshape=dict(
label=dict(texttemplate="Change: %{dy:.2f}"),
),
plot_bgcolor="#FAF1F1",
title={
"text": "Google Share Price 2018/2019",
"font": {"color": "#333333", "size": 20},
},
),
)
fig.show(
config={
"modeBarButtonsToAdd": [
"drawline",
]
}
)
Multiple Legends
Plotly.py now supports multiple legends. In this example, we assign “legend2” to the two traces on the second subplot by setting legend="legend2"
. We then position the first legend at "0.4"
on the x axis, to move it beside the first subplot. For more on the options available for configuring legends, see the layout reference docs.
import plotly.graph_objects as go
from plotly import data
from plotly.subplots import make_subplots
df = data.gapminder()
subplot_1_countries = ["Germany", "France", "United Kingdom"]
subplot_2_countries = ["United States", "Canada"]
fig = make_subplots(
rows=1,
cols=2,
horizontal_spacing=0.2,
shared_yaxes=True,
)
for country in subplot_1_countries:
filtered_data = df.loc[(df.country.isin([country]))]
fig.add_trace(
go.Scatter(x=filtered_data.year, y=filtered_data.lifeExp, name=country),
row=1,
col=1,
)
for country in subplot_2_countries:
filtered_data = df.loc[(df.country.isin([country]))]
fig.add_trace(
go.Scatter(
x=filtered_data.year,
y=filtered_data.lifeExp,
name=country,
legend="legend2",
),
row=1,
col=2,
)
fig.update_layout(
title="Life Expectancy Subplots with Multiple Legends",
plot_bgcolor="#E6F1F6",
legend={
"x": 0.4,
},
)
fig.show()
To learn how to add multiple legends to a single plot, see the adding-multiple-legends docs.
Container Reference Support for Colorbar and Legends
Plotly.py 5.15.0 adds xref
and yref
to legend
and colorbar
to support container referenced positioning. To use container references, set xref
and/or yref
to “container”. For more on positioning and the different types of coordinates see the figure structure page in the docs .
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/add-commutes-data/commute_modes_2021_census.csv"
)
fig = go.Figure()
for mode in df["Mode"]:
legend_item_visibility = "legendonly" if mode == "Car, truck or van" else True
fig.add_trace(
go.Bar(
x=df.columns[1:],
y=df.loc[df["Mode"] == mode, df.columns[1:]].values[0],
name=mode,
visible=legend_item_visibility,
)
)
fig.update_layout(
title="Commute by mode of transport as % of all commutes",
legend={
"xref": "container",
"yref": "container",
"y": 0.5,
"bgcolor": "Gold",
},
)
fig.show()
Patterns on More Graph Types
Patterns were already available on a number of graph types, but are now also available on pie, funnelarea, sunburst, icicle and treemap traces. Patterns are useful if you want to double-encode variables to improve accessibility for visually-impaired end-users, encode an additional variable beyond just using color, or make charts that are easier to print in black and white.
Here’s an example of using patterns on multiple pie charts. We add the pattern when creating each trace by setting the pattern
on the marker
:
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from plotly import data
import pandas as pd
df = data.election()[:3]
fig = make_subplots(
rows=1,
cols=3,
subplot_titles=df["district"],
specs=[[{"type": "domain"}, {"type": "domain"}, {"type": "domain"}]],
)
for i, row in df.iterrows():
labels = ["Coderre", "Bergeron", "Joly"]
values = [row["Coderre"], row["Bergeron"], row["Joly"]]
fig.add_trace(
go.Pie(
labels=labels,
values=values,
marker=dict(
colors=["Gold", "MediumTurquoise", "LightGreen"],
pattern=dict(
shape=[
"-",
"/",
".",
],
solidity=0.9,
),
),
name="",
),
row=1,
col=1 + i,
)
fig.show()
See additional examples for sunburst , funnelarea, icicle, and treemaps .
Notable Bug Fixes, Additions & Minor Changes
Dash:
- #2530 Merge JupyterDash repository with Dash.
- Add
jupyter_mode
argument toapp.run
, defaults toinline
and configurable viajupyter_dash.default_mode
. - Add prefixed arguments from
JupyterDash
toapp.run
:jupyter_width
,jupyter_height
,jupyter_server_url
.
- Add
- Set an upper bound to Flask and Werkzeug versions at
<2.3
because we expect the Dash ecosystem to be incompatible with the next minor release of Flask (this excludes the current latest Flask release 2.3.x). We will raise the upper bound to<2.4
after we fix incompatibilities elsewhere in the Dash ecosystem. - #2538 Update JS dependencies in dcc, html, dash-table, dash-renderer, and dash
- #2540 Add
include_pages_meta=True
toDash
constructor, and fix a security issue in pages meta tags #2536. - #2555 Fix browser back button when removing one of multiple location components from layout, fix #1312
- #2565 Fix sorting for > 10 pages, fix #2564
- #2545 Fix typescript objectOf generation.
- #2548 Fix component as props callback triggering other callbacks not in response, fix #2487.
- #2508 Fix error message, when callback output has different length than spec
- #2207 Fix object of components support.
- #2500 Passing customdata by click for scattermapbox, fix #2493
- #2513 Raise error when iterating over patch objects, fix #2512
- #2489 Fix location change event handling when
Location
objects are removed from the layout. Event handlers would not be removed and eventually change props of a random DOM element, fix #1346 - #2498 Fix error when caching callbacks which return
Patch
objects by makingPatch
objects picklable - #2491 Fix clientside inline function name not found, fix #2488
Plotly:
- #2474 Update plotly js to 2.24.2 from 2.23.2
- #2533 and #2538 Update Plotly.js to v2.23.2 from v2.20.0.
- Feature release 2.23.0 adds legend/colorbar xref/yref.
- Feature release 2.22.0 adds
legend
references to traces. - Feature release 2.21.0 adds
label.texttemplate
to parametric shapes. - Patch releases 2.23.1 and 2.23.2 fix heatmap rendering on iOS and Safari when zsmooth is set to false and shape text when drawing a new shape.
Previous Releases
Dash 2.9.2 Released - Partial Property Updates, Duplicate Outputs, dcc.Geolocation, Scatter Group Attributes & More
Dash 2.7 Released - Directional Arrows Feature, Map Bounds, and DataTable Filter Text
Dash 2.6 Released - Background Callbacks, Unit Testing, Persistent Selections, Dropdown Features
Dash 2.5 Released - Easier Multi-Page Apps, Component Properties
Dash 2.4 Released - Improved Callback Context, Clientside Promises, Typescript Components, Minor Ticks
Dash 2.3.0 Release - MathJax and fillpattern option in scatter trace
Dash 2.2.0 Release - Adds ticklabelstep
to axes, and added dash.get_asset_url
Dash 2.1.0 Release - Autogenerated IDs and reärranged keyword arguments in Dash components