diff --git a/doc/python/axes.md b/doc/python/axes.md index 59dc8838467..4a5d495c81d 100644 --- a/doc/python/axes.md +++ b/doc/python/axes.md @@ -6,7 +6,7 @@ jupyter: extension: .md format_name: markdown format_version: '1.2' - jupytext_version: 1.3.0 + jupytext_version: 1.4.2 kernelspec: display_name: Python 3 language: python @@ -20,11 +20,10 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.3 + version: 3.7.7 plotly: - description: How to adjust axes properties in python. Includes examples of linear - and logarithmic axes, axes titles, styling and coloring axes and grid lines, - and more. + description: How to adjust axes properties in Python - axes titles, styling and + coloring axes and grid lines, ticks, tick labels and more. display_as: file_settings language: python layout: base @@ -34,7 +33,9 @@ jupyter: thumbnail: thumbnail/axes.png --- -This tutorial explain how to set the properties of 2-dimensional Cartesian axes, namely [`go.layout.XAxis`](/python/reference/layout/xaxis/) and [`go.layout.YAxis`](python/reference/layout/xaxis/). Other kinds of axes are described in other tutorials: +This tutorial explain how to set the properties of [2-dimensional Cartesian axes](/python/figure-structure/#2d-cartesian-trace-types-and-subplots), namely [`go.layout.XAxis`](/python/reference/layout/xaxis/) and [`go.layout.YAxis`](python/reference/layout/xaxis/). + +Other kinds of subplots and axes are described in other tutorials: - [3D axes](/python/3d-axes) The axis object is [`go.layout.Scene`](/python/reference/layout/scene/) - [Polar axes](/python/polar-chart/). The axis object is [`go.layout.Polar`](/python/reference/layout/polar/) @@ -43,123 +44,141 @@ This tutorial explain how to set the properties of 2-dimensional Cartesian axes, - [Mapbox axes](/python/mapbox-layers/). The axis object is [`go.layout.Mapbox`](/python/reference/layout/mapbox/) - [Color axes](/python/colorscales/). The axis object is [`go.layout.Coloraxis`](/python/reference/layout/coloraxis/). -**See also** the tutorials on [subplots](/python/subplots) and [multiple axes](/python/multiple-axes/). +**See also** the tutorials on [facet plots](/python/facet-plots/), [subplots](/python/subplots) and [multiple axes](/python/multiple-axes/). -The different types of Cartesian axes are +### 2-D Cartesian Axis Types and Auto-Detection -- 'linear' -- 'log' (see the [example below](#logarithmic-axes)) -- 'date' (see the [tutorial on timeseries](/python/time-series/)) -- 'category' (see for example [Bar Charts](/python/bar-charts/)) -- 'multicategory' (see the [example below](<#subcategory-(multicategory)-axes>)) +The different types of Cartesian axes are configured via the `xaxis.type` or `yaxis.type` attribute, which can take on the following values: -#### Logarithmic Axes +- `'linear'` as described in this page +- `'log'` (see the [log plot tutorial](/python/log-plots/)) +- `'date'` (see the [tutorial on timeseries](/python/time-series/)) +- `'category'` (see the [categorical axes tutorial](/python/categorical-axes/)) +- `'multicategory'` (see the [categorical axes tutorial](/python/categorical-axes/)) -The `type` axis property can be set to `'log'` to arrange axis ticks in log-scale. +The axis type is auto-detected by looking at data from the first [trace](/python/figure-structure/) linked to this axis: -Here is an example of updating the x and y axes of a figure to be in log scale. +* First check for `multicategory`, then `date`, then `category`, else default to `linear` (`log` is never automatically selected) +* `multicategory` is just a shape test: is the array nested? +* `date` and `category`: require **more than twice as many distinct date or category strings** as distinct numbers or numeric strings in order to choose that axis type. + * Both of these test an evenly-spaced sample of at most 1000 values + * Small detail: the `category` test sorts every value into either number or category, whereas for dates, 2- and 4-digit integers count as both dates and numbers. -```python -import plotly.express as px -import numpy as np -x = np.arange(10) +### Forcing an axis to be categorical -fig = px.scatter(x=x, y=x**3, - log_x=True, log_y=True) +If you pass string values for the `x` or `y` parameter, plotly will automatically set the corresponding axis type to `category`, *except if enough of these strings contain numbers* as detailed above, in which case the axis is automatically set to `linear`. It is however possible to force the axis type by setting explicitely `xaxis_type` to be `category`. +```python +import plotly.express as px +fig = px.bar(x=[1, 2, 4, 10], y =[8, 6, 11, 5]) +fig.update_xaxes(type='category') fig.show() ``` + +#### General Axis properties + +The different groups of Cartesian axes properties are + +- title of the axis +- tick values (locations of tick marks) and tick labels. Tick labels and grid lines are placed at tick values. +- lines: grid lines (passing through tick values), axis lines, zero lines +- range of the axis +- domain of the axis + +The examples on this page apply to axes of any type, but extra attributes are available for [axes of type `category`](/pythone/categorical-axes/) and [axes of type `date`](/python/time-series/). + + +#### Set and Style Axes Title Labels + +##### Set axis title text with Plotly Express + +Axis titles are automatically set to the column names when [using Plotly Express with a data frame as input](/python/px-arguments/). + ```python -import plotly.graph_objects as go +import plotly.express as px +df = px.data.tips() +fig = px.scatter(df, x="total_bill", y="tip", color="sex") +fig.show() +``` -fig = go.Figure(data=[ - go.Scatter( - x=[1, 10, 20, 30, 40, 50, 60, 70, 80], - y=[80, 70, 60, 50, 40, 30, 20, 10, 1] - ), - go.Scatter( - x=[1, 10, 20, 30, 40, 50, 60, 70, 80], - y=[1, 10, 20, 30, 40, 50, 60, 70, 80] - ) -]) - -fig.update_xaxes(type="log") -fig.update_yaxes(type="log") +Axis titles (and [legend titles](/python/legend/)) can also be overridden using the `labels` argument of Plotly Express functions: +```python +import plotly.express as px +df = px.data.tips() +fig = px.scatter(df, x="total_bill", y="tip", color="sex", + labels=dict(total_bill="Total Bill ($)", tip="Tip ($)", sex="Payer Gender") +) fig.show() ``` -### Forcing an axis to be categorical +The PX `labels` argument can also be used without a data frame argument: -If you pass string values for the `x` or `y` parameter, plotly will automatically set the corresponding axis type to `category`, with the exception of string of numbers, in which case the axis is linear. It is however possible to force the axis type by setting explicitely `xaxis_type` to be `category`. ```python import plotly.express as px -fig = px.bar(x=[1, 2, 4, 10], y =[8, 6, 11, 5]) -fig.update_layout(xaxis_type='category', - title_text='Bar chart with categorical axes') +fig = px.bar(df, x=["Apples", "Oranges"], y=[10,20], color=["Here", "There"], + labels=dict(x="Fruit", y="Amount", color="Place") +) fig.show() ``` -#### Subcategory (Multicategory) Axes +##### Set axis title text with Graph Objects -A two-level categorical axis can be created by specifying a trace's `x` or `y` property as a 2-dimensional lists. The first sublist represents the outer categorical value while the second sublist represents the inner categorical value. - -Here is an example that creates a figure with 4 horizontal `box` traces with a 2-level categorical y-axis. +Axis titles are set using the nested `title.text` property of the x or y axis. Here is an example of creating a new figure and using `update_xaxes` and `update_yaxes`, with magic underscore notation, to set the axis titles. ```python -import plotly.graph_objects as go +import plotly.express as px -fig = go.Figure() +fig = px.line(y=[1, 0]) -fig.add_trace(go.Box( - x = [2, 3, 1, 5], - y = [['First', 'First', 'First', 'First'], - ["A", "A", "A", "A"]], - name = "A", - orientation = "h" -)) +fig.update_xaxes(title_text='Time') +fig.update_yaxes(title_text='Value A') -fig.add_trace(go.Box( - x = [8, 3, 6, 5], - y = [['First', 'First', 'First', 'First'], - ["B", "B", "B", "B"]], - name = "B", - orientation = "h" -)) +fig.show() +``` -fig.add_trace(go.Box( - x = [2, 3, 2, 5], - y = [['Second', 'Second', 'Second', 'Second'], - ["C", "C", "C", "C"]], - name = "C", - orientation = "h" -)) +### Set axis title position -fig.add_trace(go.Box( - x = [7.5, 3, 6, 4], - y = [['Second', 'Second', 'Second', 'Second'], - ["D", "D", "D", "D"]], - name = "D", - orientation = "h" -)) +This example sets `standoff` attribute to cartesian axes to determine the distance between the tick labels and the axis title. Note that the axis title position is always constrained within the margins, so the actual standoff distance is always less than the set or default value. By default [automargin](https://plotly.com/python/setting-graph-size/#automatically-adjust-margins) is `True` in Plotly template for the cartesian axis, so the margins will be pushed to fit the axis title at given standoff distance. + +```python +import plotly.graph_objects as go -fig.update_layout(title_text="Multi-category axis",) +fig = go.Figure(go.Scatter( + mode = "lines+markers", + y = [4, 1, 3], + x = ["December", "January", "February"])) + +fig.update_xaxes( + tickangle = 90, + title_text = "Month", + title_font = {"size": 20}, + title_standoff = 25) + +fig.update_yaxes( + title_text = "Temperature", + title_standoff = 25) fig.show() ``` -#### Toggling Axes Lines, Ticks, Labels, and Autorange +##### Set axis title font -The different groups of Cartesian axes properties are +Here is an example that configures the font family, size, and color for the axis titles in a figure created using Plotly Express. -- tick values (locations of tick marks) and tick labels. Tick labels are placed at tick values. -- lines: grid lines (passing through tick values), axis lines, zero lines -- title of the axis -- range of the axis -- domain of the axis +```python +import plotly.express as px +df = px.data.iris() + +fig = px.scatter(df, x="sepal_width", y="sepal_length", facet_col="species") +fig.update_xaxes(title_font=dict(size=18, family='Courier', color='crimson')) +fig.update_yaxes(title_font=dict(size=18, family='Courier', color='crimson')) + +fig.show() +``` #### Tick Placement, Color, and Style @@ -334,7 +353,8 @@ Here is an example of setting `showgrid` to `False` in the graph object figure c import plotly.express as px fig = px.line(y=[1, 0]) -fig.update_layout(xaxis_showgrid=False, yaxis_showgrid=False) +fig.update_xaxes(showgrid=False) +fig.update_yaxes(showgrid=False) fig.show() ``` @@ -347,43 +367,8 @@ import plotly.express as px fig = px.line(y=[1, 0]) -fig.update_layout( - xaxis=dict(showgrid=False, zeroline=False), - yaxis=dict(showgrid=False, zeroline=False), -) -fig.show() -``` - -##### Toggle grid and zerolines with update axis methods - -Axis properties can be also updated for figures after they are constructed using the `update_xaxes` and `update_yaxes` graph object figure methods. - -Here is an example that disables the x and y axis grid and zero lines using `update_xaxes` and `update_yaxes`. - -```python -import plotly.express as px - -fig = px.line(y=[1, 0]) -fig.update_xaxes(showgrid=False, zeroline=False) -fig.update_yaxes(showgrid=False, zeroline=False) - -fig.show() -``` - -##### Toggle grid and zerolines for figure created with Plotly Express - -An advantage of using the `update_xaxis` and `update_yaxis` methods is that these updates will (by default) apply to all axes in the figure. This is especially useful when customizing figures created using Plotly Express, figure factories, or `make_subplots`. - -Here is an example of disabling all grid and zero lines in a faceted figure created by Plotly Express. - -```python -import plotly.express as px -df = px.data.iris() - -fig = px.scatter(df, x="sepal_width", y="sepal_length", facet_col="species") fig.update_xaxes(showgrid=False, zeroline=False) fig.update_yaxes(showgrid=False, zeroline=False) - fig.show() ``` @@ -457,63 +442,6 @@ fig.update_yaxes(zeroline=True, zerolinewidth=2, zerolinecolor='LightPink') fig.show() ``` -#### Set and Style Axes Title Labels - -##### Set axis title text - -Axis titles are set using the nested `title.text` property of the x or y axis. Here is an example of creating a new figure and using `update_xaxes` and `update_yaxes`, with magic underscore notation, to set the axis titles. - -```python -import plotly.express as px - -fig = px.line(y=[1, 0]) - -fig.update_xaxes(title_text='Time') -fig.update_yaxes(title_text='Value A') - -fig.show() -``` - -### Set axis title position - -This example sets `standoff` attribute to cartesian axes to determine the distance between the tick labels and the axis title. Note that the axis title position is always constrained within the margins, so the actual standoff distance is always less than the set or default value. By default [automargin](https://plotly.com/python/setting-graph-size/#automatically-adjust-margins) is `True` in Plotly template for the cartesian axis, so the margins will be pushed to fit the axis title at given standoff distance. - -```python -import plotly.graph_objects as go - -fig = go.Figure(go.Scatter( - mode = "lines+markers", - y = [4, 1, 3], - x = ["December", "January", "February"])) - -fig.update_layout( - xaxis = dict( - tickangle = 90, - title_text = "Month", - title_font = {"size": 20}, - title_standoff = 25), - yaxis = dict( - title_text = "Temperature", - title_standoff = 25)) - -fig.show() -``` - -##### Set axis title font - -Here is an example that configures the font family, size, and color for the axis titles in a figure created using Plotly Express. - -```python -import plotly.express as px -df = px.data.iris() - -fig = px.scatter(df, x="sepal_width", y="sepal_length", facet_col="species") -fig.update_xaxes(title_font=dict(size=18, family='Courier', color='crimson')) -fig.update_yaxes(title_font=dict(size=18, family='Courier', color='crimson')) - -fig.show() -``` - #### Setting the Range of Axes Manually The visible x and y axis range can be configured manually by setting the `range` axis property to a list of two values, the lower and upper boundary. @@ -564,12 +492,12 @@ fig.add_trace(go.Scatter( fig.update_layout( width = 800, height = 500, - title = "fixed-ratio axes", - yaxis = dict( - scaleanchor = "x", - scaleratio = 1, - ) + title = "fixed-ratio axes" ) +fig.update_yaxes( + scaleanchor = "x", + scaleratio = 1, + ) fig.show() ``` @@ -588,15 +516,15 @@ fig.add_trace(go.Scatter( fig.update_layout( width = 800, height = 500, - title = "fixed-ratio axes with compressed axes", - xaxis = dict( - range=[-1,4], # sets the range of xaxis - constrain="domain", # meanwhile compresses the xaxis by decreasing its "domain" - ), - yaxis = dict( - scaleanchor = "x", - scaleratio = 1, - ), + title = "fixed-ratio axes with compressed axes" +) +fig.update_xaxes( + range=[-1,4], # sets the range of xaxis + constrain="domain", # meanwhile compresses the xaxis by decreasing its "domain" +) +fig.update_yaxes( + scaleanchor = "x", + scaleratio = 1 ) fig.show() ``` @@ -618,16 +546,17 @@ fig.add_trace(go.Scatter( fig.update_layout( width = 800, height = 500, - title = "fixed-ratio axes", - yaxis = dict( - scaleanchor = "x", - scaleratio = 1, - ), - xaxis = dict( - range=(-0.5, 3.5), - constrain='domain' - ) + title = "fixed-ratio axes" +) +fig.update_xaxes( + scaleanchor = "x", + scaleratio = 1, ) +fig.update_yaxes( + range=(-0.5, 3.5), + constrain='domain' +) + fig.show() ``` @@ -649,15 +578,15 @@ fig.add_trace(go.Scatter( fig.update_layout( width = 800, height = 500, - title = "fixed-ratio axes with compressed axes", - xaxis = dict( - range=[-1,4], # sets the range of xaxis - constrain="domain", # meanwhile compresses the xaxis by decreasing its "domain" - ), - yaxis = dict( - scaleanchor = "x", - scaleratio = 1, - ), + title = "fixed-ratio axes with compressed axes" +) +fig.update_xaxes( + range=[-1,4], # sets the range of xaxis + constrain="domain", # meanwhile compresses the xaxis by decreasing its "domain" +) +fig.update_yaxes( + scaleanchor = "x", + scaleratio = 1, ) fig.show() @@ -777,4 +706,4 @@ fig.show() #### Reference -See https://plotly.com/python/reference/layout/xaxis/ and https://plotly.com/python/reference/layout/yaxis/ for more information and chart attribute options! \ No newline at end of file +See https://plotly.com/python/reference/layout/xaxis/ and https://plotly.com/python/reference/layout/yaxis/ for more information and chart attribute options! diff --git a/doc/python/bar-charts.md b/doc/python/bar-charts.md index a03237ce155..6403843f23c 100644 --- a/doc/python/bar-charts.md +++ b/doc/python/bar-charts.md @@ -6,7 +6,7 @@ jupyter: extension: .md format_name: markdown format_version: '1.2' - jupytext_version: 1.3.4 + jupytext_version: 1.4.2 kernelspec: display_name: Python 3 language: python @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.7.0 + version: 3.7.7 plotly: description: How to make Bar Charts in Python with Plotly. display_as: basic @@ -112,6 +112,7 @@ fig.show() ```python # Change the default stacking import plotly.express as px +df = px.data.tips() fig = px.bar(df, x="sex", y="total_bill", color='smoker', barmode='group', height=400) @@ -124,6 +125,7 @@ Use the keyword arguments `facet_row` (resp. `facet_col`) to create facetted sub ```python import plotly.express as px +df = px.data.tips() fig = px.bar(df, x="sex", y="total_bill", color="smoker", barmode="group", facet_row="time", facet_col="day", category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], diff --git a/doc/python/categorical-axes.md b/doc/python/categorical-axes.md new file mode 100644 index 00000000000..009e290a703 --- /dev/null +++ b/doc/python/categorical-axes.md @@ -0,0 +1,191 @@ +--- +jupyter: + jupytext: + notebook_metadata_filter: all + text_representation: + extension: .md + format_name: markdown + format_version: '1.2' + jupytext_version: 1.4.2 + kernelspec: + display_name: Python 3 + language: python + name: python3 + language_info: + codemirror_mode: + name: ipython + version: 3 + file_extension: .py + mimetype: text/x-python + name: python + nbconvert_exporter: python + pygments_lexer: ipython3 + version: 3.7.7 + plotly: + description: How to use categorical axes in Python with Plotly. + display_as: basic + language: python + layout: base + name: Categorical Axes + order: 16 + page_type: example_index + permalink: python/categorical-axes/ + thumbnail: thumbnail/bar.jpg +--- + + +This page shows examples of how to configure [2-dimensional Cartesian axes](/python/figure-structure/#2d-cartesian-trace-types-and-subplots) to visualize categorical (i.e. qualitative, nominal or ordinal data as opposed to continuous numerical data). Such axes are a natural fit for bar charts, waterfall charts, funnel charts, heatmaps, violin charts and box plots, but can also be used with scatter plots and line charts. [Configuring gridlines, ticks, tick labels and axis titles](/python/axes/) on logarithmic axes is done the same was as with [linear axes](/python/axes/). + +### 2-D Cartesian Axis Type and Auto-Detection + +The different types of Cartesian axes are configured via the `xaxis.type` or `yaxis.type` attribute, which can take on the following values: + +- `'linear'` (see the [linear axes tutoria](/python/axes/)) +- `'log'` (see the [log plot tutorial](/python/log-plots/)) +- `'date'` (see the [tutorial on timeseries](/python/time-series/)) +- `'category'` see below +- `'multicategory'` see below + +The axis type is auto-detected by looking at data from the first [trace](/python/figure-structure/) linked to this axis: + +* First check for `multicategory`, then `date`, then `category`, else default to `linear` (`log` is never automatically selected) +* `multicategory` is just a shape test: is the array nested? +* `date` and `category`: require **more than twice as many distinct date or category strings** as distinct numbers or numeric strings in order to choose that axis type. + * Both of these test an evenly-spaced sample of at most 1000 values + * Small detail: the `category` test sorts every value into either number or category, whereas for dates, 2- and 4-digit integers count as both dates and numbers. + + +### Forcing an axis to be categorical + +If you pass string values for the `x` or `y` parameter, plotly will automatically set the corresponding axis type to `category`, *except if enough of these strings contain numbers* as detailed above, in which case the axis is automatically set to `linear`. It is however possible to force the axis type by setting explicitely `xaxis_type` to be `category`. + +```python +import plotly.express as px +fig = px.bar(x=[1, 2, 4, 10], y =[8, 6, 11, 5]) +fig.update_xaxes(type='category') +fig.show() +``` + +### Controlling the Category Order 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/). + +By default, Plotly Express lays out categorical data in the order in which it appears in the underlying data. Every 2-d cartesian Plotly Express function also includes a `category_orders` keyword argument which can be used to control the order in which categorical axes are drawn, but beyond that can also control [the order in which discrete colors appear in the legend](/python/discrete-color/), and [the order in which facets are laid out](/python/facet-plots/). + +```python +import plotly.express as px +df = px.data.tips() +fig = px.bar(df, x="day", y="total_bill", color="smoker", barmode="group", facet_col="sex", + category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], + "smoker": ["Yes", "No"], + "sex": ["Male", "Female"]}) +fig.show() +``` + +### Automatically Sorting Categories by Name or Total Value + +Whether using Plotly Express or not, categories can be sorted alphabetically or by value using the `categoryorder` attribute: + +Set `categoryorder` to `"category ascending"` or `"category descending"` for the alphanumerical order of the category names or `"total ascending"` or `"total descending"` for numerical order of values. [categoryorder](https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-categoryorder) for more information. Note that sorting the bars by a particular trace isn't possible right now - it's only possible to sort by the total values. Of course, you can always sort your data _before_ plotting it if you need more customization. + +This example orders the categories **alphabetically** with `categoryorder: 'category ascending'` + +```python +import plotly.graph_objects as go + +x=['b', 'a', 'c', 'd'] +fig = go.Figure(go.Bar(x=x, y=[2,5,1,9], name='Montreal')) +fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa')) +fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto')) + +fig.update_layout(barmode='stack') +fig.update_xaxes(categoryorder='category ascending') +fig.show() +``` + +This example orders the categories **by total value** with `categoryorder: 'total descending'` + +```python +import plotly.graph_objects as go + +x=['b', 'a', 'c', 'd'] +fig = go.Figure(go.Bar(x=x, y=[2,5,1,9], name='Montreal')) +fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa')) +fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto')) + +fig.update_layout(barmode='stack') +fig.update_xaxes(categoryorder='total ascending') +fig.show() +``` + +This example shows how to control category order when using `plotly.graph_objects` by defining `categoryorder` to "array" to derive the ordering from the attribute `categoryarray`. + +```python +import plotly.graph_objects as go + +x=['b', 'a', 'c', 'd'] +fig = go.Figure(go.Bar(x=x, y=[2,5,1,9], name='Montreal')) +fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa')) +fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto')) + +fig.update_layout(barmode='stack') +fig.update_xaxes(categoryorder='array', categoryarray= ['d','a','c','b']) +fig.show() +``` +### Gridlines, Ticks and Tick Labels + + +By default, gridlines and ticks are not shown on categorical axes but they can be activated: + +```python +import plotly.express as px + +fig = px.bar(x=["A","B","C"], y=[1,3,2]) +fig.update_xaxes(showgrid=True, ticks="outside") +fig.show() +``` + +By default, ticks and gridlines appear on the categories but the `tickson` attribute can be used to move them to the category boundaries: + +```python +import plotly.express as px + +fig = px.bar(x=["A","B","C"], y=[1,3,2]) +fig.update_xaxes(showgrid=True, ticks="outside", tickson="boundaries") +fig.show() +``` + +### Multi-categorical Axes + +A two-level categorical axis (also known as grouped or hierarchical categories, or sub-categories) can be created by specifying a trace's `x` or `y` property as a 2-dimensional lists. The first sublist represents the outer categorical value while the second sublist represents the inner categorical value. This is only possible with `plotly.graph_objects` at the moment, and not Plotly Express. + +Passing in a two-dimensional list as the `x` or `y` value of a trace causes [the `type` of the corresponding axis](/python/axes/) to be set to `multicategory`. + +Here is an example that creates a figure with 2 `bar` traces with a 2-level categorical x-axis. + +```python +import plotly.graph_objects as go + +fig = go.Figure() + +fig.add_trace(go.Bar( + x = [['First', 'First', 'Second', 'Second'], + ["A", "B", "A", "B"]], + y = [2, 3, 1, 5], + name = "Adults", +)) + +fig.add_trace(go.Bar( + x = [['First', 'First', 'Second', 'Second'], + ["A", "B", "A", "B"]], + y = [8, 3, 6, 5], + name = "Children", +)) + +fig.update_layout(title_text="Multi-category axis") + +fig.show() +``` +### Reference + +See https://plotly.com/python/reference/layout/xaxis/ for more information and chart attribute options! diff --git a/doc/python/facet-plots.md b/doc/python/facet-plots.md index 94d2d6137da..99859901d50 100644 --- a/doc/python/facet-plots.md +++ b/doc/python/facet-plots.md @@ -107,7 +107,7 @@ fig.show() Since subplot figure titles are [annotations](https://plotly.com/python/text-and-annotations/#simple-annotation), you can use the `for_each_annotation` function to customize them, for example to remove the equal-sign (`=`). -In the following example, we pass a lambda function to `for_each_annotation` in order to change the figure subplot titles from `smoker=No` and `smoker=Yes` to just `No` and `Yes`. +In the following example, we pass a lambda function to `for_each_annotation` in order to change the figure subplot titles from `smoker=No` and `smoker=Yes` to just `No` and `Yes`. ```python import plotly.express as px @@ -117,9 +117,23 @@ fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1])) fig.show() ``` +### Controlling Facet Ordering + +By default, Plotly Express lays out categorical data in the order in which it appears in the underlying data. Every 2-d cartesian Plotly Express function also includes a `category_orders` keyword argument which can be used to control [the order in which categorical axes are drawn](/python/categorical-axes/), but beyond that can also control [the order in which discrete colors appear in the legend](/python/discrete-color/), and the order in which facets are laid out. + +```python +import plotly.express as px +df = px.data.tips() +fig = px.bar(df, x="day", y="total_bill", color="smoker", barmode="group", facet_col="sex", + category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], + "smoker": ["Yes", "No"], + "sex": ["Male", "Female"]}) +fig.show() +``` + ### Controlling Facet Spacing -The `facet_row_spacing` and `facet_col_spacing` arguments can be used to control the spacing between rows and columns. These values are specified in fractions of the plotting area in paper coordinates and not in pixels, so they will grow or shrink with the `width` and `height` of the figure. +The `facet_row_spacing` and `facet_col_spacing` arguments can be used to control the spacing between rows and columns. These values are specified in fractions of the plotting area in paper coordinates and not in pixels, so they will grow or shrink with the `width` and `height` of the figure. The defaults work well with 1-4 rows or columns at the default figure size with the default font size, but need to be reduced to around 0.01 for very large figures or figures with many rows or columns. Conversely, if activating tick labels on all facets, the spacing will need to be increased. @@ -140,7 +154,7 @@ fig.show() ### Synchronizing axes in subplots with `matches` -Using `facet_col` from `plotly.express` let [zoom](https://help.plotly.com/zoom-pan-hover-controls/#step-3-zoom-in-and-zoom-out-autoscale-the-plot) and [pan](https://help.plotly.com/zoom-pan-hover-controls/#step-6-pan-along-axes) each facet to the same range implicitly. However, if the subplots are created with `make_subplots`, the axis needs to be updated with `matches` parameter to update all the subplots accordingly. +Using `facet_col` from `plotly.express` let [zoom](https://help.plotly.com/zoom-pan-hover-controls/#step-3-zoom-in-and-zoom-out-autoscale-the-plot) and [pan](https://help.plotly.com/zoom-pan-hover-controls/#step-6-pan-along-axes) each facet to the same range implicitly. However, if the subplots are created with `make_subplots`, the axis needs to be updated with `matches` parameter to update all the subplots accordingly. Zoom in one trace below, to see the other subplots zoomed to the same x-axis range. To pan all the subplots, click and drag from the center of x-axis to the side: diff --git a/doc/python/figure-factories.md b/doc/python/figure-factories.md index bdee1bd08bd..2ad3c5187ba 100644 --- a/doc/python/figure-factories.md +++ b/doc/python/figure-factories.md @@ -51,9 +51,9 @@ The following types of plots are still difficult to create with Graph Objects or Deprecated "legacy" Figure Factories include: * [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/) + * [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/) #### 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). \ No newline at end of file +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/figure-structure.md b/doc/python/figure-structure.md index 0ccc8f813cd..faa73fb4cd1 100644 --- a/doc/python/figure-structure.md +++ b/doc/python/figure-structure.md @@ -118,7 +118,7 @@ The following trace types are compatible with 2d-cartesian subplots via the `xax * scatter-like trace types: [`scatter`](/python/line-and-scatter/) and [`scattergl`](/python/webgl-vs-svg/), which can be used to draw [scatter plots](/python/line-and-scatter/), [line plots and curves](/python/line-charts/), [time-series plots](/python/time-series/), [bubble charts](/python/bubble-charts/), [dot plots](/python/dot-plots/) and [filled areas](/python/filled-area-plots/) and also support [error bars](/python/error-bars/) * [`bar`](/python/bar-charts/), [`funnel`](/python/funnel-charts/), [`waterfall`](/python/waterfall-charts/): bar-like trace types which can also be used to draw [timelines and Gantt charts](/python/gantt/) * [`histogram`](/python/histograms/): an *aggregating* bar-like trace type -* [`box`](/python/box-plots/) and `violin`: 1-dimensional distribution-like trace types +* [`box`](/python/box-plots/) and [`violin`](/python/box-plots/): 1-dimensional distribution-like trace types * [`histogram2d`](/python/2D-Histogram/) and [`histogram2dcontour`](/python/2d-histogram-contour/): 2-dimensional distribution-like density trace types * [`image`](/python/imshow/), [`heatmap`](/python/heatmaps/) and [`contour`](/python/contour-plots/): matrix trace types * [`ohlc`](/python/ohlc-charts/) and [`candlestick`](/python/candlestick-charts/): stock-like trace types diff --git a/doc/python/histograms.md b/doc/python/histograms.md index 7f37432390e..3d72758005b 100644 --- a/doc/python/histograms.md +++ b/doc/python/histograms.md @@ -30,7 +30,9 @@ jupyter: order: 3 page_type: example_index permalink: python/histograms/ - redirect_from: /python/histogram-tutorial/ + redirect_from: + - /python/histogram-tutorial/ + - /python/histogram/ thumbnail: thumbnail/histogram.jpg --- @@ -392,4 +394,4 @@ fig.show() #### Reference -See https://plotly.com/python/reference/histogram/ for more information and chart attribute options! \ No newline at end of file +See https://plotly.com/python/reference/histogram/ for more information and chart attribute options! diff --git a/doc/python/legend.md b/doc/python/legend.md index 45c13b9af82..65efd16c447 100644 --- a/doc/python/legend.md +++ b/doc/python/legend.md @@ -57,6 +57,46 @@ fig = px.scatter(df, x="total_bill", y="tip", color="sex", symbol="smoker", face fig.show() ``` +### Legend Order + +By default, Plotly Express lays out legend items in the order in which values appear in the underlying data. Every Plotly Express function also includes a `category_orders` keyword argument which can be used to control [the order in which categorical axes are drawn](/python/categorical-axes/), but beyond that can also control the order in which legend items appear, and [the order in which facets are laid out](/python/facet-plots/). + +```python +import plotly.express as px +df = px.data.tips() +fig = px.bar(df, x="day", y="total_bill", color="smoker", barmode="group", facet_col="sex", + category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], + "smoker": ["Yes", "No"], + "sex": ["Male", "Female"]}) +fig.show() +``` + +When using stacked bars, the bars are stacked from the bottom in the same order as they appear in the legend, so it can make sense to set `layout.legend.traceorder` to `"reversed"` to get the legend and stacks to match: + +```python +import plotly.express as px +df = px.data.tips() +fig = px.bar(df, x="day", y="total_bill", color="smoker", barmode="stack", facet_col="sex", + category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], + "smoker": ["Yes", "No"], + "sex": ["Male", "Female"]}) +fig.update_layout(legend_traceorder="reversed") +fig.show() +``` + +When using [`plotly.graph_objects`](/python/graph-objects/) rather than Plotly Express, legend items will appear in the order that traces appear in the `data`: + +```python +import plotly.graph_objects as go + +fig = go.Figure() +fig.add_trace(go.Bar(name="first", x=["a", "b"], y=[1,2])) +fig.add_trace(go.Bar(name="second", x=["a", "b"], y=[2,1])) +fig.add_trace(go.Bar(name="third", x=["a", "b"], y=[1,2])) +fig.add_trace(go.Bar(name="fourth", x=["a", "b"], y=[2,1])) +fig.show() +``` + #### Showing and Hiding the Legend By default the legend is displayed on Plotly charts with multiple traces, and this can be explicitly set with the `layout.showlegend` attribute: @@ -419,4 +459,4 @@ fig.show() #### Reference -See https://plotly.com/python/reference/layout/#layout-legend for more information! \ No newline at end of file +See https://plotly.com/python/reference/layout/#layout-legend for more information! diff --git a/doc/python/log-plot.md b/doc/python/log-plot.md index 3a21e7fed8b..cc4a79c2614 100644 --- a/doc/python/log-plot.md +++ b/doc/python/log-plot.md @@ -5,8 +5,8 @@ jupyter: text_representation: extension: .md format_name: markdown - format_version: '1.1' - jupytext_version: 1.2.0 + format_version: '1.2' + jupytext_version: 1.4.2 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.7.7 plotly: description: How to make Log plots in Python with Plotly. display_as: scientific @@ -32,26 +32,67 @@ jupyter: thumbnail: thumbnail/log.jpg --- -### Logarithmic Axes ### +This page shows examples of how to configure [2-dimensional Cartesian axes](/python/figure-structure/#2d-cartesian-trace-types-and-subplots) to follow a logarithmic rather than linear progression. [Configuring gridlines, ticks, tick labels and axis titles](/python/axes/) on logarithmic axes is done the same was as with [linear axes](/python/axes/). + +### Logarithmic Axes 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/). + +All of Plotly Express' 2-D Cartesian functions include the `log_x` and `log_y` keyword arguments, which can be set to `True` to set the corresponding axis to a logarithmic scale: + +```python +import plotly.express as px +df = px.data.gapminder().query("year == 2007") + +fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country", log_x=True) +fig.show() +``` + +Setting the range of a logarithmic axis with Plotly Express works the same was as with linear axes: using the `range_x` and `range_y` keywords. Note that you cannot set the range to include 0 or less. + +```python +import plotly.express as px +df = px.data.gapminder().query("year == 2007") + +fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country", + log_x=True, range_x=[1,100000], range_y=[0,100]) +fig.show() +``` + +### Logarithmic Axes with Graph Objects + +If Plotly Express does not provide a good starting point, it is also possible to use [the more generic `go.Figure` class from `plotly.graph_objects`](/python/graph-objects/). ```python import plotly.graph_objects as go +import plotly.express as px +df = px.data.gapminder().query("year == 2007") fig = go.Figure() -fig.add_trace(go.Scatter( - x=[0, 1, 2, 3, 4, 5, 6, 7, 8], - y=[8, 7, 6, 5, 4, 3, 2, 1, 0] -)) +fig.add_trace(go.Scatter(mode="markers", x=df["gdpPercap"], y=df["lifeExp"] )) -fig.add_trace(go.Scatter( - x=[0, 1, 2, 3, 4, 5, 6, 7, 8], - y=[0, 1, 2, 3, 4, 5, 6, 7, 8] -)) +fig.update_xaxes(type="log") +fig.show() +``` -fig.update_layout(xaxis_type="log", yaxis_type="log") +Setting the range of a logarithmic axis with `plotly.graph_objects` is *very different* than setting the range of linear axes: the range is set using the exponent rather than the actual value: + + +```python +import plotly.graph_objects as go +import plotly.express as px +df = px.data.gapminder().query("year == 2007") + +fig = go.Figure() + +fig.add_trace(go.Scatter(mode="markers", x=df["gdpPercap"], y=df["lifeExp"] )) + +fig.update_xaxes(type="log", range=[0,5]) # log range: 10^0=1, 10^5=100000 +fig.update_yaxes(range=[0,100]) # linear range fig.show() ``` #### Reference -See https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-type for more information and chart attribute options! \ No newline at end of file + +See https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-type for more information and chart attribute options! diff --git a/doc/python/mapbox-layers.md b/doc/python/mapbox-layers.md index c0409d18310..307c043bdb5 100644 --- a/doc/python/mapbox-layers.md +++ b/doc/python/mapbox-layers.md @@ -116,6 +116,7 @@ fig.update_layout( { "below": 'traces', "sourcetype": "raster", + "sourceattribution": "United States Geological Survey", "source": [ "https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}" ] @@ -147,12 +148,14 @@ fig.update_layout( { "below": 'traces', "sourcetype": "raster", + "sourceattribution": "United States Geological Survey", "source": [ "https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}" ] }, { "sourcetype": "raster", + "sourceattribution": "Government of Canada", "source": ["https://geo.weather.gc.ca/geomet/?" "SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX={bbox-epsg-3857}&CRS=EPSG:3857" "&WIDTH=1000&HEIGHT=1000&LAYERS=RADAR_1KM_RDBR&TILED=true&FORMAT=image/png"], @@ -191,4 +194,4 @@ See the example in the [plotly and datashader tutorial](/python/datashader). #### Reference -See https://plotly.com/python/reference/layout/mapbox/ for more information and options! \ No newline at end of file +See https://plotly.com/python/reference/layout/mapbox/ for more information and options! diff --git a/doc/python/sankey-diagram.md b/doc/python/sankey-diagram.md index 59c2ebe9c18..5ce928345eb 100644 --- a/doc/python/sankey-diagram.md +++ b/doc/python/sankey-diagram.md @@ -199,4 +199,4 @@ fig.show() ### Reference -See [https://plotly.com/python/reference/sankey](https://plotly/.com/python/reference/sankey/) for more information and options! \ No newline at end of file +See [https://plotly.com/python/reference/sankey](https://plotly.com/python/reference/sankey/) for more information and options! diff --git a/doc/python/time-series.md b/doc/python/time-series.md index 4c17ea9203a..797ad1f1550 100644 --- a/doc/python/time-series.md +++ b/doc/python/time-series.md @@ -87,6 +87,8 @@ fig.show() By default, the tick labels (and optional ticks) are associated with a specific grid-line, and represent an *instant* in time, for example, "00:00 on February 1, 2018". Tick labels can be formatted using the `tickformat` attribute (which accepts the [d3 time-format formatting strings](https://github.com/d3/d3-time-format)) to display only the month and year, but they still represent an instant by default, so in the figure below, the text of the label "Feb 2018" spans part of the month of January and part of the month of February. The `dtick` attribute controls the spacing between gridlines, and the `"M1"` setting means "1 month". This attribute also accepts a number of milliseconds, which can be scaled up to days by multiplying by `24*60*60*1000`. +Date axis tick labels have the special property that any portion after the first instance of `'\n'` in `tickformat` will appear on a second line only once per unique value, as with the year numbers in the example below. To have the year number appear on every tick label, `'
'` should be used instead of `'\n'`. + Note that by default, the formatting of values of X and Y values in the hover label matches that of the tick labels of the corresponding axes, so when customizing the tick labels to something broad like "month", it's usually necessary to [customize the hover label](/python/hover-text-and-formatting/) to something narrower like the acutal date, as below. ```python @@ -97,8 +99,7 @@ fig = px.line(df, x="date", y=df.columns, title='custom tick labels') fig.update_xaxes( dtick="M1", - tickformat="%b %Y", - range=["2018-01-01", "2018-12-31"]) + tickformat="%b\n%Y") fig.show() ``` @@ -116,9 +117,8 @@ fig = px.line(df, x="date", y=df.columns, title='custom tick labels with ticklabelmode="period"') fig.update_xaxes( dtick="M1", - tickformat="%b %Y", - ticklabelmode="period", - range=["2018-01-01", "2018-12-31"]) + tickformat="%b\n%Y", + ticklabelmode="period") fig.show() ```