diff --git a/.circleci/config.yml b/.circleci/config.yml index 2973d204991..e16e0e9fd7b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -374,7 +374,7 @@ jobs: full_build: docker: - - image: continuumio/miniconda3 + - image: continuumio/miniconda3:24.3.0-0 environment: LANG: en_US.UTF-8 resource_class: large @@ -448,7 +448,7 @@ jobs: docker: # specify the version you desire here # use `-browsers` prefix for selenium tests, for example, `3.9-browsers` - - image: cimg/python:3.9-browsers + - image: cimg/python:3.10-browsers steps: - add_ssh_keys: @@ -599,3 +599,4 @@ workflows: - python_38_orca - python_39_percy - build-doc + diff --git a/CHANGELOG.md b/CHANGELOG.md index adad2f3cbae..20c880922af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [5.23.0] - 2024-07-23 + +### Updated +- Updated Plotly.js from version 2.32.0 to version 2.34.0. See the [plotly.js CHANGELOG](https://github.com/plotly/plotly.js/blob/master/CHANGELOG.md#2340----2024-07-18) for more information. These changes are reflected in the auto-generated `plotly.graph_objects` module. Notable changes include: + - Add `subtitle` attribute to `layout.title` to enable adding subtitles to plots [[#7012](https://github.com/plotly/plotly.js/pull/7012)] + - Introduce "u" and "s" pseudo html tags to add partial underline and strike-through styles to SVG text elements [[#7043](https://github.com/plotly/plotly.js/pull/7043)] + - Add geometric mean functionality and 'geometric mean ascending' + 'geometric mean descending' to `category_order` on cartesian axes [[#6223](https://github.com/plotly/plotly.js/pull/6223)], + with thanks to @acxz and @prabhathc for the contribution! + - Add axis property `ticklabelindex` for drawing the label for each minor tick n positions away from a major tick, + with thanks to @my-tien for the contribution! [[#7036](https://github.com/plotly/plotly.js/pull/7036)] + - Add property `ticklabelstandoff` and `ticklabelshift` to cartesian axes to adjust positioning of tick labels, + with thanks to @my-tien for the contribution! [[#7006](https://github.com/plotly/plotly.js/pull/7006)] + - Add `x0shift`, `x1shift`, `y0shift`, `y1shift` to shapes to add control over positioning of shape vertices on (multi-)category axes, + with thanks to @my-tien for the contribution! [[#7005](https://github.com/plotly/plotly.js/pull/7005)] +- Specify Python version 3.8-3.11 for development virtual environments and pin `pytest` at version 8.1.1 to match. +- Update `IntegerValidator` to handle `extras` option to allow supporting additional keyword values. For example, 'bold' and 'normal' as well as integers as used in font weights [#4612]. + + ## [5.22.0] - 2024-05-01 ### Updated diff --git a/README.md b/README.md index d12f427e06e..d8039732b70 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,16 @@ +
nonnegative
, tozero
, and normal
Rangemode
-When you don't specify a range, autorange is used. It's also used for bounds set to `None` when providing a `range`.
+When you don't specify a range, autorange is used. It's also used for bounds set to `None` when providing a `range`.
The axis auto-range calculation logic can be configured using the `rangemode` axis parameter.
@@ -898,7 +958,7 @@ fig.update_xaxes(autorangeoptions=dict(maxallowed=5))
fig.show()
```
-##### Clip Minimum and Maximum
+##### Clip Minimum and Maximum
You can also clip an axis range at a specific maximum or minimum value with `autorangeoptions.clipmax` and `autorangeoptions.clipmin`.
@@ -916,7 +976,7 @@ fig.show()
##### Specify Values to be Included
-Use `autorangeoptions.include` to specify a value that should always be included within the calculated autorange. In this example, we specify that for the autorange calculated on the x-axis, 5 should be included.
+Use `autorangeoptions.include` to specify a value that should always be included within the calculated autorange. In this example, we specify that for the autorange calculated on the x-axis, 5 should be included.
```python
import plotly.express as px
diff --git a/doc/python/box-plots.md b/doc/python/box-plots.md
index a22762c0750..dbaca729096 100644
--- a/doc/python/box-plots.md
+++ b/doc/python/box-plots.md
@@ -458,12 +458,12 @@ x_data = ['Carmelo Anthony', 'Dwyane Wade',
N = 50
-y0 = (10 * np.random.randn(N) + 30).astype(np.int)
-y1 = (13 * np.random.randn(N) + 38).astype(np.int)
-y2 = (11 * np.random.randn(N) + 33).astype(np.int)
-y3 = (9 * np.random.randn(N) + 36).astype(np.int)
-y4 = (15 * np.random.randn(N) + 31).astype(np.int)
-y5 = (12 * np.random.randn(N) + 40).astype(np.int)
+y0 = (10 * np.random.randn(N) + 30).astype(int)
+y1 = (13 * np.random.randn(N) + 38).astype(int)
+y2 = (11 * np.random.randn(N) + 33).astype(int)
+y3 = (9 * np.random.randn(N) + 36).astype(int)
+y4 = (15 * np.random.randn(N) + 31).astype(int)
+y5 = (12 * np.random.randn(N) + 40).astype(int)
y_data = [y0, y1, y2, y3, y4, y5]
diff --git a/doc/python/configuration-options.md b/doc/python/configuration-options.md
index 52dcc8764ec..1b884b84786 100644
--- a/doc/python/configuration-options.md
+++ b/doc/python/configuration-options.md
@@ -252,7 +252,7 @@ fig.show()
*New in v4.7*
-Some modebar buttons of Cartesian plots are optional and have to be added explicitly, using the `modeBarButtonsToAdd` config attribute. These buttons are used for drawing or erasing shapes. See [the tutorial on shapes and shape drawing](python/shapes#drawing-shapes-on-cartesian-plots) for more details.
+Some modebar buttons of Cartesian plots are optional and have to be added explicitly, using the `modeBarButtonsToAdd` config attribute. These buttons are used for drawing or erasing shapes. See [the tutorial on shapes and shape drawing](/python/shapes#drawing-shapes-with-a-mouse-on-cartesian-plots) for more details.
```python
import plotly.express as px
diff --git a/doc/python/figure-labels.md b/doc/python/figure-labels.md
index 0e00f5e575b..f687fcda1de 100644
--- a/doc/python/figure-labels.md
+++ b/doc/python/figure-labels.md
@@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.3'
- jupytext_version: 1.16.1
+ jupytext_version: 1.16.3
kernelspec:
display_name: Python 3 (ipykernel)
language: python
@@ -20,7 +20,7 @@ jupyter:
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
- version: 3.10.11
+ version: 3.10.14
plotly:
description: How to set the global font, title, legend-entries, and axis-titles
in python.
@@ -236,5 +236,44 @@ fig.update_layout(
fig.show()
```
+### Adding a Plot Subtitle
+
+*New in 5.23*
+
+Add a subtitle to a plot with `layout.title.subtitle`. In the following example, we set the subtitle's `text`, and configure the `font` `color` and `size`. By default, if you don't set a font size for the subtitle, it will be `0.7` of the `title` font size.
+
+```python
+import plotly.graph_objects as go
+from plotly import data
+
+df = data.gapminder().query("continent == 'Europe' and (year == 1952 or year == 2002)")
+
+df_pivot = df.pivot(index="country", columns="year", values="lifeExp")
+
+fig = go.Figure(
+ [
+ go.Bar(
+ x=df_pivot.index, y=df_pivot[1952], name="1952", marker_color="IndianRed"
+ ),
+ go.Bar(
+ x=df_pivot.index, y=df_pivot[2002], name="2002", marker_color="LightSalmon"
+ ),
+ ],
+ layout=dict(
+ title=dict(
+ text="Life Expectancy",
+ subtitle=dict(
+ text="Life expectancy by European country in 1952 and in 2002",
+ font=dict(color="gray", size=13),
+ ),
+ )
+ ),
+)
+
+
+fig.show()
+
+```
+
#### Reference
See https://plotly.com/python/reference/layout/ for more information!
diff --git a/doc/python/getting-started.md b/doc/python/getting-started.md
index 8276a535c4f..3827de29c4f 100644
--- a/doc/python/getting-started.md
+++ b/doc/python/getting-started.md
@@ -58,13 +58,13 @@ We also encourage you to join the [Plotly Community Forum](http://community.plot
`plotly` may be installed using `pip`:
```
-$ pip install plotly==5.21.0
+$ pip install plotly==5.22.0
```
or `conda`:
```
-$ conda install -c plotly plotly=5.21.0
+$ conda install -c plotly plotly=5.22.0
```
This package contains everything you need to write figures to standalone HTML files.
@@ -152,7 +152,7 @@ The instructions above apply to JupyterLab 3.x. **For JupyterLab 2 or earlier**,
```
# JupyterLab 2.x renderer support
-jupyter labextension install jupyterlab-plotly@5.21.0 @jupyter-widgets/jupyterlab-manager
+jupyter labextension install jupyterlab-plotly@5.22.0 @jupyter-widgets/jupyterlab-manager
```
Please check out our [Troubleshooting guide](/python/troubleshooting/) if you run into any problems with JupyterLab, particularly if you are using multiple python environments inside Jupyter.
diff --git a/doc/python/icicle-charts.md b/doc/python/icicle-charts.md
index 540f9f7e82c..38569a7ea03 100644
--- a/doc/python/icicle-charts.md
+++ b/doc/python/icicle-charts.md
@@ -305,7 +305,7 @@ def build_hierarchical_dataframe(df, levels, value_column, color_columns=None):
Levels are given starting from the bottom to the top of the hierarchy,
ie the last level corresponds to the root.
"""
- df_all_trees = pd.DataFrame(columns=['id', 'parent', 'value', 'color'])
+ df_list = []
for i, level in enumerate(levels):
df_tree = pd.DataFrame(columns=['id', 'parent', 'value', 'color'])
dfg = df.groupby(levels[i:]).sum()
@@ -317,11 +317,12 @@ def build_hierarchical_dataframe(df, levels, value_column, color_columns=None):
df_tree['parent'] = 'total'
df_tree['value'] = dfg[value_column]
df_tree['color'] = dfg[color_columns[0]] / dfg[color_columns[1]]
- df_all_trees = df_all_trees.append(df_tree, ignore_index=True)
+ df_list.append(df_tree)
total = pd.Series(dict(id='total', parent='',
value=df[value_column].sum(),
- color=df[color_columns[0]].sum() / df[color_columns[1]].sum()))
- df_all_trees = df_all_trees.append(total, ignore_index=True)
+ color=df[color_columns[0]].sum() / df[color_columns[1]].sum()), name=0)
+ df_list.append(total)
+ df_all_trees = pd.concat(df_list, ignore_index=True)
return df_all_trees
diff --git a/doc/python/mixed-subplots.md b/doc/python/mixed-subplots.md
index 13737b5f6d1..24ee5123beb 100644
--- a/doc/python/mixed-subplots.md
+++ b/doc/python/mixed-subplots.md
@@ -55,8 +55,8 @@ df = pd.read_csv(
)
# frequency of Country
-freq = df
-freq = freq.Country.value_counts().reset_index().rename(columns={"index": "x"})
+freq = df['Country'].value_counts().reset_index()
+freq.columns = ['x', 'Country']
# read in 3d volcano surface data
df_v = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/volcano.csv")
diff --git a/doc/python/ml-regression.md b/doc/python/ml-regression.md
index b8be347943a..c74b49e92bd 100644
--- a/doc/python/ml-regression.md
+++ b/doc/python/ml-regression.md
@@ -120,7 +120,7 @@ from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
df = px.data.tips()
-X = df.total_bill[:, None]
+X = df.total_bill.to_numpy()[:, None]
X_train, X_test, y_train, y_test = train_test_split(X, df.tip, random_state=0)
model = LinearRegression()
@@ -129,7 +129,6 @@ model.fit(X_train, y_train)
x_range = np.linspace(X.min(), X.max(), 100)
y_range = model.predict(x_range.reshape(-1, 1))
-
fig = go.Figure([
go.Scatter(x=X_train.squeeze(), y=y_train, name='train', mode='markers'),
go.Scatter(x=X_test.squeeze(), y=y_test, name='test', mode='markers'),
diff --git a/doc/python/multiple-axes.md b/doc/python/multiple-axes.md
index 9b2095a6389..5bbdeda3c93 100644
--- a/doc/python/multiple-axes.md
+++ b/doc/python/multiple-axes.md
@@ -357,7 +357,7 @@ fig.show()
*New in 5.13*
-With overlayed axes, each axis by default has its own number of ticks. You can sync the number of ticks on a cartesian axis with another one it overlays by setting `tickmode="sync"`. In this example, we sync the ticks on the `"Total bill amount"` axis with the `"Total number of diners"` axis that it overlays.
+With overlayed axes, each axis by default has its own number of ticks. You can sync the number of ticks on a cartesian axis with another one it overlays by setting `tickmode="sync"`. In this example, we sync the ticks on the `"Total bill amount"` axis with the `"Total number of diners"` axis that it overlays.
```python
import plotly.graph_objects as go
@@ -415,4 +415,4 @@ fig.show()
```
#### Reference
-All of the y-axis properties are found here: https://plotly.com/python/reference/YAxis/. For more information on creating subplots see the [Subplots in Python](/python/subplots/) section.
+All of the y-axis properties are found here: https://plotly.com/python/reference/layout/yaxis/. For more information on creating subplots see the [Subplots in Python](/python/subplots/) section.
diff --git a/doc/python/network-graphs.md b/doc/python/network-graphs.md
index 6046fdd4728..9d2f3fec2e2 100644
--- a/doc/python/network-graphs.md
+++ b/doc/python/network-graphs.md
@@ -134,7 +134,7 @@ fig = go.Figure(data=[edge_trace, node_trace],
hovermode='closest',
margin=dict(b=20,l=5,r=5,t=40),
annotations=[ dict(
- text="Python code: https://plotly.com/ipython-notebooks/network-graphs/",
+ text="Python code: https://plotly.com/python/network-graphs/",
showarrow=False,
xref="paper", yref="paper",
x=0.005, y=-0.002 ) ],
diff --git a/doc/python/peak-finding.md b/doc/python/peak-finding.md
index f04375af7ec..1449afb44c5 100644
--- a/doc/python/peak-finding.md
+++ b/doc/python/peak-finding.md
@@ -36,7 +36,7 @@ jupyter:
#### Imports
-The tutorial below imports [Pandas](https://plotly.com/pandas/intro-to-pandas-tutorial/), and [SciPy](https://www.scipy.org/).
+The tutorial below imports [Pandas](https://pandas.pydata.org/docs/user_guide/10min.html), and [SciPy](https://www.scipy.org/).
```python
import pandas as pd
diff --git a/doc/python/scattermapbox.md b/doc/python/scattermapbox.md
index 8cb2b2b6abf..1bd58271686 100644
--- a/doc/python/scattermapbox.md
+++ b/doc/python/scattermapbox.md
@@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.3'
- jupytext_version: 1.14.1
+ jupytext_version: 1.16.2
kernelspec:
display_name: Python 3 (ipykernel)
language: python
@@ -20,7 +20,7 @@ jupyter:
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
- version: 3.8.0
+ version: 3.10.0
plotly:
description: How to make scatter plots on Mapbox maps in Python.
display_as: maps
@@ -265,6 +265,65 @@ fig.show()
```
+#### Font Customization
+
+You can customize the font on `go.Scattermapbox` traces with `textfont`. For example, you can set the font `family`.
+
+```python
+import plotly.graph_objects as go
+
+token = open(".mapbox_token").read() # you need your own token
+
+fig = go.Figure(go.Scattermapbox(
+ mode = "markers+text+lines",
+ lon = [-75, -80, -50], lat = [45, 20, -20],
+ marker = {'size': 20, 'symbol': ["bus", "harbor", "airport"]},
+ text = ["Bus", "Harbor", "airport"], textposition = "bottom right",
+ textfont = dict(size=18, color="black", family="Open Sans Bold")
+ ))
+
+fig.update_layout(
+ mapbox = {
+ 'accesstoken': token,
+ 'style': "outdoors", 'zoom': 0.7},
+ showlegend = False,)
+
+fig.show()
+```
+
+`go.Scattermapbox` supports the following values for `textfont.family`:
+
+'Metropolis Black Italic', 'Metropolis Black', 'Metropolis Bold Italic', 'Metropolis Bold', 'Metropolis Extra Bold Italic', 'Metropolis Extra Bold', 'Metropolis Extra Light Italic', 'Metropolis Extra Light', 'Metropolis Light Italic', 'Metropolis Light', 'Metropolis Medium Italic', 'Metropolis Medium', 'Metropolis Regular Italic', 'Metropolis Regular', 'Metropolis Semi Bold Italic', 'Metropolis Semi Bold', 'Metropolis Thin Italic', 'Metropolis Thin', 'Open Sans Bold Italic', 'Open Sans Bold', 'Open Sans Extrabold Italic', 'Open Sans Extrabold', 'Open Sans Italic', 'Open Sans Light Italic', 'Open Sans Light', 'Open Sans Regular', 'Open Sans Semibold Italic', 'Open Sans Semibold', 'Klokantech Noto Sans Bold', 'Klokantech Noto Sans CJK Bold', 'Klokantech Noto Sans CJK Regular', 'Klokantech Noto Sans Italic', and 'Klokantech Noto Sans Regular'.
+
+
+##### Font Weight
+
+*New in 5.23*
+
+You can specify a numeric font weight on `go.Scattermapbox` with `textfont.weight`.
+
+```python
+import plotly.graph_objects as go
+
+token = open(".mapbox_token").read() # you need your own token
+
+fig = go.Figure(go.Scattermapbox(
+ mode = "markers+text+lines",
+ lon = [-75, -80, -50], lat = [45, 20, -20],
+ marker = dict(size=20, symbol=["bus", "harbor", "airport"]),
+ text = ["Bus", "Harbor", "airport"], textposition = "bottom right",
+ textfont = dict(size=18, color="black", weight=900)
+ ))
+
+fig.update_layout(
+ mapbox = dict(
+ accesstoken=token,
+ style="outdoors", zoom=0.7),
+ showlegend = False,)
+
+fig.show()
+```
+
#### Reference
See [function reference for `px.(scatter_mapbox)`](https://plotly.com/python-api-reference/generated/plotly.express.scatter_mapbox) or https://plotly.com/python/reference/scattermapbox/ for more information and options!
diff --git a/doc/python/shapes.md b/doc/python/shapes.md
index d4796f6a900..5d67fbf598c 100644
--- a/doc/python/shapes.md
+++ b/doc/python/shapes.md
@@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.3'
- jupytext_version: 1.16.1
+ jupytext_version: 1.16.3
kernelspec:
display_name: Python 3 (ipykernel)
language: python
@@ -20,7 +20,7 @@ jupyter:
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
- version: 3.10.11
+ version: 3.10.14
plotly:
description: How to make SVG shapes in python. Examples of lines, circle, rectangle,
and path.
@@ -579,6 +579,72 @@ fig.update_layout(
fig.show()
```
+#### Shifting Shapes on Categorical Axes
+
+*New in 5.23*
+
+When drawing shapes where `xref` or `yref` reference axes of type category or multicategory, you can shift `x0`, `x1`, `y0`, and `y1` away from the center of the category using `x0shift`, `x1shift`, `y0shift`, and `y1shift` by specifying a value between -1 and 1.
+
+-1 is the center of the previous category, 0 is the center of the referenced category, and 1 is the center of the next category.
+
+In the following example, the `x0` and `x1` values for both shapes reference category values on the x-axis.
+
+In this example, the first shape:
+- Shifts `x0` half way between the center of category "Germany" and the center of the previous category by setting `x0shift=-0.5`
+- Shifts `x1`half way between the center of category "Germany" and the center of the next category by setting `x1shift=0.5`
+
+The second shape:
+- Shifts `x0` back to the center of the previous category by setting `x0shift=-1`
+- Shifts `x1`forward to the center of the next category by setting `x1shift=1`
+
+```python
+import plotly.graph_objects as go
+import plotly.express as px
+
+df = px.data.gapminder().query("continent == 'Europe' and year == 1952")
+
+fig = go.Figure(
+ data=go.Bar(x=df["country"], y=df["lifeExp"], marker_color="LightSalmon"),
+ layout=dict(
+ shapes=[
+ dict(
+ type="rect",
+ x0="Germany",
+ y0=0,
+ x1="Germany",
+ y1=0.5,
+ xref="x",
+ yref="paper",
+ x0shift=-0.5,
+ x1shift=0.5,
+ line=dict(color="LightGreen", width=4),
+ ),
+ dict(
+ type="rect",
+ x0="Spain",
+ y0=0,
+ x1="Spain",
+ y1=0.5,
+ xref="x",
+ yref="paper",
+ x0shift=-1,
+ x1shift=1,
+ line=dict(color="MediumTurquoise", width=4),
+ ),
+ ]
+ ),
+)
+
+fig.update_layout(
+ title="GDP per Capita in Europe (1972)",
+ xaxis_title="Country",
+ yaxis_title="GDP per Capita",
+)
+
+fig.show()
+
+```
+
### Drawing shapes with a Mouse on Cartesian plots
_introduced in plotly 4.7_
diff --git a/doc/python/smoothing.md b/doc/python/smoothing.md
index 7c977478625..7ad484f1e69 100644
--- a/doc/python/smoothing.md
+++ b/doc/python/smoothing.md
@@ -36,7 +36,7 @@ jupyter:
#### Imports
-The tutorial below imports [NumPy](http://www.numpy.org/), [Pandas](https://plotly.com/pandas/intro-to-pandas-tutorial/), [SciPy](https://www.scipy.org/) and [Plotly](https://plotly.com/python/getting-started/).
+The tutorial below imports [NumPy](http://www.numpy.org/), [Pandas](https://pandas.pydata.org/docs/user_guide/10min.html), [SciPy](https://www.scipy.org/) and [Plotly](https://plotly.com/python/getting-started/).
```python
import plotly.graph_objects as go
diff --git a/doc/python/static-image-export.md b/doc/python/static-image-export.md
index 48bb28366ae..b0334597694 100644
--- a/doc/python/static-image-export.md
+++ b/doc/python/static-image-export.md
@@ -101,7 +101,7 @@ if not os.path.exists("images"):
os.mkdir("images")
```
-If you are running this notebook live, click to [open the output directory](./images) so you can examine the images as they are written.
+If you are running this notebook live, click to open the output directory so you can examine the images as they are written.
#### Raster Formats: PNG, JPEG, and WebP
diff --git a/doc/python/subplots.md b/doc/python/subplots.md
index 5d9c49c55ae..6842a650b50 100644
--- a/doc/python/subplots.md
+++ b/doc/python/subplots.md
@@ -619,8 +619,8 @@ fig = make_subplots(2, 3, horizontal_spacing=0.1)
```
#### Reference
-All of the x-axis properties are found here: https://plotly.com/python/reference/XAxis/
-All of the y-axis properties are found here: https://plotly.com/python/reference/YAxis/
+All of the x-axis properties are found here: https://plotly.com/python/reference/layout/xaxis/
+All of the y-axis properties are found here: https://plotly.com/python/reference/layout/yaxis/
```python
from plotly.subplots import make_subplots
diff --git a/doc/python/sunburst-charts.md b/doc/python/sunburst-charts.md
index e22f9f9dd7b..06cfb38e57d 100644
--- a/doc/python/sunburst-charts.md
+++ b/doc/python/sunburst-charts.md
@@ -355,7 +355,7 @@ def build_hierarchical_dataframe(df, levels, value_column, color_columns=None):
Levels are given starting from the bottom to the top of the hierarchy,
ie the last level corresponds to the root.
"""
- df_all_trees = pd.DataFrame(columns=['id', 'parent', 'value', 'color'])
+ df_list = []
for i, level in enumerate(levels):
df_tree = pd.DataFrame(columns=['id', 'parent', 'value', 'color'])
dfg = df.groupby(levels[i:]).sum()
@@ -367,11 +367,12 @@ def build_hierarchical_dataframe(df, levels, value_column, color_columns=None):
df_tree['parent'] = 'total'
df_tree['value'] = dfg[value_column]
df_tree['color'] = dfg[color_columns[0]] / dfg[color_columns[1]]
- df_all_trees = df_all_trees.append(df_tree, ignore_index=True)
+ df_list.append(df_tree)
total = pd.Series(dict(id='total', parent='',
value=df[value_column].sum(),
- color=df[color_columns[0]].sum() / df[color_columns[1]].sum()))
- df_all_trees = df_all_trees.append(total, ignore_index=True)
+ color=df[color_columns[0]].sum() / df[color_columns[1]].sum()), name=0)
+ df_list.append(total)
+ df_all_trees = pd.concat(df_list, ignore_index=True)
return df_all_trees
diff --git a/doc/python/text-and-annotations.md b/doc/python/text-and-annotations.md
index 7f721651eb6..ca8dbd63dfa 100644
--- a/doc/python/text-and-annotations.md
+++ b/doc/python/text-and-annotations.md
@@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.3'
- jupytext_version: 1.16.1
+ jupytext_version: 1.16.3
kernelspec:
display_name: Python 3 (ipykernel)
language: python
@@ -20,7 +20,7 @@ jupyter:
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
- version: 3.10.11
+ version: 3.10.14
plotly:
description: How to add text labels and annotations to plots in python.
display_as: file_settings
@@ -122,7 +122,7 @@ IFrame(snippet_url + 'text-and-annotations', width='100%', height=1200)
### Controlling Text Size with `uniformtext`
-For the [pie](/python/pie-charts), [bar](/python/bar-charts)-like, [sunburst](/python/sunburst-charts) and [treemap](/python/treemap-charts) traces, it is possible to force all the text labels to have the same size thanks to the `uniformtext` layout parameter. The `minsize` attribute sets the font size, and the `mode` attribute sets what happens for labels which cannot fit with the desired fontsize: either `hide` them or `show` them with overflow.
+For the [pie](/python/pie-charts), [bar](/python/bar-charts)-like, [sunburst](/python/sunburst-charts) and [treemap](/python/treemaps) traces, it is possible to force all the text labels to have the same size thanks to the `uniformtext` layout parameter. The `minsize` attribute sets the font size, and the `mode` attribute sets what happens for labels which cannot fit with the desired fontsize: either `hide` them or `show` them with overflow.
Here is a bar chart with the default behavior which will scale down text to fit.
@@ -131,7 +131,7 @@ Here is a bar chart with the default behavior which will scale down text to fit.
import plotly.express as px
df = px.data.gapminder(year=2007)
-fig = px.bar(df, x='continent', y='pop', color="lifeExp", text='country',
+fig = px.bar(df, x='continent', y='pop', color="lifeExp", text='country',
title="Default behavior: some text is tiny")
fig.update_traces(textposition='inside')
fig.show()
@@ -143,7 +143,7 @@ Here is the same figure with uniform text applied: the text for all bars is the
import plotly.express as px
df = px.data.gapminder(year=2007)
-fig = px.bar(df, x='continent', y='pop', color="lifeExp", text='country',
+fig = px.bar(df, x='continent', y='pop', color="lifeExp", text='country',
title="Uniform Text: min size is 8, hidden if can't fit")
fig.update_traces(textposition='inside')
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide')
@@ -162,7 +162,7 @@ fig.show()
### Controlling Maximum Text Size
-The `textfont_size` parameter of the the [pie](/python/pie-charts), [bar](/python/bar-charts)-like, [sunburst](/python/sunburst-charts) and [treemap](/python/treemap-charts) traces can be used to set the **maximum font size** used in the chart. Note that the `textfont` parameter sets the `insidetextfont` and `outsidetextfont` parameter, which can also be set independently.
+The `textfont_size` parameter of the the [pie](/python/pie-charts), [bar](/python/bar-charts)-like, [sunburst](/python/sunburst-charts) and [treemap](/python/treemaps) traces can be used to set the **maximum font size** used in the chart. Note that the `textfont` parameter sets the `insidetextfont` and `outsidetextfont` parameter, which can also be set independently.
```python
import plotly.express as px
@@ -353,7 +353,7 @@ fig.show()
*New in 5.22*
-You can also configure a font's `variant`, `style`, and `weight` on `textfont`. Here, we configure an `italic` style on the first bar, `bold` weight on the second, and`small-caps` as the font variant on the third.
+You can also configure a font's `variant`, `style`, and `weight` on `textfont`. Here, we configure an `italic` style on the first bar, `bold` weight on the second, and `small-caps` as the font variant on the third.
```python
import plotly.graph_objects as go
@@ -395,6 +395,162 @@ fig.show()
```
+## Numeric Font Weight
+
+*New in 5.23*
+
+In the previous example, we set a font `weight` using a keyword value. You can also set font `weight` using a numeric value.
+
+The font weights that are available depend on the font family that is set. If you set a font `weight` that isn't available for a particular font family, the weight will be rounded to the nearest available value.
+
+
+```python
+import plotly.graph_objects as go
+from plotly import data
+
+df = data.medals_wide()
+
+fig = go.Figure(
+ data=[
+ go.Bar(
+ x=df.nation,
+ y=df.gold,
+ name="Gold",
+ marker=dict(color="Gold"),
+ text="Gold",
+ textfont=dict(weight=900, size=17),
+ ),
+ go.Bar(
+ x=df.nation,
+ y=df.silver,
+ name="Silver",
+ marker=dict(color="MediumTurquoise"),
+ text="Silver",
+ textfont=dict(size=17),
+ ),
+ go.Bar(
+ x=df.nation,
+ y=df.bronze,
+ name="Bronze",
+ marker=dict(color="LightGreen"),
+ text="Bronze",
+ textfont=dict(size=17),
+ ),
+ ],
+ layout=dict(barcornerradius=15, showlegend=False),
+)
+
+fig.show()
+```
+
+[scattergl](https://plotly.com/python/reference/scattergl) traces do not support all numeric font weights. When you specify a numeric font weight on `scattergl`, weights up to 500 are mapped to the keyword font weight "normal", while weights above 500 are mapped to "bold".
+
+
+## Text Case
+
+*New in 5.23*
+
+You can configure text case using the `textfont.textcase` property. In this example, we set `textfont.textcase="upper"` to transform the text on all bars to uppercase.
+
+```python
+import plotly.graph_objects as go
+from plotly import data
+
+df = data.gapminder()
+
+grouped = df[df.year == 2007].loc[df[df.year == 2007].groupby('continent')['lifeExp'].idxmax()]
+
+fig = go.Figure(
+ data=go.Bar(
+ x=grouped['lifeExp'],
+ y=grouped['continent'],
+ text=grouped['country'],
+ orientation='h',
+ textfont=dict(
+ family="sans serif",
+ size=14,
+ # Here we set textcase to "upper.
+ # Set to lower" for lowercase text, or "word caps" to capitalize the first letter of each word
+ textcase="upper"
+
+ )
+ ),
+ layout=go.Layout(
+ title_text='Country with Highest Life Expectancy per Continent, 2007',
+ yaxis=dict(showticklabels=False)
+ )
+)
+
+fig.show()
+```
+
+## Text Lines
+
+*New in 5.23*
+
+You can add decoration lines to text using the `textfont.lineposition` property. This property accepts `"under"`, `"over"`, and `"through"`, or a combination of these separated by a `+`.
+
+```python
+import plotly.graph_objects as go
+from plotly import data
+
+df = data.gapminder()
+
+grouped = df[df.year == 2002].loc[df[df.year == 2002].groupby('continent')['lifeExp'].idxmax()]
+
+fig = go.Figure(
+ data=go.Bar(
+ x=grouped['lifeExp'],
+ y=grouped['continent'],
+ text=grouped['country'],
+ orientation='h',
+ marker_color='MediumSlateBlue',
+ textfont=dict(
+ lineposition="under" # combine different line positions with a "+" to add more than one: "under+over"
+ )
+ ),
+ layout=go.Layout(
+ title_text='Country with Highest Life Expectancy per Continent, 2002',
+ yaxis=dict(showticklabels=False)
+ )
+)
+
+fig.show()
+```
+
+## Text Shadow
+
+*New in 5.23*
+
+You can apply a shadow effect to text using the `textfont.shadow` property. This property accepts shadow specifications in the same format as the [text-shadow CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow).
+
+```python
+import plotly.graph_objects as go
+from plotly import data
+
+df = data.gapminder()
+
+grouped = df[df.year == 1997].loc[df[df.year == 1997].groupby('continent')['lifeExp'].idxmax()]
+
+fig = go.Figure(
+ data=go.Bar(
+ x=grouped['lifeExp'],
+ y=grouped['continent'],
+ text=grouped['country'],
+ orientation='h',
+ textfont=dict(
+ shadow="1px 1px 2px pink"
+ )
+ ),
+ layout=go.Layout(
+ title_text='Country with Highest Life Expectancy per Continent, 1997',
+ yaxis=dict(showticklabels=False)
+ )
+)
+
+fig.show()
+```
+
### Styling and Coloring Annotations
```python
@@ -497,6 +653,54 @@ fig.update_layout(
fig.show()
```
+### HTML Tags in Text
+
+The `text` attribute supports the following HTML tags: `0?[0]:[]);if(o.enter().append("g").classed(f.containerClassName,!0).style("cursor","pointer"),o.exit().each((function(){n.select(this).selectAll("g."+f.headerGroupClassName).each(a)})).remove(),0!==r.length){var l=o.selectAll("g."+f.headerGroupClassName).data(r,p);l.enter().append("g").classed(f.headerGroupClassName,!0);for(var u=s.ensureSingle(o,"g",f.dropdownButtonGroupClassName,(function(t){t.style("pointer-events","all")})),c=0;cl?r.y-l:0;return Math.sqrt(u*u+f*f)}for(var p=h(u);p;){if((u+=p+r)>f)return;p=h(u)}for(p=h(f);p;){if(u>(f-=p+r))return;p=h(f)}return{min:u,max:f,len:f-u,total:c,isClosed:0===u&&f===c&&Math.abs(n.x-i.x)<.1&&Math.abs(n.y-i.y)<.1}},e.findPointOnPath=function(t,e,r,n){for(var i,a,o,s=(n=n||{}).pathLength||t.getTotalLength(),l=n.tolerance||.001,u=n.iterationLimit||30,c=t.getPointAtLength(0)[r]>t.getPointAtLength(s)[r]?-1:1,f=0,h=0,p=s;f0?p=i:h=i,f++}return a}},33040:function(t,e,r){"use strict";var n=r(38248),i=r(49760),a=r(72160),o=r(8932),s=r(22548).defaultLine,l=r(38116).isArrayOrTypedArray,u=a(s);function c(t,e){var r=t;return r[3]*=e,r}function f(t){if(n(t))return u;var e=a(t);return e.length?e:u}function h(t){return n(t)?t:1}t.exports={formatColor:function(t,e,r){var n=t.color;n&&n._inputArray&&(n=n._inputArray);var i,s,p,d,v,g=l(n),y=l(e),m=o.extractOpts(t),x=[];if(i=void 0!==m.colorscale?o.makeColorScaleFuncFromTrace(t):f,s=g?function(t,e){return void 0===t[e]?u:a(i(t[e]))}:f,p=y?function(t,e){return void 0===t[e]?1:h(t[e])}:h,g||y)for(var b=0;b