diff --git a/CHANGELOG.md b/CHANGELOG.md index 298927812ee..9a0f13b6f00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [5.16.1] - 2023-08-16 + +### Fixed +- Fixed issue with necessary columns from complex arguments dropped when interchanging dataframes [[#4324](https://github.com/plotly/plotly.py/pull/4324)] ## [5.16.0] - 2023-08-11 diff --git a/README.md b/README.md index 0616fdf10f5..b9249bb6e0d 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ ## Quickstart -`pip install plotly==5.16.0` +`pip install plotly==5.16.1` Inside [Jupyter](https://jupyter.org/install) (installable with `pip install "jupyterlab>=3" "ipywidgets>=7.6"`): @@ -78,13 +78,13 @@ Built on top of [plotly.js](https://github.com/plotly/plotly.js), `plotly.py` is plotly.py may be installed using pip... ``` -pip install plotly==5.16.0 +pip install plotly==5.16.1 ``` or conda. ``` -conda install -c plotly plotly=5.16.0 +conda install -c plotly plotly=5.16.1 ``` ### JupyterLab Support @@ -106,7 +106,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.16.0 @jupyter-widgets/jupyterlab-manager +jupyter labextension install jupyterlab-plotly@5.16.1 @jupyter-widgets/jupyterlab-manager ``` Please check out our [Troubleshooting guide](https://plotly.com/python/troubleshooting/) if you run into any problems with JupyterLab. diff --git a/binder/requirements.txt b/binder/requirements.txt index 814d0417bc3..442cdaf9b5b 100644 --- a/binder/requirements.txt +++ b/binder/requirements.txt @@ -1,5 +1,5 @@ jupytext -plotly==5.15.0 +plotly==5.16.0 jupyter notebook pandas==1.0.3 diff --git a/doc/apidoc/conf.py b/doc/apidoc/conf.py index 6793413bcb7..60c0098c510 100644 --- a/doc/apidoc/conf.py +++ b/doc/apidoc/conf.py @@ -28,7 +28,7 @@ # The short X.Y version version = "" # The full version, including alpha/beta/rc tags -release = "5.15.0" +release = "5.16.0" # -- General configuration --------------------------------------------------- diff --git a/doc/python/animations.md b/doc/python/animations.md index ffd948c7064..c765d36621f 100644 --- a/doc/python/animations.md +++ b/doc/python/animations.md @@ -37,7 +37,7 @@ jupyter: Several [Plotly Express](/python/plotly-express/) functions support the creation of animated figures through the `animation_frame` and `animation_group` arguments. -Here is an example of an animated scatter plot creating using Plotly Express. Note that you should always fix the `x_range` and `y_range` to ensure that your data remains visible throughout the animation. +Here is an example of an animated scatter plot created with Plotly Express. Note that you should always fix the `x_range` and `y_range` to ensure that your data remains visible throughout the animation. ```python import plotly.express as px diff --git a/doc/python/getting-started.md b/doc/python/getting-started.md index 24fecf41317..0be3251daca 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.15.0 +$ pip install plotly==5.16.0 ``` or `conda`: ``` -$ conda install -c plotly plotly=5.15.0 +$ conda install -c plotly plotly=5.16.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.15.0 @jupyter-widgets/jupyterlab-manager +jupyter labextension install jupyterlab-plotly@5.16.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/interactive-html-export.md b/doc/python/interactive-html-export.md index 9691e0f2398..bd7284beb02 100644 --- a/doc/python/interactive-html-export.md +++ b/doc/python/interactive-html-export.md @@ -46,7 +46,7 @@ Any figure can be saved as an HTML file using the `write_html` method. These HTM ```python import plotly.express as px -fig =px.scatter(x=range(10), y=range(10)) +fig = px.scatter(x=range(10), y=range(10)) fig.write_html("path/to/file.html") ``` diff --git a/doc/python/px-arguments.md b/doc/python/px-arguments.md index 78e9a1f59ae..e998602ba6f 100644 --- a/doc/python/px-arguments.md +++ b/doc/python/px-arguments.md @@ -35,7 +35,7 @@ jupyter: ### Plotly Express works with Column-oriented, Matrix or Geographic Data -[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/). +[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/). 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. diff --git a/doc/requirements.txt b/doc/requirements.txt index b888ed8816a..13bbef919e0 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,4 +1,4 @@ -plotly==5.15.0 +plotly==5.16.0 jupytext==1.1.1 ipywidgets==7.7.2 jupyter-client<7 diff --git a/packages/javascript/jupyterlab-plotly/package-lock.json b/packages/javascript/jupyterlab-plotly/package-lock.json index 60f5e7b051c..7eced61d027 100644 --- a/packages/javascript/jupyterlab-plotly/package-lock.json +++ b/packages/javascript/jupyterlab-plotly/package-lock.json @@ -1,12 +1,12 @@ { "name": "jupyterlab-plotly", - "version": "5.16.0", + "version": "5.16.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jupyterlab-plotly", - "version": "5.16.0", + "version": "5.16.1", "license": "MIT", "dependencies": { "@jupyter-widgets/base": ">=2.0.0 <7.0.0", diff --git a/packages/javascript/jupyterlab-plotly/package.json b/packages/javascript/jupyterlab-plotly/package.json index ff5aba575c8..c4b42fe7117 100644 --- a/packages/javascript/jupyterlab-plotly/package.json +++ b/packages/javascript/jupyterlab-plotly/package.json @@ -1,6 +1,6 @@ { "name": "jupyterlab-plotly", - "version": "5.16.0", + "version": "5.16.1", "description": "The plotly Jupyter extension", "author": "The plotly.py team", "license": "MIT", diff --git a/packages/python/plotly/plotly/_widget_version.py b/packages/python/plotly/plotly/_widget_version.py index 15af696494a..3eb599b6f59 100644 --- a/packages/python/plotly/plotly/_widget_version.py +++ b/packages/python/plotly/plotly/_widget_version.py @@ -2,4 +2,4 @@ # for automated dev builds # # It is edited by hand prior to official releases -__frontend_version__ = "^5.16.0" +__frontend_version__ = "^5.16.1" diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index b889bec88df..275efaf3b4a 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -1419,9 +1419,13 @@ def build_dataframe(args, constructor): else: # Save precious resources by only interchanging columns that are # actually going to be plotted. - columns = [ + necessary_columns = { i for i in args.values() if isinstance(i, str) and i in columns - ] + } + for field in args: + if args[field] is not None and field in array_attrables: + necessary_columns.update(i for i in args[field] if i in columns) + columns = list(necessary_columns) args["data_frame"] = pd.api.interchange.from_dataframe( args["data_frame"].select_columns_by_name(columns) ) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py index fa0f1298fdc..7c9ad6ac1ea 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py @@ -8,6 +8,7 @@ from plotly.express._core import build_dataframe from pandas.testing import assert_frame_equal + # Fixtures # -------- @pytest.fixture @@ -292,9 +293,10 @@ def __dataframe__(self): ) as mock_from_dataframe: build_dataframe(args, go.Scatter) mock_from_dataframe.assert_called_once_with(interchange_dataframe_reduced) - interchange_dataframe.select_columns_by_name.assert_called_with( - ["petal_width", "sepal_length"] - ) + assert set(interchange_dataframe.select_columns_by_name.call_args[0][0]) == { + "petal_width", + "sepal_length", + } args = dict(data_frame=input_dataframe_reduced, color=None) with mock.patch( @@ -327,6 +329,35 @@ def test_build_df_from_vaex_and_polars(test_lib): ) +@pytest.mark.skipif( + version.parse(pd.__version__) < version.parse("2.0.2"), + reason="plotly doesn't use a dataframe interchange protocol for pandas < 2.0.2", +) +@pytest.mark.parametrize("test_lib", ["vaex", "polars"]) +@pytest.mark.parametrize( + "hover_data", [["sepal_width"], {"sepal_length": False, "sepal_width": ":.2f"}] +) +def test_build_df_with_hover_data_from_vaex_and_polars(test_lib, hover_data): + if test_lib == "vaex": + import vaex as lib + else: + import polars as lib + + # take out the 'species' columns since the vaex implementation does not cover strings yet + iris_pandas = px.data.iris()[["petal_width", "sepal_length", "sepal_width"]] + iris_vaex = lib.from_pandas(iris_pandas) + args = dict( + data_frame=iris_vaex, + x="petal_width", + y="sepal_length", + hover_data=hover_data, + ) + out = build_dataframe(args, go.Scatter) + assert_frame_equal( + iris_pandas.reset_index()[out["data_frame"].columns], out["data_frame"] + ) + + def test_timezones(): df = pd.DataFrame({"date": ["2015-04-04 19:31:30+1:00"], "value": [3]}) df["date"] = pd.to_datetime(df["date"])