diff --git a/doc/python/dropdowns.md b/doc/python/dropdowns.md index 222b794e80..c43103a630 100644 --- a/doc/python/dropdowns.md +++ b/doc/python/dropdowns.md @@ -365,27 +365,27 @@ fig.add_trace( go.Scatter(x=list(df.Date), y=list(df.High), name="High", - line=dict(color="#33CFA5"))) + line=dict(color="DarkBlue"))) fig.add_trace( go.Scatter(x=list(df.Date), y=[df.High.mean()] * len(df.index), name="High Average", visible=False, - line=dict(color="#33CFA5", dash="dash"))) + line=dict(color="DarkBlue", dash="dash"))) fig.add_trace( go.Scatter(x=list(df.Date), y=list(df.Low), name="Low", - line=dict(color="#F06A6A"))) + line=dict(color="Crimson"))) fig.add_trace( go.Scatter(x=list(df.Date), y=[df.Low.mean()] * len(df.index), name="Low Average", visible=False, - line=dict(color="#F06A6A", dash="dash"))) + line=dict(color="Crimson", dash="dash"))) # Add Annotations and Buttons high_annotations = [dict(x="2016-03-01", diff --git a/doc/python/facet-plots.md b/doc/python/facet-plots.md index 5d0f629b2e..7a79ea06c2 100644 --- a/doc/python/facet-plots.md +++ b/doc/python/facet-plots.md @@ -54,6 +54,8 @@ fig.show() ### Bar Chart Row Facets +There is a more presentation-ready horizontal, faceted bar chart in the [horizontal bar documentation](/python/horizontal-bar-charts/#Small-multiple-horizontal-bar-charts-show-each-component's-size-more-clearly-than-a-stacked-bar) + ```python import plotly.express as px df = px.data.tips() diff --git a/doc/python/graph-objects.md b/doc/python/graph-objects.md index 936ea6d696..878b36d6bf 100644 --- a/doc/python/graph-objects.md +++ b/doc/python/graph-objects.md @@ -68,7 +68,9 @@ Note that the figures produced by Plotly Express **in a single function-call** a The figures produced by Plotly Express can always be built from the ground up using graph objects, but this approach typically takes **5-100 lines of code rather than 1**. -Here is a simple example of how to produce the same figure object from the same data, once with Plotly Express and once without. The data in this example is in "long form" but [Plotly Express also accepts data in "wide form"](/python/wide-form/) and the line-count savings from Plotly Express over graph objects are comparable. More complex figures such as [sunbursts](/python/sunburst-charts/), [parallel coordinates](/python/parallel-coordinates-plot/), [facet plots](/python/facet-plots/) or [animations](/python/animations/) require many more lines of figure-specific graph objects code, whereas switching from one representation to another with Plotly Express usually involves changing just a few characters. +Here is a simple example of how to produce the same figure object from the same data, once with Plotly Express and once without. Note that [Plotly Express functions](/python-api-reference/plotly.express.html) like [`px.bar()`](/python/bar-charts/) can accept a DataFrame as their first argument with column names passed to the `x` and `y` arguments, while [Graph Objects functions](/python-api-reference/plotly.graph_objects.html) like [`go.Bar()`](/python/bar-charts/#basic-bar-charts-with-plotlygraphobjects) require the data values to be passed directly to the `x` and `y` arguments as a tuple, list, NumPy array, or Pandas Series. + +The data in this example is in "long form" but [Plotly Express also accepts data in "wide form"](/python/wide-form/) and the line-count savings from Plotly Express over graph objects are comparable. More complex figures such as [sunbursts](/python/sunburst-charts/), [parallel coordinates](/python/parallel-coordinates-plot/), [facet plots](/python/facet-plots/) or [animations](/python/animations/) require many more lines of figure-specific graph objects code, whereas switching from one representation to another with Plotly Express usually involves changing just a few characters. ```python import pandas as pd diff --git a/doc/python/horizontal-bar-charts.md b/doc/python/horizontal-bar-charts.md index dc8e54a1a4..60a6a28686 100644 --- a/doc/python/horizontal-bar-charts.md +++ b/doc/python/horizontal-bar-charts.md @@ -91,8 +91,8 @@ fig.add_trace(go.Bar( name='SF Zoo', orientation='h', marker=dict( - color='rgba(246, 78, 139, 0.6)', - line=dict(color='rgba(246, 78, 139, 1.0)', width=3) + color='hotpink', + line=dict(color='deeppink', width=3) ) )) fig.add_trace(go.Bar( @@ -101,27 +101,69 @@ fig.add_trace(go.Bar( name='LA Zoo', orientation='h', marker=dict( - color='rgba(58, 71, 80, 0.6)', - line=dict(color='rgba(58, 71, 80, 1.0)', width=3) + color='dimgray', + line=dict(color='black', width=3) ) )) fig.update_layout(barmode='stack') +fig.show() +``` +### Small multiple horizontal bar charts show each component's size more clearly than a stacked bar + +Bar charts with multiple components pose a fundamental trade off between presenting the total clearly and presenting the component values clearly. This small multiples approach shows the component magnitudes clearly at the cost of slightly obscuring the totals. A stacked bar does the opposite. Small multiple bar charts often work better in a horizontal orientation; and are easy to create with the px.bar orientation and facet_col parameters. +```python +import pandas as pd +import plotly.express as px + +data = { + "Quarter": ["Q1", "Q2", "Q3", "Q4"] * 3, + "Region": ["North", "North", "North", "North", "South", "South", "South", "South", "West", "West", "West", "West"], + "Outcome": [150, 200, 250, 300, 120, 180, 240, 310, 100, 150, 220, 280] +} +df = pd.DataFrame(data) + + +fig = px.bar( + df, + x="Outcome", + y="Region", + orientation="h", + facet_col="Quarter", + title="Number of Patients Served by Region and Quarter", + labels={"Outcome": "Patients Served", "Region": "Region"} +) + +## the section below is optional clean up to make this presentation ready + +fig.update_layout( + height=400, #the Plotly default makes the bars awkwardly large; setting a height improves the display + showlegend=False, # the legend does not add anything +) + +# remove the default "facet_variable =" text from the title of each facet graph +fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1])) + +# Remove duplicate axis labels +fig.for_each_yaxis(lambda axis: axis.update(title=None)) +fig.for_each_xaxis(lambda axis: axis.update(title=None)) +# add the one valuable axis label back in +fig.update_xaxes(title="Count", row=1, col=1) + fig.show() ``` ### Color Palette for Bar Chart +This bar chart uses a sequential palette to show gradations of responses. Additional color options for sequential palettes are available at [The Urban Institute](https://urbaninstitute.github.io/graphics-styleguide/#color) and [Colorbrewer](https://colorbrewer2.org/#type=sequential) + ```python import plotly.graph_objects as go top_labels = ['Strongly
agree', 'Agree', 'Neutral', 'Disagree', 'Strongly
disagree'] -colors = ['rgba(38, 24, 74, 0.8)', 'rgba(71, 58, 131, 0.8)', - 'rgba(122, 120, 168, 0.8)', 'rgba(164, 163, 204, 0.85)', - 'rgba(190, 192, 213, 1)'] - +colors = ['DarkBlue', 'MediumBlue', 'DarkSlateBlue', 'mediumpurple', 'thistle'] x_data = [[21, 30, 21, 16, 12], [24, 31, 19, 15, 11], [27, 26, 23, 11, 13], @@ -142,7 +184,7 @@ for i in range(0, len(x_data[0])): orientation='h', marker=dict( color=colors[i], - line=dict(color='rgb(248, 248, 249)', width=1) + line=dict(color='ghostwhite', width=1) ) )) @@ -161,8 +203,8 @@ fig.update_layout( zeroline=False, ), barmode='stack', - paper_bgcolor='rgb(248, 248, 255)', - plot_bgcolor='rgb(248, 248, 255)', + paper_bgcolor='lavenderblush', + plot_bgcolor='lavenderblush', margin=dict(l=120, r=10, t=140, b=80), showlegend=False, ) @@ -176,14 +218,14 @@ for yd, xd in zip(y_data, x_data): xanchor='right', text=str(yd), font=dict(family='Arial', size=14, - color='rgb(67, 67, 67)'), + color='dimgray'), showarrow=False, align='right')) # labeling the first percentage of each bar (x_axis) annotations.append(dict(xref='x', yref='y', x=xd[0] / 2, y=yd, text=str(xd[0]) + '%', font=dict(family='Arial', size=14, - color='rgb(248, 248, 255)'), + color='white'), showarrow=False)) # labeling the first Likert scale (on the top) if yd == y_data[-1]: @@ -191,7 +233,7 @@ for yd, xd in zip(y_data, x_data): x=xd[0] / 2, y=1.1, text=top_labels[0], font=dict(family='Arial', size=14, - color='rgb(67, 67, 67)'), + color='dimgray'), showarrow=False)) space = xd[0] for i in range(1, len(xd)): @@ -200,7 +242,7 @@ for yd, xd in zip(y_data, x_data): x=space + (xd[i]/2), y=yd, text=str(xd[i]) + '%', font=dict(family='Arial', size=14, - color='rgb(248, 248, 255)'), + color='ghostwhite'), showarrow=False)) # labeling the Likert scale if yd == y_data[-1]: @@ -208,7 +250,7 @@ for yd, xd in zip(y_data, x_data): x=space + (xd[i]/2), y=1.1, text=top_labels[i], font=dict(family='Arial', size=14, - color='rgb(67, 67, 67)'), + color='dimgray'), showarrow=False)) space += xd[i] @@ -313,9 +355,9 @@ fig.add_trace(go.Bar( x=y_saving, y=x, marker=dict( - color='rgba(50, 171, 96, 0.6)', + color='mediumseagreen', line=dict( - color='rgba(50, 171, 96, 1.0)', + color='seagreen', width=1), ), name='Household savings, percentage of household disposable income', @@ -325,7 +367,7 @@ fig.add_trace(go.Bar( fig.add_trace(go.Scatter( x=y_net_worth, y=x, mode='lines+markers', - line_color='rgb(128, 0, 128)', + line_color='purple', name='Household net worth, Million USD/capita', ), 1, 2) @@ -341,7 +383,7 @@ fig.update_layout( showgrid=False, showline=True, showticklabels=False, - linecolor='rgba(102, 102, 102, 0.8)', + linecolor='gray', linewidth=2, domain=[0, 0.85], ), @@ -363,8 +405,8 @@ fig.update_layout( ), legend=dict(x=0.029, y=1.038, font_size=10), margin=dict(l=100, r=20, t=70, b=70), - paper_bgcolor='rgb(248, 248, 255)', - plot_bgcolor='rgb(248, 248, 255)', + paper_bgcolor='lavenderblush', + plot_bgcolor='lavenderblush', ) annotations = [] @@ -379,14 +421,14 @@ for ydn, yd, xd in zip(y_nw, y_s, x): y=xd, x=ydn - 20000, text='{:,}'.format(ydn) + 'M', font=dict(family='Arial', size=12, - color='rgb(128, 0, 128)'), + color='purple'), showarrow=False)) # labeling the bar net worth annotations.append(dict(xref='x1', yref='y1', y=xd, x=yd + 3, text=str(yd) + '%', - font=dict(family='Arial', size=12, - color='rgb(50, 171, 96)'), + font=dict(family='Arial', size=16, + color='mediumseagreen'), showarrow=False)) # Source annotations.append(dict(xref='paper', yref='paper', @@ -395,7 +437,7 @@ annotations.append(dict(xref='paper', yref='paper', '(2015), Household savings (indicator), ' + 'Household net worth (indicator). doi: ' + '10.1787/cfc6f499-en (Accessed on 05 June 2015)', - font=dict(family='Arial', size=10, color='rgb(150,150,150)'), + font=dict(family='Arial', size=10, color='gray'), showarrow=False)) fig.update_layout(annotations=annotations) diff --git a/plotly/express/_doc.py b/plotly/express/_doc.py index 8754e5265b..59faac4c0b 100644 --- a/plotly/express/_doc.py +++ b/plotly/express/_doc.py @@ -612,7 +612,12 @@ def make_docstring(fn, override_dict=None, append_dict=None): override_dict = {} if override_dict is None else override_dict append_dict = {} if append_dict is None else append_dict - tw = TextWrapper(width=75, initial_indent=" ", subsequent_indent=" ") + tw = TextWrapper( + width=75, + initial_indent=" ", + subsequent_indent=" ", + break_on_hyphens=False, + ) result = (fn.__doc__ or "") + "\nParameters\n----------\n" for param in getfullargspec(fn)[0]: if override_dict.get(param):