From beb7c8cce99bf5c9cbcfe9666267614830e6e522 Mon Sep 17 00:00:00 2001 From: Nicolas Kruchten Date: Fri, 5 Jun 2020 08:09:43 -0400 Subject: [PATCH 1/4] imshow now handles DataFrame indexes and names by default --- doc/python/heatmaps.md | 12 ++++++++-- doc/python/px-arguments.md | 4 ++-- doc/python/wide-form.md | 4 ++-- .../python/plotly/plotly/express/_imshow.py | 11 ++++++++++ .../tests/test_core/test_px/test_imshow.py | 22 +++++++++++++++++++ 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/doc/python/heatmaps.md b/doc/python/heatmaps.md index defed42f5f1..9fb1d870eb4 100644 --- a/doc/python/heatmaps.md +++ b/doc/python/heatmaps.md @@ -36,7 +36,7 @@ jupyter: ### Heatmap with `plotly.express` and `px.imshow` -[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/). With `px.imshow`, each value of the input array is represented as a heatmap pixel. +[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/). With `px.imshow`, each value of the input array or data frame is represented as a heatmap pixel. For more examples using `px.imshow`, see the [tutorial on displaying image data with plotly](/python/imshow). @@ -49,6 +49,14 @@ fig = px.imshow([[1, 20, 30], fig.show() ``` +```python +import plotly.express as px + +df = px.data.medals_wide(indexed=True) +fig = px.imshow(df) +fig.show() +``` + ### Customizing the axes and labels on a heatmap You can use the `x`, `y` and `labels` arguments to customize the display of a heatmap, and use `.update_xaxes()` to move the x axis tick labels to the top: @@ -182,4 +190,4 @@ Arrays of rasterized values build by datashader can be visualized using plotly's heatmaps, as shown in the [plotly and datashader tutorial](/python/datashader/). #### Reference -See https://plotly.com/python/reference/#heatmap for more information and chart attribute options! \ No newline at end of file +See https://plotly.com/python/reference/#heatmap for more information and chart attribute options! diff --git a/doc/python/px-arguments.md b/doc/python/px-arguments.md index 45db70dadab..c945ad8bba8 100644 --- a/doc/python/px-arguments.md +++ b/doc/python/px-arguments.md @@ -49,7 +49,7 @@ There are three common conventions for storing column-oriented data, usually in * **wide-form data** has one row per value of one of the first variable, and one column per value of the second variable. This is suitable for storing and displaying 2-dimensional data. * **mixed-form data** is a hybrid of long-form and wide-form data, with one row per value of one variable, and some columns representing values of another, and some columns representing more variables. See the [wide-form documentation](/python/wide-form/) for examples of how to use Plotly Express to visualize this kind of data. -Every Plotly Express function other than `imshow` can operate on long-form data, and in addition, the following 2D-Cartesian functions can operate on wide-form and mixed-form data: `px.scatter`, `px.line`, `px.area`, `px.bar`, `px.histogram`, `px.violin`, `px.box`, `px.strip`, `px.funnel`, `px.density_heatmap` and `px.density_contour`. +Every Plotly Express function can operate on long-form data (other than `px.imshow` which operates only on wide-form input), and in addition, the following 2D-Cartesian functions can operate on wide-form and mixed-form data: `px.scatter`, `px.line`, `px.area`, `px.bar`, `px.histogram`, `px.violin`, `px.box`, `px.strip`, `px.funnel`, `px.density_heatmap` and `px.density_contour`. By way of example here is the same data, represented in long-form first, and then in wide-form: @@ -241,4 +241,4 @@ fig = px.bar(df, x='year', y=gdp, color='continent', labels={'y':'log gdp'}, hover_data=['country'], title='Evolution of world GDP') fig.show() -``` \ No newline at end of file +``` diff --git a/doc/python/wide-form.md b/doc/python/wide-form.md index c67813c1fc4..b998c707749 100644 --- a/doc/python/wide-form.md +++ b/doc/python/wide-form.md @@ -48,7 +48,7 @@ There are three common conventions for storing column-oriented data, usually in * **wide-form data** has one row per value of one of the first variable, and one column per value of the second variable. This is suitable for storing and displaying 2-dimensional data. * **mixed-form data** is a hybrid of long-form and wide-form data, with one row per value of one variable, and some columns representing values of another, and some columns representing more variables. -Every Plotly Express function other than `imshow` can operate on long-form data, and in addition, the following 2D-Cartesian functions can operate on wide-form and mixed-form data: `px.scatter`, `px.line`, `px.area`, `px.bar`, `px.histogram`, `px.violin`, `px.box`, `px.strip`, `px.funnel`, `px.density_heatmap` and `px.density_contour`. +Every Plotly Express function can operate on long-form data (other than `px.imshow` which operates only on wide-form input), and in addition, the following 2D-Cartesian functions can operate on wide-form and mixed-form data: `px.scatter`, `px.line`, `px.area`, `px.bar`, `px.histogram`, `px.violin`, `px.box`, `px.strip`, `px.funnel`, `px.density_heatmap` and `px.density_contour`. By way of example here is the same data, represented in long-form first, and then in wide-form: @@ -302,4 +302,4 @@ fig.show() fig = px.box(wide_df, orientation="h") fig.show() -``` \ No newline at end of file +``` diff --git a/packages/python/plotly/plotly/express/_imshow.py b/packages/python/plotly/plotly/express/_imshow.py index d8446d227d2..deade844c94 100644 --- a/packages/python/plotly/plotly/express/_imshow.py +++ b/packages/python/plotly/plotly/express/_imshow.py @@ -196,6 +196,17 @@ def imshow( labels["color"] = xarray.plot.utils.label_from_attrs(img) labels["color"] = labels["color"].replace("\n", "
") else: + if hasattr(img, "columns") and hasattr(img.columns, "__len__"): + if x is None: + x = img.columns + if labels.get("x", None) is None and hasattr(img.columns, "name"): + labels["x"] = img.columns.name or "" + if hasattr(img, "index") and hasattr(img.index, "__len__"): + if y is None: + y = img.index + if labels.get("y", None) is None and hasattr(img.index, "name"): + labels["y"] = img.index.name or "" + if labels.get("x", None) is None: labels["x"] = "" if labels.get("y", None) is None: diff --git a/packages/python/plotly/plotly/tests/test_core/test_px/test_imshow.py b/packages/python/plotly/plotly/tests/test_core/test_px/test_imshow.py index 7f8c2afd48b..465a2e3dab1 100644 --- a/packages/python/plotly/plotly/tests/test_core/test_px/test_imshow.py +++ b/packages/python/plotly/plotly/tests/test_core/test_px/test_imshow.py @@ -150,3 +150,25 @@ def test_imshow_labels_and_ranges(): with pytest.raises(ValueError): fig = px.imshow([[1, 2], [3, 4], [5, 6]], x=["a"]) + + +def test_imshow_dataframe(): + df = px.data.medals_wide(indexed=False) + fig = px.imshow(df) + assert fig.data[0].x[0] == df.columns[0] + assert fig.data[0].x[0] == "nation" + assert fig.layout.xaxis.title.text is None + assert fig.data[0].y[0] == df.index[0] + assert fig.data[0].y[0] == 0 + assert fig.layout.yaxis.title.text is None + + df = px.data.medals_wide(indexed=True) + fig = px.imshow(df) + assert fig.data[0].x[0] == df.columns[0] + assert fig.data[0].x[0] == "gold" + assert fig.layout.xaxis.title.text == df.columns.name + assert fig.layout.xaxis.title.text == "medal" + assert fig.data[0].y[0] == df.index[0] + assert fig.data[0].y[0] == "South Korea" + assert fig.layout.yaxis.title.text == df.index.name + assert fig.layout.yaxis.title.text == "nation" From 8d39dc1e523a25b880ea0fb5450c805f74a868f5 Mon Sep 17 00:00:00 2001 From: Nicolas Kruchten Date: Fri, 5 Jun 2020 08:11:51 -0400 Subject: [PATCH 2/4] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 985f3c231d0..edd75bca0df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Fixed special cases with `px.sunburst` and `px.treemap` with `path` input ([#2524](https://github.com/plotly/plotly.py/pull/2524)) +### Updated + +- `plotly.express.imshow` now uses data frame index names and values to populate axis parameters by default ([#2539](https://github.com/plotly/plotly.py/pull/2539)) + ## [4.8.1] - 2020-05-28 ### Fixed From a01a1e7ef093a0e53c391ee484313e658d96d6e3 Mon Sep 17 00:00:00 2001 From: Nicolas Kruchten Date: Fri, 5 Jun 2020 08:44:06 -0400 Subject: [PATCH 3/4] should go into a minor changelog --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd75bca0df..b03baf068e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,18 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [4.9.0] - unreleased + +### Updated + +- `plotly.express.imshow` now uses data frame index names and values to populate axis parameters by default ([#2539](https://github.com/plotly/plotly.py/pull/2539)) + ## [4.8.2] - unreleased ### Fixed - Fixed special cases with `px.sunburst` and `px.treemap` with `path` input ([#2524](https://github.com/plotly/plotly.py/pull/2524)) -### Updated - -- `plotly.express.imshow` now uses data frame index names and values to populate axis parameters by default ([#2539](https://github.com/plotly/plotly.py/pull/2539)) - ## [4.8.1] - 2020-05-28 ### Fixed From 85041ae1569ec0f233cd48e208696c50d700ee69 Mon Sep 17 00:00:00 2001 From: Nicolas Kruchten Date: Fri, 12 Jun 2020 15:38:22 -0400 Subject: [PATCH 4/4] Update CHANGELOG.md Co-authored-by: Emmanuelle Gouillart --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b03baf068e5..44b6a952334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Updated -- `plotly.express.imshow` now uses data frame index names and values to populate axis parameters by default ([#2539](https://github.com/plotly/plotly.py/pull/2539)) +- `plotly.express.imshow` now uses data frame index and columns names and values to populate axis parameters by default ([#2539](https://github.com/plotly/plotly.py/pull/2539)) ## [4.8.2] - unreleased