Skip to content

Commit 3ae3ea9

Browse files
authored
Merge branch 'master' into doc-prod
2 parents 43ff7c1 + 598f214 commit 3ae3ea9

File tree

16 files changed

+159
-40
lines changed

16 files changed

+159
-40
lines changed

Diff for: .circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: 2.1
22

33
orbs:
4-
browser-tools: circleci/[email protected].1
4+
browser-tools: circleci/[email protected].3
55

66
commands:
77
test_core:

Diff for: CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
6+
## UNRELEASED
7+
8+
### Updated
9+
- Updated Plotly.js from version 2.24.1 to version 2.24.2. See the [plotly.js CHANGELOG](https://github.com/plotly/plotly.js/blob/master/CHANGELOG.md#2242----2023-06-09) for more information. These changes are reflected in the auto-generated `plotly.graph_objects` module.
10+
- `px` methods now accept data-frame-like objects that support a [dataframe interchange protocol](https://data-apis.org/dataframe-protocol/latest/index.html), such as polars, vaex, modin etc. This protocol has priority on `to_pandas` call, but will only be used if pandas>=2.0.2 is installed in the environment.
11+
512
## [5.15.0] - 2023-06-08
613

714
### Updated

Diff for: doc/python/plotly-express.md

+6-7
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ jupyter:
55
text_representation:
66
extension: .md
77
format_name: markdown
8-
format_version: '1.2'
9-
jupytext_version: 1.4.2
8+
format_version: '1.3'
9+
jupytext_version: 1.14.7
1010
kernelspec:
11-
display_name: Python 3
11+
display_name: Python 3 (ipykernel)
1212
language: python
1313
name: python3
1414
language_info:
@@ -20,7 +20,7 @@ jupyter:
2020
name: python
2121
nbconvert_exporter: python
2222
pygments_lexer: ipython3
23-
version: 3.7.7
23+
version: 3.10.4
2424
plotly:
2525
description: Plotly Express is a terse, consistent, high-level API for creating
2626
figures.
@@ -42,8 +42,7 @@ Plotly Express provides [more than 30 functions for creating different types of
4242

4343
Here is a talk from the [SciPy 2021 conference](https://www.scipy2021.scipy.org/) that gives a good introduction to Plotly Express and [Dash](https://dash.plotly.com/):
4444

45-
```python hide_code=true
46-
%%html
45+
```html hide_code=true
4746
<div align="center">
4847
<iframe width="560" height="315"
4948
src="https://www.youtube.com/embed/FpCgG85g2Hw"
@@ -72,7 +71,7 @@ The Plotly Express API in general offers the following features:
7271

7372
* **A single entry point into `plotly`**: just `import plotly.express as px` and get access to [all the plotting functions](https://plotly.com/python-api-reference/plotly.express.html), plus [built-in demo datasets under `px.data`](https://plotly.com/python-api-reference/generated/plotly.data.html#module-plotly.data) and [built-in color scales and sequences under `px.color`](https://plotly.com/python-api-reference/generated/plotly.colors.html#module-plotly.colors). Every PX function returns a `plotly.graph_objects.Figure` object, so you can edit it using all the same methods like [`update_layout` and `add_trace`](https://plotly.com/python/creating-and-updating-figures/#updating-figures).
7473
* **Sensible, Overridable Defaults**: PX functions will infer sensible defaults wherever possible, and will always let you override them.
75-
* **Flexible Input Formats**: PX functions [accept input in a variety of formats](/python/px-arguments/), from `list`s and `dict`s to [long-form or wide-form Pandas `DataFrame`s](/python/wide-form/) to [`numpy` arrays and `xarrays`](/python/imshow/) to [GeoPandas `GeoDataFrames`](/python/maps/).
74+
* **Flexible Input Formats**: PX functions [accept input in a variety of formats](/python/px-arguments/), from `list`s and `dict`s to [long-form or wide-form `DataFrame`s](/python/wide-form/) to [`numpy` arrays and `xarrays`](/python/imshow/) to [GeoPandas `GeoDataFrames`](/python/maps/).
7675
* **Automatic Trace and Layout configuration**: PX functions will create one [trace](/python/figure-structure) per animation frame for each unique combination of data values mapped to discrete color, symbol, line-dash, facet-row and/or facet-column. Traces' [`legendgroup` and `showlegend` attributes](https://plotly.com/python/legend/) are set such that only one legend item appears per unique combination of discrete color, symbol and/or line-dash. Traces are automatically linked to a correctly-configured [subplot of the appropriate type](/python/figure-structure).
7776
* **Automatic Figure Labelling**: PX functions [label axes, legends and colorbars](https://plotly.com/python/figure-labels/) based in the input `DataFrame` or `xarray`, and provide [extra control with the `labels` argument](/python/styling-plotly-express/).
7877
* **Automatic Hover Labels**: PX functions populate the hover-label using the labels mentioned above, and provide [extra control with the `hover_name` and `hover_data` arguments](/python/hover-text-and-formatting/).

Diff for: doc/python/px-arguments.md

+39-7
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ jupyter:
55
text_representation:
66
extension: .md
77
format_name: markdown
8-
format_version: '1.2'
9-
jupytext_version: 1.4.2
8+
format_version: '1.3'
9+
jupytext_version: 1.14.7
1010
kernelspec:
11-
display_name: Python 3
11+
display_name: Python 3 (ipykernel)
1212
language: python
1313
name: python3
1414
language_info:
@@ -20,7 +20,7 @@ jupyter:
2020
name: python
2121
nbconvert_exporter: python
2222
pygments_lexer: ipython3
23-
version: 3.7.7
23+
version: 3.10.4
2424
plotly:
2525
description: Input data arguments accepted by Plotly Express functions
2626
display_as: file_settings
@@ -35,9 +35,11 @@ jupyter:
3535

3636
### Plotly Express works with Column-oriented, Matrix or Geographic Data
3737

38-
[Plotly Express](/python/plotly-express/) is the easy-to-use, high-level interface to Plotly, which [operates on a variety of types of data](/python/px-arguments/) and produces [easy-to-style figures](/python/styling-plotly-express/).
38+
[Plotly Express](/python/plotly-express/) is the easy-to-use, high-level interface to Plotly, which operates on a variety of types of data and produces [easy-to-style figures](/python/styling-plotly-express/).
3939

40-
Plotly Express provides functions to visualize a variety of types of data. Most functions such as `px.bar` or `px.scatter` expect to operate on column-oriented data of the type you might store in a Pandas `DataFrame` (in either "long" or "wide" format, see below). [`px.imshow` operates on matrix-like data](/python/imshow/) you might store in a `numpy` or `xarray` array and functions like [`px.choropleth` and `px.choropleth_mapbox` can operate on geographic data](/python/maps/) of the kind you might store in a GeoPandas `GeoDataFrame`. This page details how to provide column-oriented data to most Plotly Express functions.
40+
Plotly Express provides functions to visualize a variety of types of data. Most functions such as `px.bar` or `px.scatter` expect to operate on column-oriented data of the type you might store in a `DataFrame` (in either "long" or "wide" format, see below). These functions use Pandas internally to process the data, but also accept other types of DataFrames as arguments. See the **Input Data as Non-Pandas DataFrames** section below for more details.
41+
42+
[`px.imshow` operates on matrix-like data](/python/imshow/) you might store in a `numpy` or `xarray` array and functions like [`px.choropleth` and `px.choropleth_mapbox` can operate on geographic data](/python/maps/) of the kind you might store in a GeoPandas `GeoDataFrame`. This page details how to provide column-oriented data to most Plotly Express functions.
4143

4244

4345

@@ -166,6 +168,36 @@ fig = px.bar(df, x='year', y=gdp, color='continent', labels={'y':'gdp'},
166168
fig.show()
167169
```
168170

171+
### Input Data as Non-Pandas `DataFrame`s
172+
173+
**New in 5.16**
174+
175+
In the examples above, we've used Pandas DataFrames. You can also provide another type of DataFrame to the `data_frame` argument if that DataFrame has a `to_pandas` method or supports the [Python dataframe interchange protocol](https://data-apis.org/dataframe-protocol/latest/index.html), for example, a [Polars](https://www.pola.rs/) DataFrame.
176+
177+
Plotly Express uses Pandas internally to process the data. When you provide a Non-Pandas DataFrame to the `data_frame` argument of a Plotly Express function, the entire DataFrame is converted to a Pandas DataFrame.
178+
179+
If you are using a type of DataFrame that doesn't have a `to_pandas` method, but supports the Python dataframe interchange protocol, you'll need to have Pandas version 2.0.3 or later installed.
180+
181+
In this example, we use a Polars DataFrame. If you are using Polars, you'll need to install `pyarrow`, which is used by its [`to_pandas` method](
182+
https://pola-rs.github.io/polars/py-polars/html/reference/dataframe/api/polars.DataFrame.to_pandas.html)
183+
184+
```python
185+
import polars as pl
186+
import plotly.express as px
187+
188+
wide_df = pl.DataFrame(
189+
{
190+
"nation": ["South Korea", "China", "Canada"],
191+
"gold": [24, 10, 9],
192+
"silver": [13, 15, 12],
193+
"bronze": [9, 12, 12],
194+
}
195+
)
196+
197+
fig = px.bar(wide_df, x="nation", y=["gold", "silver", "bronze"], title="Wide-Form Input")
198+
fig.show()
199+
```
200+
169201
### Input Data as array-like columns: NumPy arrays, lists...
170202

171203
`px` arguments can also be array-like objects such as lists, NumPy arrays, in both long-form or wide-form (for certain functions).
@@ -243,4 +275,4 @@ fig = px.bar(df, x='year', y=gdp, color='continent', labels={'y':'log gdp'},
243275
hover_data=['country'],
244276
title='Evolution of world GDP')
245277
fig.show()
246-
```
278+
```

Diff for: doc/python/wide-form.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ jupyter:
55
text_representation:
66
extension: .md
77
format_name: markdown
8-
format_version: '1.2'
9-
jupytext_version: 1.4.2
8+
format_version: '1.3'
9+
jupytext_version: 1.14.7
1010
kernelspec:
11-
display_name: Python 3
11+
display_name: Python 3 (ipykernel)
1212
language: python
1313
name: python3
1414
language_info:
@@ -20,7 +20,7 @@ jupyter:
2020
name: python
2121
nbconvert_exporter: python
2222
pygments_lexer: ipython3
23-
version: 3.7.7
23+
version: 3.10.4
2424
plotly:
2525
description: Plotly Express' 2D-Cartesian functions accept data in long-, wide-,
2626
and mixed-form.
@@ -36,7 +36,9 @@ jupyter:
3636

3737
### Plotly Express works with Column-oriented, Matrix or Geographic Data
3838

39-
Plotly Express provides functions to visualize a variety of types of data. Most functions such as `px.bar` or `px.scatter` expect to operate on column-oriented data of the type you might store in a Pandas `DataFrame` (in either "long" or "wide" format, see below). [`px.imshow` operates on matrix-like data](/python/imshow/) you might store in a `numpy` or `xarray` array and functions like [`px.choropleth` and `px.choropleth_mapbox` can operate on geographic data](/python/maps/) of the kind you might store in a GeoPandas `GeoDataFrame`. This page details how to provide a specific form of column-oriented data to 2D-Cartesian Plotly Express functions, but you can also check out our [detailed column-input-format documentation](/python/px-arguments/).
39+
Plotly Express provides functions to visualize a variety of types of data. Most functions such as `px.bar` or `px.scatter` expect to operate on column-oriented data of the type you might store in a `DataFrame` (in either "long" or "wide" format, see below). These functions use Pandas internally to process the data, but also accept other types of DataFrames as arguments. See the [Plotly Express arguments page](/python/px-arguments/) for more details.
40+
41+
[`px.imshow` operates on matrix-like data](/python/imshow/) you might store in a `numpy` or `xarray` array and functions like [`px.choropleth` and `px.choropleth_mapbox` can operate on geographic data](/python/maps/) of the kind you might store in a GeoPandas `GeoDataFrame`. This page details how to provide a specific form of column-oriented data to 2D-Cartesian Plotly Express functions, but you can also check out our [detailed column-input-format documentation](/python/px-arguments/).
4042

4143
### Plotly Express works with Long-, Wide-, and Mixed-Form Data
4244

@@ -312,4 +314,4 @@ fig.show()
312314

313315
fig = px.box(wide_df, orientation="h")
314316
fig.show()
315-
```
317+
```

Diff for: doc/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ orjson
3737
dash-bio
3838
jinja2<3.1
3939
parmed<=3.4.4; python_version<"3.8"
40+
polars

Diff for: packages/javascript/jupyterlab-plotly/package-lock.json

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/javascript/jupyterlab-plotly/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
"@lumino/messaging": "^1.2.3",
6666
"@lumino/widgets": "^1.8.1",
6767
"lodash": "^4.17.4",
68-
"plotly.js": "^2.24.1"
68+
"plotly.js": "^2.24.2"
6969
},
7070
"jupyterlab": {
7171
"extension": "lib/jupyterlab-plugin",

Diff for: packages/python/plotly/plotly/express/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
`plotly.express` is a terse, consistent, high-level wrapper around `plotly.graph_objects`
3-
for rapid data exploration and figure generation. Learn more at https://plotly.express/
3+
for rapid data exploration and figure generation. Learn more at https://plotly.com/python/plotly-express/
44
"""
55
from __future__ import absolute_import
66
from plotly import optional_imports

Diff for: packages/python/plotly/plotly/express/_core.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from _plotly_utils.basevalidators import ColorscaleValidator
88
from plotly.colors import qualitative, sequential
99
import math
10+
from packaging import version
1011
import pandas as pd
1112
import numpy as np
1213

@@ -1307,7 +1308,25 @@ def build_dataframe(args, constructor):
13071308
# Cast data_frame argument to DataFrame (it could be a numpy array, dict etc.)
13081309
df_provided = args["data_frame"] is not None
13091310
if df_provided and not isinstance(args["data_frame"], pd.DataFrame):
1310-
if hasattr(args["data_frame"], "to_pandas"):
1311+
if hasattr(args["data_frame"], "__dataframe__") and version.parse(
1312+
pd.__version__
1313+
) >= version.parse("2.0.2"):
1314+
import pandas.api.interchange
1315+
1316+
df_not_pandas = args["data_frame"]
1317+
try:
1318+
df_pandas = pandas.api.interchange.from_dataframe(df_not_pandas)
1319+
except (ImportError, NotImplementedError) as exc:
1320+
# temporary workaround; developers of third-party libraries themselves
1321+
# should try a different implementation, if available. For example:
1322+
# def __dataframe__(self, ...):
1323+
# if not some_condition:
1324+
# self.to_pandas(...)
1325+
if not hasattr(df_not_pandas, "to_pandas"):
1326+
raise exc
1327+
df_pandas = df_not_pandas.to_pandas()
1328+
args["data_frame"] = df_pandas
1329+
elif hasattr(args["data_frame"], "to_pandas"):
13111330
args["data_frame"] = args["data_frame"].to_pandas()
13121331
else:
13131332
args["data_frame"] = pd.DataFrame(args["data_frame"])
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# DO NOT EDIT
22
# This file is generated by the updatebundle setup.py command
3-
__plotlyjs_version__ = "2.24.1"
3+
__plotlyjs_version__ = "2.24.2"

Diff for: packages/python/plotly/plotly/package_data/plotly.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/python/plotly/plotly/tests/test_io/test_renderers.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,8 @@ def test_missing_webbrowser_module(fig1):
388388
"""
389389
Assert that no errors occur if the webbrowser module is absent
390390
"""
391-
try:
392-
import builtins
393-
except ImportError:
394-
import __builtin__ as builtins
391+
import builtins
392+
395393
realimport = builtins.__import__
396394

397395
def webbrowser_absent_import(name, globals, locals, fromlist, level):

Diff for: packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py

+57
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,25 @@
33
import numpy as np
44
import pandas as pd
55
import pytest
6+
from packaging import version
7+
import unittest.mock as mock
68
from plotly.express._core import build_dataframe
79
from pandas.testing import assert_frame_equal
810

11+
# Fixtures
12+
# --------
13+
@pytest.fixture
14+
def add_interchange_module_for_old_pandas():
15+
if not hasattr(pd.api, "interchange"):
16+
pd.api.interchange = mock.MagicMock()
17+
# to make the following import work: `import pandas.api.interchange`
18+
with mock.patch.dict(
19+
"sys.modules", {"pandas.api.interchange": pd.api.interchange}
20+
):
21+
yield
22+
else:
23+
yield
24+
925

1026
def test_numpy():
1127
fig = px.scatter(x=[1, 2, 3], y=[2, 3, 4], color=[1, 3, 9])
@@ -233,6 +249,47 @@ def test_build_df_with_index():
233249
assert_frame_equal(tips.reset_index()[out["data_frame"].columns], out["data_frame"])
234250

235251

252+
def test_build_df_using_interchange_protocol_mock(
253+
add_interchange_module_for_old_pandas,
254+
):
255+
class CustomDataFrame:
256+
def __dataframe__(self):
257+
pass
258+
259+
input_dataframe = CustomDataFrame()
260+
args = dict(data_frame=input_dataframe, x="petal_width", y="sepal_length")
261+
262+
iris_pandas = px.data.iris()
263+
264+
with mock.patch("pandas.__version__", "2.0.2"):
265+
with mock.patch(
266+
"pandas.api.interchange.from_dataframe", return_value=iris_pandas
267+
) as mock_from_dataframe:
268+
build_dataframe(args, go.Scatter)
269+
mock_from_dataframe.assert_called_once_with(input_dataframe)
270+
271+
272+
@pytest.mark.skipif(
273+
version.parse(pd.__version__) < version.parse("2.0.2"),
274+
reason="plotly doesn't use a dataframe interchange protocol for pandas < 2.0.2",
275+
)
276+
@pytest.mark.parametrize("test_lib", ["vaex", "polars"])
277+
def test_build_df_from_vaex_and_polars(test_lib):
278+
if test_lib == "vaex":
279+
import vaex as lib
280+
else:
281+
import polars as lib
282+
283+
# take out the 'species' columns since the vaex implementation does not cover strings yet
284+
iris_pandas = px.data.iris()[["petal_width", "sepal_length"]]
285+
iris_vaex = lib.from_pandas(iris_pandas)
286+
args = dict(data_frame=iris_vaex, x="petal_width", y="sepal_length")
287+
out = build_dataframe(args, go.Scatter)
288+
assert_frame_equal(
289+
iris_pandas.reset_index()[out["data_frame"].columns], out["data_frame"]
290+
)
291+
292+
236293
def test_timezones():
237294
df = pd.DataFrame({"date": ["2015-04-04 19:31:30+1:00"], "value": [3]})
238295
df["date"] = pd.to_datetime(df["date"])

Diff for: packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
requests==2.25.1
22
tenacity==6.2.0
3-
pandas==2.0.1
3+
pandas==2.0.2
44
numpy==1.20.3
55
xarray==0.17.0
66
statsmodels
@@ -19,3 +19,6 @@ matplotlib==2.2.3
1919
scikit-image==0.18.1
2020
psutil==5.7.0
2121
kaleido
22+
vaex
23+
pydantic<=1.10.11 # for vaex, see https://github.com/vaexio/vaex/issues/2384
24+
polars

Diff for: release.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ start by doing it first if not. Then merge `master` into `doc-prod` to deploy th
128128
to features in the release.
129129
3. in a clone of the [`graphing-library-docs` repo](https://github.com/plotly/graphing-library-docs):
130130
1. bump the version of Plotly.py in `_data/pyversion.json`
131-
2. bump the version of Plotly.js with `cd _data && python get_plotschema.py <PLOTLY.JS VERSION>` fixing any errors that come up
131+
2. bump the version of Plotly.js with `cd _data && python get_plotschema.py <PLOTLY.JS VERSION>` fixing any errors that come up.
132+
- If Plotly.js contains any new traces or trace or layout attributes, you'll get a warning `“missing key in attributes: <attribute-name>`. To resolve, add the attribute to the relevant section in `/_data/orderings.json` in the position you want it to appear in the reference docs.
132133
3. rebuild the Algolia `schema` index with `ALGOLIA_API_KEY=<key> make update_ref_search`
133134
4. Rebuild the Algolia `python` index with `ALGOLIA_API_KEY=<key> make update_python_search`
134135
5. Commit and push the changes to `master` in that repo

0 commit comments

Comments
 (0)