diff --git a/CHANGELOG.md b/CHANGELOG.md index fb35da134f6..ca7ae10c09f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## UNRELEASED +### Added + + - `text_auto` argument to `px.bar`, `px.histogram`, `px.density_heatmap`, `px.imshow` [#3518](https://github.com/plotly/plotly.py/issues/3518) + - Deprecated `ff.create_annotated_heatmap`, `ff.create_county_choropleth`, `ff.create_gantt` [#3518](https://github.com/plotly/plotly.py/issues/3518) + ### Updated - Updated Plotly.js to from version 2.6.3 to version 2.8.1. See the [plotly.js CHANGELOG](https://github.com/plotly/plotly.js/blob/master/CHANGELOG.md#280----2021-12-10) for more information. Notable changes include: - Horizontal color bars diff --git a/doc/python/2D-Histogram.md b/doc/python/2D-Histogram.md index ea2543cf728..aa7e305dbc1 100644 --- a/doc/python/2D-Histogram.md +++ b/doc/python/2D-Histogram.md @@ -8,7 +8,7 @@ jupyter: format_version: '1.3' jupytext_version: 1.13.4 kernelspec: - display_name: Python 3 (ipykernel) + display_name: Python 3 language: python name: python3 language_info: @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.11 + version: 3.8.11 plotly: description: How to make 2D Histograms in Python with Plotly. display_as: statistical @@ -82,14 +82,17 @@ fig = px.density_heatmap(df, x="total_bill", y="tip", facet_row="sex", facet_col fig.show() ``` -You can add the `z` values as text to 2D Histogram points using `fig.update_traces(texttemplate="%{z}")` +### Displaying Text + +*New in v5.5* + +You can add the `z` values as text using the `text_auto` argument. Setting it to `True` will display the values on the bars, and setting it to a `d3-format` formatting string will control the output format. ```python import plotly.express as px df = px.data.tips() -fig = px.density_heatmap(df, x="total_bill", y="tip") -fig.update_traces(texttemplate="%{z}") +fig = px.density_heatmap(df, x="total_bill", y="tip", text_auto=True) fig.show() ``` diff --git a/doc/python/annotated-heatmap.md b/doc/python/annotated-heatmap.md index eeb08f5920c..becbc0a8ba8 100644 --- a/doc/python/annotated-heatmap.md +++ b/doc/python/annotated-heatmap.md @@ -8,7 +8,7 @@ jupyter: format_version: '1.3' jupytext_version: 1.13.4 kernelspec: - display_name: Python 3 (ipykernel) + display_name: Python 3 language: python name: python3 language_info: @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.11 + version: 3.8.11 plotly: description: How to make Annotated Heatmaps in Python with Plotly. display_as: scientific @@ -34,9 +34,11 @@ jupyter: thumbnail: thumbnail/ann_heat.jpg --- -### Annotated Heatmaps with plotly.express and px.imshow +### Annotated Heatmaps with Plotly Express -These examples use [px.imshow](/python/imshow) to create Annotated Heatmaps. px.imshow is the recommended way to create heatmaps with z-annotations. +*New in v5.5* + +As of version 5.5.0 of `plotly`, the **recommended way to [display annotated heatmaps is to use `px.imshow()`](/python/heatmaps/)** rather than the now-deprecated `create_annotated_heatmap` figure factory documented below for historical reasons. #### Basic Annotated Heatmap for z-annotations @@ -46,33 +48,19 @@ After creating a figure with `px.imshow`, you can add z-annotations with `.updat ```python import plotly.express as px -df = px.data.medals_wide(indexed=True) - -fig = px.imshow(df) -fig.update_traces(texttemplate="%{z}") - -fig.show() -``` - -#### Custom Font - -You can make changes to the font using `textfont`. Here we set the font size to 20. - -```python -import plotly.express as px - -df = px.data.medals_wide(indexed=True) - -fig = px.imshow(df) -fig.update_traces(texttemplate="%{z}") -fig.update_traces(textfont={"size":20}) +z = [[.1, .3, .5, .7, .9], + [1, .8, .6, .4, .2], + [.2, 0, .5, .7, .9], + [.9, .8, .4, .2, 0], + [.3, .4, .5, .7, 1]] +fig = px.imshow(z, text_auto=True) fig.show() ``` -### Annotated Heatmaps with [figure factory](/python/figure-factories/). For more examples with Heatmaps, see [this page](/python/heatmaps/). +### Deprecated Figure Factory -The remaining examples show how to create Annotated Heatmaps with [figure factory](/python/figure-factories/). For more examples with Heatmaps, see [this page](/python/heatmaps/). +The remaining examples show how to create Annotated Heatmaps with the deprecated `create_annotated_heatmap` [figure factory](/python/figure-factories/). #### Simple Annotated Heatmap @@ -90,54 +78,48 @@ fig = ff.create_annotated_heatmap(z) fig.show() ``` -#### Defined Colorscale +#### Custom Text and X & Y Labels +set `annotation_text` to a matrix with the same dimensions as `z` + +> WARNING: this legacy figure factory requires the `y` array to be provided in reverse order, and will map the `z_text` to the `z` values in reverse order. **The use of the `px.imshow()` version below is highly recommended** ```python import plotly.figure_factory as ff -z = [[.1, .3, .5, .7], - [1, .8, .6, .4], - [.6, .4, .2, .0], - [.9, .7, .5, .3]] - -fig = ff.create_annotated_heatmap(z, colorscale='Viridis') -fig.show() -``` - -#### Custom Colorscale +z = [[.1, .3, .5], + [1.0, .8, .6], + [.6, .4, .2]] -```python -import plotly.figure_factory as ff +x = ['Team A', 'Team B', 'Team C'] +y = ['Game Three', 'Game Two', 'Game One'] -z = [[.1, .3, .5, .7], - [1.0, .8, .6, .4], - [.6, .4, .2, 0.0], - [.9, .7, .5, .3]] +z_text = [['Win', 'Lose', 'Win'], + ['Lose', 'Lose', 'Win'], + ['Win', 'Win', 'Lose']] -colorscale = [[0, 'navy'], [1, 'plum']] -font_colors = ['white', 'black'] -fig = ff.create_annotated_heatmap(z, colorscale=colorscale, font_colors=font_colors) +fig = ff.create_annotated_heatmap(z, x=x, y=y, annotation_text=z_text, colorscale='Viridis') fig.show() ``` -#### Custom Text and X & Y Labels -set `annotation_text` to a matrix with the same dimensions as `z` +Here is the same figure using `px.imshow()` ```python -import plotly.figure_factory as ff +import plotly.express as px + +x = ['Team A', 'Team B', 'Team C'] +y = ['Game One', 'Game Two', 'Game Three'] z = [[.1, .3, .5], [1.0, .8, .6], [.6, .4, .2]] -x = ['Team A', 'Team B', 'Team C'] -y = ['Game Three', 'Game Two', 'Game One'] - z_text = [['Win', 'Lose', 'Win'], ['Lose', 'Lose', 'Win'], ['Win', 'Win', 'Lose']] -fig = ff.create_annotated_heatmap(z, x=x, y=y, annotation_text=z_text, colorscale='Viridis') +fig = px.imshow(z, x=x, y=y, color_continuous_scale='Viridis', aspect="auto") +fig.update_traces(text=z_text, texttemplate="%{text}") +fig.update_xaxes(side="top") fig.show() ``` @@ -161,7 +143,20 @@ for i in range(len(fig.layout.annotations)): fig.show() ``` -#### Custom Hovertext +Here is the same figure using `px.imshow()` + +```python +import plotly.express as px +import numpy as np +np.random.seed(1) + +z = np.random.randn(20, 20) + +fig = px.imshow(z, text_auto=".2f", color_continuous_scale='Greys', aspect="auto") +fig.show() +``` + +Here is a fairly contrived example showing how one can display a periodic table with custom text and hover using `ff.create_annotated_heatmap()` (scroll below to see the `px.imshow()` equivalent). ```python # Add Periodic Table Data @@ -180,11 +175,11 @@ symbol = [['H', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', element = [['Hydrogen', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'Helium'], ['Lithium', 'Beryllium', '', '', '', '', '', '', '', '', '', '', 'Boron', 'Carbon', 'Nitrogen', 'Oxygen', 'Fluorine', 'Neon'], - ['Sodium', 'Magnesium', '', '', '', '', '', '', '', '', '', '', 'Aluminium', 'Silicon', 'Phosphorus', 'Sulfur', 'Chlorine', ' Argon'], - ['Potassium', ' Calcium', ' Scandium', ' Titanium', ' Vanadium', ' Chromium', 'Manganese', 'Iron', 'Cobalt', 'Nickel', 'Copper', 'Zinc', 'Gallium', 'Germanium', 'Arsenic', 'Selenium', 'Bromine', 'Krypton'], + ['Sodium', 'Magnesium', '', '', '', '', '', '', '', '', '', '', 'Aluminium', 'Silicon', 'Phosphorus', 'Sulfur', 'Chlorine', 'Argon'], + ['Potassium', 'Calcium', 'Scandium', 'Titanium', 'Vanadium', 'Chromium', 'Manganese', 'Iron', 'Cobalt', 'Nickel', 'Copper', 'Zinc', 'Gallium', 'Germanium', 'Arsenic', 'Selenium', 'Bromine', 'Krypton'], ['Rubidium', 'Strontium', 'Yttrium', 'Zirconium', 'Niobium', 'Molybdenum', 'Technetium', 'Ruthenium', 'Rhodium', 'Palladium', 'Silver', 'Cadmium', 'Indium', 'Tin', 'Antimony', 'Tellurium', 'Iodine', 'Xenon'], - [' Cesium', ' Barium', '', 'Hafnium', 'Tantalum', 'Tungsten', 'Rhenium', 'Osmium', 'Iridium', 'Platinum', 'Gold', 'Mercury', 'Thallium', 'Lead', 'Bismuth', 'Polonium', 'Astatine', 'Radon'], - [' Francium', ' Radium', '', 'Rutherfordium','Dubnium','Seaborgium','Bohrium','Hassium','Meitnerium','Darmstadtium','Roentgenium','Copernicium','Ununtrium','Ununquadium','Ununpentium','Ununhexium','Ununseptium','Ununoctium'], + ['Cesium', 'Barium', '', 'Hafnium', 'Tantalum', 'Tungsten', 'Rhenium', 'Osmium', 'Iridium', 'Platinum', 'Gold', 'Mercury', 'Thallium', 'Lead', 'Bismuth', 'Polonium', 'Astatine', 'Radon'], + ['Francium', 'Radium', '', 'Rutherfordium','Dubnium','Seaborgium','Bohrium','Hassium','Meitnerium','Darmstadtium','Roentgenium','Copernicium','Ununtrium','Ununquadium','Ununpentium','Ununhexium','Ununseptium','Ununoctium'], ['', '', 'Lanthanum', 'Cerium', 'Praseodymium', 'Neodymium', 'Promethium', 'Samarium', 'Europium', 'Gadolinium', 'Terbium', 'Dysprosium', 'Holmium', 'Erbium', 'Thulium', 'Ytterbium', 'Lutetium', ''], ['', '', 'Actinium', 'Thorium', 'Protactinium', 'Uranium', 'Neptunium', 'Plutonium', 'Americium', 'Curium', 'Berkelium', 'Californium', 'Einsteinium','Fermium' ,'Mendelevium', 'Nobelium', 'Lawrencium', '' ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], @@ -204,7 +199,7 @@ atomic_mass = [[ 1.00794, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0 [.0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0], [.0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0]] -z = [[.8, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, 1.], +color = [[.8, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, 1.], [.1, .2, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .7, .8, .8, .8, .9, 1.], [.1, .2, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .6, .7, .8, .8, .9, 1], [.1, .2, .3, .3, .3, .3, .3, .3, .3, .3, .3, .3, .6, .7, .8, .8, .9, 1.], @@ -217,29 +212,44 @@ z = [[.8, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, .0, 1.], [.1, .1, .1, .3, .3, .3, .5, .5, .5, .7, .7, .7, .9, .9, .9, .0, .0, .0], [.2, .2, .2, .4, .4, .4, .6, .6, .6, .8, .8, .8, 1., 1., 1., .0, .0, .0]] -# Display element name and atomic mass on hover -hover=[] -for x in range(len(symbol)): - hover.append([i + '
' + 'Atomic Mass: ' + str(j) - for i, j in zip(element[x], atomic_mass[x])]) - -# Invert Matrices -symbol = symbol[::-1] -hover = hover[::-1] -z = z[::-1] - # Set Colorscale colorscale=[[0.0, 'rgb(255,255,255)'], [.2, 'rgb(255, 255, 153)'], [.4, 'rgb(153, 255, 204)'], [.6, 'rgb(179, 217, 255)'], [.8, 'rgb(240, 179, 255)'],[1.0, 'rgb(255, 77, 148)']] +# Display element name and atomic mass on hover +hover=[] +for x in range(len(symbol)): + hover.append([i + '
' + 'Atomic Mass: ' + str(j) + for i, j in zip(element[x], atomic_mass[x])]) + +import plotly.figure_factory as ff # Make Annotated Heatmap -fig = ff.create_annotated_heatmap(z, annotation_text=symbol, text=hover, +fig = ff.create_annotated_heatmap(color[::-1], annotation_text=symbol[::-1], text=hover[::-1], colorscale=colorscale, font_colors=['black'], hoverinfo='text') fig.update_layout(title_text='Periodic Table') fig.show() ``` +Here is the same output using `px.imshow()` with much less array manipulation: + +```python +import plotly.express as px +import numpy as np + +fig = px.imshow(color, color_continuous_scale=colorscale, aspect="auto", + title='Periodic Table') +fig.update_traces( + text=symbol, texttemplate="%{text}", textfont_size=12, + customdata=np.moveaxis([element, atomic_mass], 0,-1), + hovertemplate="%{customdata[0]}
Atomic Mass: %{customdata[1]:.2f}" +) +fig.update_xaxes(visible=False) +fig.update_yaxes(visible=False) +fig.update_coloraxes(showscale=False) +fig.show() +``` + #### Reference For more info on Plotly heatmaps, see: https://plotly.com/python/reference/heatmap/.
For more info on using colorscales with Plotly see: https://plotly.com/python/heatmap-and-contour-colorscales/
For more info on `ff.create_annotated_heatmap()`, see the [full function reference](https://plotly.com/python-api-reference/generated/plotly.figure_factory.create_annotated_heatmap.html#plotly.figure_factory.create_annotated_heatmap) diff --git a/doc/python/bar-charts.md b/doc/python/bar-charts.md index f02892d6da9..275e7af3ea0 100644 --- a/doc/python/bar-charts.md +++ b/doc/python/bar-charts.md @@ -5,8 +5,8 @@ jupyter: text_representation: extension: .md format_name: markdown - format_version: '1.2' - jupytext_version: 1.4.2 + format_version: '1.3' + jupytext_version: 1.13.4 kernelspec: display_name: Python 3 language: python @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.7 + version: 3.8.11 plotly: description: How to make Bar Charts in Python with Plotly. display_as: basic @@ -37,7 +37,9 @@ jupyter: [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.bar`, each row of the DataFrame is represented as a rectangular mark. +With `px.bar`, **each row of the DataFrame is represented as a rectangular mark**. To aggregate multiple data points into the same rectangular mark, please refer to the [histogram documentation](/python/histograms). + +In the example below, there is only a single row of data per year, so a single bar is displayed per year. ```python import plotly.express as px @@ -98,21 +100,32 @@ snippet_url = 'https://dash-gallery.plotly.host/python-docs-dash-snippets/' IFrame(snippet_url + 'bar-charts', width='100%', height=630) ``` -### Customize bar charts with Plotly Express +### Colored Bars The bar plot can be customized using keyword arguments, for example to use [continuous color](https://plotly.com/python/colorscales/), as below, or [discrete color](/python/discrete-color/), as above. ```python import plotly.express as px -data = px.data.gapminder() -data_canada = data[data.country == 'Canada'] -fig = px.bar(data_canada, x='year', y='pop', +df = px.data.gapminder().query("country == 'Canada'") +fig = px.bar(df, x='year', y='pop', hover_data=['lifeExp', 'gdpPercap'], color='lifeExp', labels={'pop':'population of Canada'}, height=400) fig.show() ``` +```python +import plotly.express as px + +df = px.data.gapminder().query("continent == 'Oceania'") +fig = px.bar(df, x='year', y='pop', + hover_data=['lifeExp', 'gdpPercap'], color='country', + labels={'pop':'population of Canada'}, height=400) +fig.show() +``` + +### Stacked vs Grouped Bars + When several rows share the same value of `x` (here Female or Male), the rectangles are stacked on top of one another by default. ```python @@ -133,6 +146,88 @@ fig = px.bar(df, x="sex", y="total_bill", fig.show() ``` +### Aggregating into Single Colored Bars + +As noted above `px.bar()` will result in **one rectangle drawn per row of input**. This can sometimes result in a striped look as in the examples above. To combine these rectangles into one per color per position, you can use `px.histogram()`, which has [its own detailed documentation page](/python/histogram). + +> `px.bar` and `px.histogram` are designed to be nearly interchangeable in their call signatures, so as to be able to switch between aggregated and disaggregated bar representations. + +```python +import plotly.express as px +df = px.data.tips() +fig = px.histogram(df, x="sex", y="total_bill", + color='smoker', barmode='group', + height=400) +fig.show() +``` + +`px.histogram()` will aggregate `y` values by summing them by default, but the `histfunc` argument can be used to set this to `avg` to create what is sometimes called a "barplot" which summarizes the central tendency of a dataset, rather than visually representing the totality of the dataset. + +> Warning: when using `histfunc`s other than `"sum"` or `"count"` it can be very misleading to use a `barmode` other than `"group"`, as stacked bars in effect represent the sum of the bar heights, and summing averages is rarely a reasonable thing to visualize. + +```python +import plotly.express as px +df = px.data.tips() +fig = px.histogram(df, x="sex", y="total_bill", + color='smoker', barmode='group', + histfunc='avg', + height=400) +fig.show() +``` + +### Bar Charts with Text + +*New in v5.5* + +You can add text to bars using the `text_auto` argument. Setting it to `True` will display the values on the bars, and setting it to a `d3-format` formatting string will control the output format. + +```python +import plotly.express as px +df = px.data.medals_long() + +fig = px.bar(df, x="medal", y="count", color="nation", text_auto=True) +fig.show() +``` + +The `text` argument can be used to display arbitrary text on the bars: + +```python +import plotly.express as px +df = px.data.medals_long() + +fig = px.bar(df, x="medal", y="count", color="nation", text="nation") +fig.show() +``` + +By default, Plotly will scale and rotate text labels to maximize the number of visible labels, which can result in a variety of text angles and sizes and positions in the same figure. The `textfont`, `textposition` and `textangle` trace attributes can be used to control these. + +Here is an example of the default behavior: + +```python +import plotly.express as px + +df = px.data.gapminder().query("continent == 'Europe' and year == 2007 and pop > 2.e6") +fig = px.bar(df, y='pop', x='country', text_auto='.2s', + title="Default: various text sizes, positions and angles") +fig.show() +``` + +Here is the same data with less variation in text formatting. Note that `textfont_size` will set the *maximum* size. The `layout.uniformtext` attribute can be used to guarantee that all text labels are the same size. See the [documentation on text and annotations](/python/text-and-annotations/) for details. + +The `cliponaxis` attribute is set to `False` in the example below to ensure that the outside text on the tallest bar is allowed to render outside of the plotting area. + +```python +import plotly.express as px + +df = px.data.gapminder().query("continent == 'Europe' and year == 2007 and pop > 2.e6") +fig = px.bar(df, y='pop', x='country', text_auto='.2s', + title="Controlled text sizes, positions and angles") +fig.update_traces(textfont_size=12, textangle=0, textposition="outside", cliponaxis=False) +fig.show() +``` + +### Pattern Fills + *New in v5.0* @@ -147,7 +242,7 @@ fig = px.bar(df, x="medal", y="count", color="nation", fig.show() ``` -#### Facetted subplots +### Facetted subplots Use the keyword arguments `facet_row` (resp. `facet_col`) to create facetted subplots, where different rows (resp. columns) correspond to different values of the dataframe column specified in `facet_row`. @@ -161,9 +256,7 @@ fig = px.bar(df, x="sex", y="total_bill", color="smoker", barmode="group", fig.show() ``` -To learn more, see the _link to px.bar reference page_. - -#### Basic Bar Chart with plotly.graph_objects +#### Basic Bar Charts with plotly.graph_objects If Plotly Express does not provide a good starting point, it is also possible to use [the more generic `go.Bar` class from `plotly.graph_objects`](/python/graph-objects/). diff --git a/doc/python/county-choropleth.md b/doc/python/county-choropleth.md index 2fd9366f5a4..ffed5efedc6 100644 --- a/doc/python/county-choropleth.md +++ b/doc/python/county-choropleth.md @@ -41,11 +41,12 @@ This page describes a [legacy "figure factory" method](/python/figure-factories/ #### Required Packages -`geopandas`, `pyshp` and `shapely` must be installed for this figure factory. +`plotly_geo`, `geopandas`, `pyshp` and `shapely` must be installed for this figure factory to run. Run the following commands to install the correct versions of the following modules: ```python +!pip install plotly-geo==1.0.0 !pip install geopandas==0.3.0 !pip install pyshp==1.2.10 !pip install shapely==1.6.3 diff --git a/doc/python/figure-factories.md b/doc/python/figure-factories.md index 2870a963ff5..20fadd7c818 100644 --- a/doc/python/figure-factories.md +++ b/doc/python/figure-factories.md @@ -5,8 +5,8 @@ jupyter: text_representation: extension: .md format_name: markdown - format_version: '1.2' - jupytext_version: 1.3.1 + format_version: '1.3' + jupytext_version: 1.13.4 kernelspec: display_name: Python 3 language: python @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.6.8 + version: 3.8.11 plotly: description: Figure Factories are dedicated functions for creating very specific types of plots. @@ -39,7 +39,6 @@ The `plotly.figure_factory` module contains dedicated functions for creating ver The following types of plots are still difficult to create with Graph Objects or Plotly Express and therefore the corresponding Figure Factories are *not* deprecated: - * [Annotated Heatmaps](/python/annotated-heatmap/) * [Dendrograms](/python/dendrogram/) * [Hexagonal Binning Tile Map](/python/hexbin-mapbox/) * [Quiver Plots](/python/quiver-plots/) @@ -50,6 +49,7 @@ The following types of plots are still difficult to create with Graph Objects or Deprecated "legacy" Figure Factories include: + * [Annotated Heatmaps](/python/annotated-heatmap/), deprecated by [heatmaps with `px.imshow()`](/python/heatmaps/) * [County Choropleth Maps](/python/county-choropleth/), deprecated by regular [Choropleth maps with GeoJSON input](/python/choropleth-maps/) * [Distplots](/python/distplot/), mostly deprecated by [`px.histogram`](/python/histograms/) except for KDE plots, which `px.histogram` doesn't support yet * [Gantt Charts](/python/gantt/), deprecated by [`px.timeline`](/python/gantt/) @@ -57,3 +57,4 @@ Deprecated "legacy" Figure Factories include: #### Reference For more information about the contents of `plotly.figure_factory`, including deprecated methods, please refer to our [API Reference documentation](https://plotly.com/python-api-reference/plotly.figure_factory.html). + diff --git a/doc/python/heatmaps.md b/doc/python/heatmaps.md index 192218aa9c3..f9670081336 100644 --- a/doc/python/heatmaps.md +++ b/doc/python/heatmaps.md @@ -8,7 +8,7 @@ jupyter: format_version: '1.3' jupytext_version: 1.13.4 kernelspec: - display_name: Python 3 (ipykernel) + display_name: Python 3 language: python name: python3 language_info: @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.11 + version: 3.8.11 plotly: description: How to make Heatmaps in Python with Plotly. display_as: scientific @@ -34,11 +34,25 @@ jupyter: thumbnail: thumbnail/heatmap.jpg --- -### Heatmap with `plotly.express` and `px.imshow` +The term "heatmap" usually refers to a cartesian plot with data visualized as colored rectangular tiles, which is the subject of this page. It is also sometimes used to refer to [actual maps with density data displayed as color intensity](/python/mapbox-density-heatmaps/). + +Plotly supports two different types of colored-tile heatmaps: + +1. **Matrix Heatmaps** accept a 2-dimensional matrix or array of data and visualizes it directly. This type of heatmap is the subject of this page. +2. **Density Heatmaps** accept data as a list and visualizes aggregated quantities like counts or sums of this data. Please refer to the [2D Histogram documentation](/python/2D-Histogram/) for this kind of figure. + + +### Heatmaps with 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/). 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). + + +The `px.imshow()` function can be used to display heatmaps (as well as full-color images, as its name suggests). It accepts both array-like objects like lists of lists and `numpy` or `xarray` arrays, as well as `pandas.DataFrame` objects. + + +> For more examples using `px.imshow`, including examples of faceting and animations, as well as full-color image display, see the [the `imshow` documentation page](/python/imshow). + ```python import plotly.express as px @@ -57,6 +71,28 @@ fig = px.imshow(df) fig.show() ``` + +### Displaying Text on Heatmaps + +*New in v5.5* + + +You can add the values to the figure as text using the `text_auto` argument. Setting it to `True` will display the values on the bars, and setting it to a `d3-format` formatting string will control the output format. + + +```python +import plotly.express as px + +z = [[.1, .3, .5, .7, .9], + [1, .8, .6, .4, .2], + [.2, 0, .5, .7, .9], + [.9, .8, .4, .2, 0], + [.3, .4, .5, .7, 1]] + +fig = px.imshow(z, text_auto=True) +fig.show() +``` + #### Heatmaps in Dash [Dash](https://plotly.com/dash/) is the best way to build analytical apps in Python using Plotly figures. To run the app below, run `pip install dash`, click "Download" to get the code and run `python app.py`. @@ -70,6 +106,23 @@ snippet_url = 'https://dash-gallery.plotly.host/python-docs-dash-snippets/' IFrame(snippet_url + 'heatmaps', width='100%', height=630) ``` +### Controlling Aspect Ratio + +By default, `px.imshow()` produces heatmaps with square tiles, but setting the `aspect` argument to `"auto"` will instead fill the plotting area with the heatmap, using non-square tiles. + +```python +import plotly.express as px + +z = [[.1, .3, .5, .7, .9], + [1, .8, .6, .4, .2], + [.2, 0, .5, .7, .9], + [.9, .8, .4, .2, 0], + [.3, .4, .5, .7, 1]] + +fig = px.imshow(z, text_auto=True, aspect="auto") +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: @@ -86,18 +139,16 @@ fig.update_xaxes(side="top") fig.show() ``` -### Adding and customizing text on points +### Display an xarray image with px.imshow -You can add text to heatmap points with `.update_traces(texttemplate="%{variable}")`. Here we use the values of the `z` attribute for `variable`. We also customize the font size with `textfont`. +[xarrays](http://xarray.pydata.org/en/stable/) are labeled arrays (with labeled axes and coordinates). If you pass an xarray image to `px.imshow`, its axes labels and coordinates will be used for axis titles. If you don't want this behavior, you can pass `img.values` which is a NumPy array if `img` is an xarray. Alternatively, you can override axis titles hover labels and colorbar title using the `labels` attribute, as above. ```python import plotly.express as px - -df = px.data.medals_wide(indexed=True) -fig = px.imshow(df) -fig.update_traces(texttemplate="%{z}") -fig.update_traces(textfont={"size":20}) - +import xarray as xr +# Load xarray from dataset included in the xarray tutorial +airtemps = xr.tutorial.open_dataset('air_temperature').air.sel(lon=250.0) +fig = px.imshow(airtemps.T, color_continuous_scale='RdBu_r', origin='lower') fig.show() ``` diff --git a/doc/python/histograms.md b/doc/python/histograms.md index 30f620dd2c1..6ee93d95c7b 100644 --- a/doc/python/histograms.md +++ b/doc/python/histograms.md @@ -8,7 +8,7 @@ jupyter: format_version: '1.3' jupytext_version: 1.13.4 kernelspec: - display_name: Python 3 (ipykernel) + display_name: Python 3 language: python name: python3 language_info: @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.11 + version: 3.8.11 plotly: description: How to make Histograms in Python with Plotly. display_as: statistical @@ -208,15 +208,16 @@ fig = px.histogram(df, x="total_bill", color="sex", marginal="rug", # can be `bo fig.show() ``` -### Adding bar text +### Adding text labels -You can add text to histogram bars using `fig.update_traces(texttemplate="%{variable}")`, where `variable` is the text to add. In this example, we add the y-axis values to the bars. +*New in v5.5* + +You can add text to histogram bars using the `text_auto` argument. Setting it to `True` will display the values on the bars, and setting it to a `d3-format` formatting string will control the output format. ```python import plotly.express as px df = px.data.tips() -fig = px.histogram(df, x="total_bill", y="tip", histfunc='avg', nbins=8) -fig.update_traces(texttemplate="%{y}") +fig = px.histogram(df, x="total_bill", y="tip", histfunc="avg", nbins=8, text_auto=True) fig.show() ``` diff --git a/doc/python/text-and-annotations.md b/doc/python/text-and-annotations.md index d9d7a098291..888fe33559b 100644 --- a/doc/python/text-and-annotations.md +++ b/doc/python/text-and-annotations.md @@ -5,8 +5,8 @@ jupyter: text_representation: extension: .md format_name: markdown - format_version: '1.2' - jupytext_version: 1.6.0 + format_version: '1.3' + jupytext_version: 1.13.4 kernelspec: display_name: Python 3 language: python @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.6 + version: 3.8.11 plotly: description: How to add text labels and annotations to plots in python. display_as: file_settings @@ -116,16 +116,32 @@ snippet_url = 'https://dash-gallery.plotly.host/python-docs-dash-snippets/' IFrame(snippet_url + 'text-and-annotations', width='100%', height=630) ``` -### Controlling text fontsize with uniformtext +### Controlling Text Size with `uniformtext` -For the [pie](/python/pie-charts), [bar](/python/bar-charts), [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/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. + + +Here is a bar chart with the default behavior which will scale down text to fit. ```python import plotly.express as px -df = px.data.gapminder().query("continent == 'Europe' and year == 2007 and pop > 2.e6") -fig = px.bar(df, y='pop', x='country', text='pop') -fig.update_traces(texttemplate='%{text:.2s}', textposition='outside') +df = px.data.gapminder(year=2007) +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() +``` + +Here is the same figure with uniform text applied: the text for all bars is the same size, with a minimum size of 8. Any text at the minimum size which does not fit in the bar is hidden. + +```python +import plotly.express as px + +df = px.data.gapminder(year=2007) +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') fig.show() ``` @@ -140,9 +156,9 @@ fig.update_layout(uniformtext_minsize=12, uniformtext_mode='hide') fig.show() ``` -### Controlling text fontsize with textfont +### Controlling Maximum Text Size -The `textfont_size` parameter of the the [pie](/python/pie-charts), [bar](/python/bar-charts), [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/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. ```python import plotly.express as px diff --git a/packages/python/plotly/plotly/express/_chart_types.py b/packages/python/plotly/plotly/express/_chart_types.py index 3e1f97fc05b..c113a96bd81 100644 --- a/packages/python/plotly/plotly/express/_chart_types.py +++ b/packages/python/plotly/plotly/express/_chart_types.py @@ -103,6 +103,7 @@ def density_contour( histnorm=None, nbinsx=None, nbinsy=None, + text_auto=False, title=None, template=None, width=None, @@ -172,6 +173,7 @@ def density_heatmap( histnorm=None, nbinsx=None, nbinsy=None, + text_auto=False, title=None, template=None, width=None, @@ -353,6 +355,7 @@ def bar( log_y=False, range_x=None, range_y=None, + text_auto=False, title=None, template=None, width=None, @@ -454,6 +457,7 @@ def histogram( histfunc=None, cumulative=None, nbins=None, + text_auto=False, title=None, template=None, width=None, diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 01c789ecab2..2b69b57890b 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -1791,6 +1791,18 @@ def infer_config(args, constructor, trace_patch, layout_patch): ): args["histfunc"] = trace_patch["histfunc"] = "sum" + if args.get("text_auto", False) is not False: + if constructor in [go.Histogram2d, go.Histogram2dContour]: + letter = "z" + elif constructor == go.Bar: + letter = "y" if args["orientation"] == "v" else "x" + else: + letter = "value" + if args["text_auto"] is True: + trace_patch["texttemplate"] = "%{" + letter + "}" + else: + trace_patch["texttemplate"] = "%{" + letter + ":" + args["text_auto"] + "}" + if constructor in [go.Histogram2d, go.Densitymapbox]: show_colorbar = True trace_patch["coloraxis"] = "coloraxis1" diff --git a/packages/python/plotly/plotly/express/_doc.py b/packages/python/plotly/plotly/express/_doc.py index 7d5282ef076..7984549c133 100644 --- a/packages/python/plotly/plotly/express/_doc.py +++ b/packages/python/plotly/plotly/express/_doc.py @@ -591,6 +591,11 @@ "If `'complementary'`, the CCDF is plotted such that values represent data above the point.", "If `'reversed'`, a variant of the CCDF is plotted such that values represent data at or above the point.", ], + text_auto=[ + "bool or string (default `False`)", + "If `True` or a string, the x or y or z values will be displayed as text, depending on the orientation", + "A string like `'.2f'` will be interpreted as a `texttemplate` numeric formatting directive.", + ], ) diff --git a/packages/python/plotly/plotly/express/_imshow.py b/packages/python/plotly/plotly/express/_imshow.py index c255bc32692..afb6460d416 100644 --- a/packages/python/plotly/plotly/express/_imshow.py +++ b/packages/python/plotly/plotly/express/_imshow.py @@ -79,6 +79,7 @@ def imshow( binary_backend="auto", binary_compression_level=4, binary_format="png", + text_auto=False, ): """ Display an image, i.e. data on a 2D regular raster. @@ -208,6 +209,10 @@ def imshow( since it uses lossless compression, but 'jpg' (lossy) compression can result if smaller binary strings for natural images. + text_auto: bool or str (default `False`) + If `True` or a string, single-channel `img` values will be displayed as text. + A string like `'.2f'` will be interpreted as a `texttemplate` numeric formatting directive. + Returns ------- fig : graph_objects.Figure containing the displayed image @@ -385,8 +390,22 @@ def imshow( "The length of the x vector must match the length of the second " + "dimension of the img matrix." ) + + texttemplate = None + if text_auto is True: + texttemplate = "%{z}" + elif text_auto is not False: + texttemplate = "%{z:" + text_auto + "}" + traces = [ - go.Heatmap(x=x, y=y, z=img[index_tup], coloraxis="coloraxis1", name=str(i)) + go.Heatmap( + x=x, + y=y, + z=img[index_tup], + coloraxis="coloraxis1", + name=str(i), + texttemplate=texttemplate, + ) for i, index_tup in enumerate(itertools.product(*iterables)) ] autorange = True if origin == "lower" else "reversed" diff --git a/packages/python/plotly/plotly/figure_factory/_annotated_heatmap.py b/packages/python/plotly/plotly/figure_factory/_annotated_heatmap.py index e6253c43afe..c251234efc2 100644 --- a/packages/python/plotly/plotly/figure_factory/_annotated_heatmap.py +++ b/packages/python/plotly/plotly/figure_factory/_annotated_heatmap.py @@ -59,6 +59,9 @@ def create_annotated_heatmap( **kwargs ): """ + **deprecated**, use instead + :func:`plotly.express.imshow`. + Function that creates annotated heatmaps This function adds annotations to each cell of the heatmap. diff --git a/packages/python/plotly/plotly/figure_factory/_county_choropleth.py b/packages/python/plotly/plotly/figure_factory/_county_choropleth.py index 2a09a09931c..ddd973dfd18 100644 --- a/packages/python/plotly/plotly/figure_factory/_county_choropleth.py +++ b/packages/python/plotly/plotly/figure_factory/_county_choropleth.py @@ -414,6 +414,11 @@ def create_choropleth( **layout_options ): """ + **deprecated**, use instead + :func:`plotly.express.choropleth` with custom GeoJSON. + + This function also requires `shapely`, `geopandas` and `plotly-geo` to be installed. + Returns figure for county choropleth. Uses data from package_data. :param (list) fips: list of FIPS values which correspond to the con diff --git a/packages/python/plotly/plotly/figure_factory/_gantt.py b/packages/python/plotly/plotly/figure_factory/_gantt.py index 8eaa6b0b109..aedb26c2a53 100644 --- a/packages/python/plotly/plotly/figure_factory/_gantt.py +++ b/packages/python/plotly/plotly/figure_factory/_gantt.py @@ -819,6 +819,9 @@ def create_gantt( show_hover_fill=True, ): """ + **deprecated**, use instead + :func:`plotly.express.timeline`. + Returns figure for a gantt chart :param (array|list) df: input data for gantt chart. Must be either a