|  | 
|  | 1 | +--- | 
|  | 2 | +jupyter: | 
|  | 3 | +  jupytext: | 
|  | 4 | +    notebook_metadata_filter: all | 
|  | 5 | +    text_representation: | 
|  | 6 | +      extension: .md | 
|  | 7 | +      format_name: markdown | 
|  | 8 | +      format_version: '1.2' | 
|  | 9 | +      jupytext_version: 1.4.2 | 
|  | 10 | +  kernelspec: | 
|  | 11 | +    display_name: Python 3 | 
|  | 12 | +    language: python | 
|  | 13 | +    name: python3 | 
|  | 14 | +  language_info: | 
|  | 15 | +    codemirror_mode: | 
|  | 16 | +      name: ipython | 
|  | 17 | +      version: 3 | 
|  | 18 | +    file_extension: .py | 
|  | 19 | +    mimetype: text/x-python | 
|  | 20 | +    name: python | 
|  | 21 | +    nbconvert_exporter: python | 
|  | 22 | +    pygments_lexer: ipython3 | 
|  | 23 | +    version: 3.7.7 | 
|  | 24 | +  plotly: | 
|  | 25 | +    description: How to use categorical axes in Python with Plotly. | 
|  | 26 | +    display_as: basic | 
|  | 27 | +    language: python | 
|  | 28 | +    layout: base | 
|  | 29 | +    name: Bar Charts | 
|  | 30 | +    order: 16 | 
|  | 31 | +    page_type: example_index | 
|  | 32 | +    permalink: python/bar-charts/ | 
|  | 33 | +    thumbnail: thumbnail/bar.jpg | 
|  | 34 | +--- | 
|  | 35 | + | 
|  | 36 | + | 
|  | 37 | +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/). | 
|  | 38 | + | 
|  | 39 | +### Axis Type and Auto-Detection | 
|  | 40 | + | 
|  | 41 | +The different types of Cartesian axes are configured via the `xaxis.type` or `yaxis.type` attribute, which can take on the following values: | 
|  | 42 | + | 
|  | 43 | +- `'linear'` (see the [linear axes tutoria](/python/axes/)) | 
|  | 44 | +- `'log'` (see the [log plot tutorial](/python/log-plots/)) | 
|  | 45 | +- `'date'` (see the [tutorial on timeseries](/python/time-series/)) | 
|  | 46 | +- `'category'` see below | 
|  | 47 | +- `'multicategory'` see below | 
|  | 48 | + | 
|  | 49 | +The axis type is auto-detected by looking at data from the first [trace](/python/figure-structure/) linked to this axis: | 
|  | 50 | + | 
|  | 51 | +* First check for `multicategory`, then `date`, then `category`, else default to `linear` (`log` is never automatically selected) | 
|  | 52 | +* `multicategory` is just a shape test: is the array nested? | 
|  | 53 | +* `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. | 
|  | 54 | +	* Both of these test an evenly-spaced sample of at most 1000 values | 
|  | 55 | +	* 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. | 
|  | 56 | + | 
|  | 57 | + | 
|  | 58 | +### Forcing an axis to be categorical | 
|  | 59 | + | 
|  | 60 | +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`. | 
|  | 61 | + | 
|  | 62 | +```python | 
|  | 63 | +import plotly.express as px | 
|  | 64 | +fig = px.bar(x=[1, 2, 4, 10], y =[8, 6, 11, 5]) | 
|  | 65 | +fig.update_xaxes(type='category') | 
|  | 66 | +fig.show() | 
|  | 67 | +``` | 
|  | 68 | + | 
|  | 69 | +### Controlling the Category Order with Plotly Express | 
|  | 70 | + | 
|  | 71 | +[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/). | 
|  | 72 | + | 
|  | 73 | +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/). | 
|  | 74 | + | 
|  | 75 | +```python | 
|  | 76 | +import plotly.express as px | 
|  | 77 | +df = px.data.tips() | 
|  | 78 | +fig = px.bar(df, x="day", y="total_bill", color="smoker", barmode="group", facet_col="sex", | 
|  | 79 | +             category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], | 
|  | 80 | +                              "smoker": ["Yes", "No"], | 
|  | 81 | +                              "sex": ["Male", "Female"]}) | 
|  | 82 | +fig.show() | 
|  | 83 | +``` | 
|  | 84 | + | 
|  | 85 | +### Automatically Sorting Categories by Name or Total Value | 
|  | 86 | + | 
|  | 87 | +Whether using Plotly Express or not, categories can be sorted alphabetically or by value using the `categoryorder` attribute: | 
|  | 88 | + | 
|  | 89 | +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. | 
|  | 90 | + | 
|  | 91 | +This example orders the categories **alphabetically** with `categoryorder: 'category ascending'` | 
|  | 92 | + | 
|  | 93 | +```python | 
|  | 94 | +import plotly.graph_objects as go | 
|  | 95 | + | 
|  | 96 | +x=['b', 'a', 'c', 'd'] | 
|  | 97 | +fig = go.Figure(go.Bar(x=x, y=[2,5,1,9], name='Montreal')) | 
|  | 98 | +fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa')) | 
|  | 99 | +fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto')) | 
|  | 100 | + | 
|  | 101 | +fig.update_layout(barmode='stack') | 
|  | 102 | +fig.update_xaxes(categoryorder='category ascending') | 
|  | 103 | +fig.show() | 
|  | 104 | +``` | 
|  | 105 | + | 
|  | 106 | +This example orders the categories **by total value** with `categoryorder: 'total descending'` | 
|  | 107 | + | 
|  | 108 | +```python | 
|  | 109 | +import plotly.graph_objects as go | 
|  | 110 | + | 
|  | 111 | +x=['b', 'a', 'c', 'd'] | 
|  | 112 | +fig = go.Figure(go.Bar(x=x, y=[2,5,1,9], name='Montreal')) | 
|  | 113 | +fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa')) | 
|  | 114 | +fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto')) | 
|  | 115 | + | 
|  | 116 | +fig.update_layout(barmode='stack') | 
|  | 117 | +fig.update_xaxes(categoryorder='total ascending') | 
|  | 118 | +fig.show() | 
|  | 119 | +``` | 
|  | 120 | + | 
|  | 121 | +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`. | 
|  | 122 | + | 
|  | 123 | +```python | 
|  | 124 | +import plotly.graph_objects as go | 
|  | 125 | + | 
|  | 126 | +x=['b', 'a', 'c', 'd'] | 
|  | 127 | +fig = go.Figure(go.Bar(x=x, y=[2,5,1,9], name='Montreal')) | 
|  | 128 | +fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa')) | 
|  | 129 | +fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto')) | 
|  | 130 | + | 
|  | 131 | +fig.update_layout(barmode='stack') | 
|  | 132 | +fig.update_xaxes(categoryorder='array', categoryarray:['d','a','c','b']) | 
|  | 133 | +fig.show() | 
|  | 134 | +``` | 
|  | 135 | +### Gridlines, Ticks and Tick Labels | 
|  | 136 | + | 
|  | 137 | + | 
|  | 138 | +By default, gridlines and ticks are not shown on categorical axes but they can be activated: | 
|  | 139 | + | 
|  | 140 | +```python | 
|  | 141 | +import plotly.express as px | 
|  | 142 | + | 
|  | 143 | +fig = px.bar(x=["A","B","C"], y=[1,3,2]) | 
|  | 144 | +fig.update_xaxes(showgrid=True, ticks="outside") | 
|  | 145 | +fig.show() | 
|  | 146 | +``` | 
|  | 147 | + | 
|  | 148 | +By default, ticks and gridlines appear on the categories but the `tickson` attribute can be used to move them to the category boundaries: | 
|  | 149 | + | 
|  | 150 | +```python | 
|  | 151 | +import plotly.express as px | 
|  | 152 | + | 
|  | 153 | +fig = px.bar(x=["A","B","C"], y=[1,3,2]) | 
|  | 154 | +fig.update_xaxes(showgrid=True, ticks="outside", tickson="boundaries") | 
|  | 155 | +fig.show() | 
|  | 156 | +``` | 
|  | 157 | + | 
|  | 158 | +### Multi-categorical Axes | 
|  | 159 | + | 
|  | 160 | +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. | 
|  | 161 | + | 
|  | 162 | +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`. | 
|  | 163 | + | 
|  | 164 | +Here is an example that creates a figure with 2 `bar` traces with a 2-level categorical x-axis. | 
|  | 165 | + | 
|  | 166 | +```python | 
|  | 167 | +import plotly.graph_objects as go | 
|  | 168 | + | 
|  | 169 | +fig = go.Figure() | 
|  | 170 | + | 
|  | 171 | +fig.add_trace(go.Bar( | 
|  | 172 | +  x = [['First', 'First', 'Second', 'Second'], | 
|  | 173 | +       ["A", "B", "A", "B"]], | 
|  | 174 | +  y = [2, 3, 1, 5], | 
|  | 175 | +  name = "Adults", | 
|  | 176 | +)) | 
|  | 177 | + | 
|  | 178 | +fig.add_trace(go.Bar( | 
|  | 179 | +  x = [['First', 'First', 'Second', 'Second'], | 
|  | 180 | +       ["A", "B", "A", "B"]], | 
|  | 181 | +  y = [8, 3, 6, 5], | 
|  | 182 | +  name = "Children", | 
|  | 183 | +)) | 
|  | 184 | + | 
|  | 185 | +fig.update_layout(title_text="Multi-category axis") | 
|  | 186 | + | 
|  | 187 | +fig.show() | 
|  | 188 | +``` | 
|  | 189 | +### Reference | 
|  | 190 | + | 
|  | 191 | +See https://plotly.com/python/reference/layout/xaxis/ for more information and chart attribute options! | 
0 commit comments