We are happy to announce that Plotly.py 5.15.0 is now available for download via pip
and conda
! For up-to-date installation and upgrading instructions, please see our Getting Started documentation page and if you run into trouble, check out our Troubleshooting Guide.
To start working with Plotly v5.15.0, using pip:
- pip install plotly==5.15.0
Or with conda:
- conda install -c plotly plotly=5.15.0
This is a combined announcement for Plotly.py versions 5.14.0 and 5.15.0 and highlights some of the main updates. See the full changelog for more info.
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()
This feature was anonymously sponsored: thank you to our sponsor!
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()
Thanks to the Volkswagen Center of Excellence for Battery Systems for sponsoring development!
Texttemplate on Shapes
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",
]
}
)
Thanks to the Volkswagen Center of Excellence for Battery Systems for sponsoring development!
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()
This feature was anonymously sponsored: thank you to our sponsor
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()
Thanks to Gamma Technologies for sponsoring the related development.
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.
Powered by Plotly.js 2.24.1
Plotly.py 5.15.0 is built with Plotly.js 2.24.1. The examples above, except the pattern examples, will work with Dash 2.10, which uses Plotly.js 2.23.2. The patterns feature on pie, funnelarea, sunburst, icicle and treemap traces will be available in Dash 2.11.
Get it now!
To sum up: Plotly.py 5.15.0 is out and if you’re excited about any of the above features, head on over to our Getting Started documentation page for full installation instructions!
In Case You Missed It: Previous Announcements
-
Plotly.py 5.13, 5.12, 5.11, 5.10, and 5.9
- Grouped scatter support
- New marker and angle attributes
- Persistent selections
- Sankey links with arrows
- Rounded corners on treemaps
- Map bounds and clusters
-
Plotly.py 5.8
- Better Autocompletions with Type Hints
- Minor Ticks
-
Plotly.py 5.7
- Patterns on areas
- Tick label steps (Plotly 5.6)
- Text on histograms and heatmaps (Plotly 5.5)
- Smith charts (Plotly 5.4)
- Legend group click (Plotly 5.3)
-
Plotly.py 5.2 and 5.1
- Trendlines
- ECDF Plots
- Markers on Lines
- Sharper WebGL
- Legend Group Titles
-
Plotly.py 5.0
- A combined, federated JupyterLab Extension
- Bar Chart Patterns (aka Hatching or Textures)
- Icicle and Flame Charts
- Explicit Legend-Item Ordering
- Faster JSON serialization with
orjson