Spaces:
Running
Running
Update version
Browse files- README.md +64 -65
- app.py +1 -2
- chart_groups.py +0 -3
- custom_charts.py +56 -2
- pages/_factories.py +46 -1
- pages/examples/diverging_stacked_bar.py +7 -3
- pages/examples/lollipop.py +42 -0
- pages/examples/sparkline.py +16 -0
- pages/magnitude.py +11 -1
- pages/ranking.py +4 -1
- pages/time.py +49 -8
README.md
CHANGED
@@ -47,80 +47,79 @@ Credits and sources:
|
|
47 |
|
48 |
The dashboard is still in development. Below is an overview of the chart types for which a completed page is available.
|
49 |
|
50 |
-
| Chart Type |
|
51 |
-
| --------------------- |
|
52 |
-
| Arc | β
|
53 |
-
| Area | β
|
54 |
-
| Bar | β
|
55 |
-
| Barcode | β
|
56 |
-
| Beeswarm | β
|
57 |
-
| Boxplot | β
|
58 |
-
| Bubble | β
|
59 |
-
| Bubble map | β
|
60 |
-
| Bubble timeline | β
|
61 |
-
| Bullet | β
|
62 |
-
| Bump | β
|
63 |
-
| Butterfly | β
|
64 |
-
| Chord | β
|
65 |
-
| Choropleth | β
|
66 |
-
| Column | β
|
67 |
-
| Column and line | β
|
68 |
-
| Connected scatter | β
|
69 |
-
| Cumulative curve | β
|
70 |
-
| Diverging bar | β
|
71 |
-
| Diverging stacked bar | β
|
72 |
-
| Donut | β
|
73 |
-
| Dot map | β
|
74 |
-
| Dumbbell | β
|
75 |
-
| Fan | β
|
76 |
-
| Flow map | β
|
77 |
-
| Funnel | β
|
78 |
-
| Gantt | β
|
79 |
-
| Gridplot | β
|
80 |
-
| Heatmap | β
|
81 |
-
| Correlation matrix | β
|
82 |
-
| Histogram | β
|
83 |
-
| Line | β
|
84 |
-
| Lollipop |
|
85 |
-
| Marimekko | β
|
86 |
-
| Network | β
|
87 |
-
| Ordered bar | β
|
88 |
-
| Ordered bubble | β
|
89 |
-
| Ordered column | β
|
90 |
-
| Paired bar | β
|
91 |
-
| Paired column | β
|
92 |
-
| Parallel coordinates | β
|
93 |
-
| Pictogram | β
|
94 |
-
| Pie | β
|
95 |
-
| Radar | β
|
96 |
-
| Radial | β
|
97 |
-
| Sankey | β
|
98 |
-
| Scatter | β
|
99 |
-
| Scatter matrix | β
|
100 |
-
| Slope | β
|
101 |
-
| Sparkline |
|
102 |
-
| Stacked bar | β
|
103 |
-
| Stacked column | β
|
104 |
-
| Stepped line | β
|
105 |
-
| Surplus deficit line | β
|
106 |
-
| Treemap | β
|
107 |
-
| Venn | β
|
108 |
-
| Violin | β
|
109 |
-
| Waterfall | β
|
110 |
|
111 |
## How to contribute
|
112 |
|
113 |
Contributions are welcome! To contribute a chart, follow the steps below:
|
114 |
|
115 |
1. Check that a `svg` file named after the chart type is contained in the [assets](https://github.com/mckinsey/vizro/tree/main/vizro-core/examples/visual-vocabulary/assets/images/charts) folder. If not, [raise an issue](https://github.com/mckinsey/vizro/issues) in the repository.
|
116 |
-
2. Add
|
117 |
3. Create a new page for the chart type and add it to the relevant category `.py` file such as `correlation.py`,
|
118 |
`deviation.py`, `distribution.py`, etc. Ensure you add the page to the list of `pages` at the end of the `.py` file.
|
119 |
-
4.
|
120 |
-
5.
|
121 |
-
6. Update this `README.md` with the new chart type, its status, category, and API links.
|
122 |
|
123 |
## How to run the example locally
|
124 |
|
125 |
1. Run the example with the command `hatch run example visual-vocabulary`.
|
126 |
-
2. You should now be able to access the app locally via http://127.0.0.1:
|
|
|
47 |
|
48 |
The dashboard is still in development. Below is an overview of the chart types for which a completed page is available.
|
49 |
|
50 |
+
| Chart Type | Done | Category | Credits & sources | API |
|
51 |
+
| --------------------- | ---- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
52 |
+
| Arc | β | Part-to-whole | | |
|
53 |
+
| Area | β
| Time | [Filled area plot with px](https://plotly.com/python/filled-area-plots/) | [px.area](https://plotly.com/python-api-reference/generated/plotly.express.area) |
|
54 |
+
| Bar | β
| Magnitude | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar) |
|
55 |
+
| Barcode | β | Distribution | | |
|
56 |
+
| Beeswarm | β | Distribution | | |
|
57 |
+
| Boxplot | β
| Distribution | [Box plot with px](https://plotly.com/python/box-plots/) | [px.box](https://plotly.github.io/plotly.py-docs/generated/plotly.express.box) |
|
58 |
+
| Bubble | β
| Correlation | [Scatter plot with px](https://plotly.com/python/line-and-scatter/) | [px.scatter](https://plotly.com/python-api-reference/generated/plotly.express.scatter) |
|
59 |
+
| Bubble map | β
| Spatial | [Bubble map in px](https://plotly.com/python/bubble-maps/) | [px.scatter_map](https://plotly.github.io/plotly.py-docs/generated/plotly.express.scatter_map) |
|
60 |
+
| Bubble timeline | β | Time | | |
|
61 |
+
| Bullet | β | Magnitude | | |
|
62 |
+
| Bump | β | Ranking | | |
|
63 |
+
| Butterfly | β
| Deviation, Distribution | [Pyramid charts in Plotly](https://plotly.com/python/v3/population-pyramid-charts/) | [go.Bar](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Bar.html) |
|
64 |
+
| Chord | β | Flow | | |
|
65 |
+
| Choropleth | β
| Spatial | [Choropleth map with px](https://plotly.com/python/choropleth-maps/) | [px.choropleth](https://plotly.github.io/plotly.py-docs/generated/plotly.express.choropleth.html) |
|
66 |
+
| Column | β
| Magnitude, Time | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar.html) |
|
67 |
+
| Column and line | β
| Correlation, Time | [Multiple chart types in Plotly](https://plotly.com/python/graphing-multiple-chart-types/) | [go.Bar](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Bar.html) and [go.Scatter](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Scatter.html) |
|
68 |
+
| Connected scatter | β
| Correlation, Time | [Line plot with px](https://plotly.com/python/line-charts/) | [px.line](https://plotly.com/python-api-reference/generated/plotly.express.line) |
|
69 |
+
| Cumulative curve | β | Distribution | | |
|
70 |
+
| Diverging bar | β
| Deviation | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar) |
|
71 |
+
| Diverging stacked bar | β
| Deviation | [Plotly forum - diverging stacked bar](https://community.plotly.com/t/need-help-in-making-diverging-stacked-bar-charts/34023/2) | [go.Bar](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Bar.html) |
|
72 |
+
| Donut | β
| Part-to-whole | [Pie chart with px](https://plotly.com/python/pie-charts/) | [px.pie](https://plotly.com/python-api-reference/generated/plotly.express.pie) |
|
73 |
+
| Dot map | β
| Spatial | [Bubble map in px](https://plotly.com/python/bubble-maps/) | [px.scatter_map](https://plotly.github.io/plotly.py-docs/generated/plotly.express.scatter_map) |
|
74 |
+
| Dumbbell | β
| Distribution | [Dumbbell plots in Plotly](https://community.plotly.com/t/how-to-make-dumbbell-plots-in-plotly-python/47762) | [px.scatter](https://plotly.com/python-api-reference/generated/plotly.express.scatter.html) and [add_shape](https://plotly.com/python/shapes/) |
|
75 |
+
| Fan | β | Time | | |
|
76 |
+
| Flow map | β | Spatial | | |
|
77 |
+
| Funnel | β
| Part-to-whole | [Funnel plot with px](https://plotly.com/python/funnel-charts/) | [px.funnel](https://plotly.com/python/funnel-charts/) |
|
78 |
+
| Gantt | β
| Time | [Gantt chart with px](https://plotly.com/python/gantt/) | [px.timeline](https://plotly.com/python-api-reference/generated/plotly.express.timeline.html) |
|
79 |
+
| Gridplot | β | Part-to-whole | | |
|
80 |
+
| Heatmap | β
| Time | [Heatmaps with px](https://plotly.com/python/heatmaps/) | [px.density_heatmap](https://plotly.com/python-api-reference/generated/plotly.express.density_heatmap.html) |
|
81 |
+
| Correlation matrix | β | Correlation | | |
|
82 |
+
| Histogram | β
| Distribution | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
|
83 |
+
| Line | β
| Time | [Line plot with px](https://plotly.com/python/line-charts/) | [px.line](https://plotly.com/python-api-reference/generated/plotly.express.line) |
|
84 |
+
| Lollipop | β
| Ranking, Magnitude | [Lollipop & Dumbbell Charts with Plotly](https://towardsdatascience.com/lollipop-dumbbell-charts-with-plotly-696039d5f85) | [px.scatter](https://plotly.com/python-api-reference/generated/plotly.express.scatter) |
|
85 |
+
| Marimekko | β | Magnitude, Part-to-whole | | |
|
86 |
+
| Network | β | Flow | | |
|
87 |
+
| Ordered bar | β
| Ranking | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar.html) |
|
88 |
+
| Ordered bubble | β | Ranking | | |
|
89 |
+
| Ordered column | β
| Ranking | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar.html) |
|
90 |
+
| Paired bar | β
| Magnitude | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
|
91 |
+
| Paired column | β
| Magnitude | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
|
92 |
+
| Parallel coordinates | β
| Magnitude | [Parallel coordinates plot with px](https://plotly.com/python/parallel-coordinates-plot/) | [px.parallel_coordinates](https://plotly.com/python-api-reference/generated/plotly.express.parallel_coordinates.html) |
|
93 |
+
| Pictogram | β | Magnitude | | |
|
94 |
+
| Pie | β
| Part-to-whole | [Pie chart with px](https://plotly.com/python/pie-charts/) | [px.pie](https://plotly.com/python-api-reference/generated/plotly.express.pie) |
|
95 |
+
| Radar | β
| Magnitude | [Radar chart with px](https://plotly.com/python/radar-chart/) | [px.line_polar](https://plotly.com/python-api-reference/generated/plotly.express.line_polar) |
|
96 |
+
| Radial | β | Magnitude | | |
|
97 |
+
| Sankey | β
| Flow | [Sankey diagram in Plotly](https://plotly.com/python/sankey-diagram/) | [go.Sankey](https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.Sankey.html) |
|
98 |
+
| Scatter | β
| Correlation | [Scatter plot with px](https://plotly.com/python/line-and-scatter/) | [px.scatter](https://plotly.com/python-api-reference/generated/plotly.express.scatter) |
|
99 |
+
| Scatter matrix | β
| Correlation | [Scatter matrix with px](https://plotly.com/python/splom/) | [px.scatter_matrix](https://plotly.github.io/plotly.py-docs/generated/plotly.express.scatter_matrix.html) |
|
100 |
+
| Slope | β | Ranking, Time | | |
|
101 |
+
| Sparkline | β
| Time | [Sparklines with px](https://plotly.com/python/line-charts/#sparklines-with-plotly-express) | [px.line](https://plotly.com/python-api-reference/generated/plotly.express.line) or [px.area](https://plotly.com/python-api-reference/generated/plotly.express.area) |
|
102 |
+
| Stacked bar | β
| Part-to-whole | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
|
103 |
+
| Stacked column | β
| Part-to-whole | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
|
104 |
+
| Stepped line | β
| Time | [Line plot with px](https://plotly.com/python/line-charts/) | [px.line](https://plotly.com/python-api-reference/generated/plotly.express.line) |
|
105 |
+
| Surplus deficit line | β | Deviation | | |
|
106 |
+
| Treemap | β
| Part-to-whole | [Treemap with px](https://plotly.com/python/treemaps/) | [px.treemap](https://plotly.com/python-api-reference/generated/plotly.express.treemap.html) |
|
107 |
+
| Venn | β | Part-to-whole | | |
|
108 |
+
| Violin | β
| Distribution | [Violin plot with px](https://plotly.com/python/violin/) | [px.violin](https://plotly.com/python-api-reference/generated/plotly.express.violin.html) |
|
109 |
+
| Waterfall | β
| Part-to-whole, Flow | [Waterfall charts in Plotly](https://plotly.com/python/waterfall-charts/) | [go.Waterfall](https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.Waterfall.html) |
|
110 |
|
111 |
## How to contribute
|
112 |
|
113 |
Contributions are welcome! To contribute a chart, follow the steps below:
|
114 |
|
115 |
1. Check that a `svg` file named after the chart type is contained in the [assets](https://github.com/mckinsey/vizro/tree/main/vizro-core/examples/visual-vocabulary/assets/images/charts) folder. If not, [raise an issue](https://github.com/mckinsey/vizro/issues) in the repository.
|
116 |
+
2. Add a `.py` file containing a code example of the chart type in the `pages/examples` folder, for instance, `area.py`. Take a look at existing examples.
|
117 |
3. Create a new page for the chart type and add it to the relevant category `.py` file such as `correlation.py`,
|
118 |
`deviation.py`, `distribution.py`, etc. Ensure you add the page to the list of `pages` at the end of the `.py` file.
|
119 |
+
4. Remove the `IncompletePage(..)` entry for that chart type in `chart_groups.py`.
|
120 |
+
5. Update this `README.md` with the new chart type, its status, category, and API links.
|
|
|
121 |
|
122 |
## How to run the example locally
|
123 |
|
124 |
1. Run the example with the command `hatch run example visual-vocabulary`.
|
125 |
+
2. You should now be able to access the app locally via http://127.0.0.1:8051/.
|
app.py
CHANGED
@@ -2,11 +2,11 @@
|
|
2 |
|
3 |
from typing import Union
|
4 |
|
5 |
-
from dash import html, get_asset_url
|
6 |
import dash_bootstrap_components as dbc
|
7 |
import vizro.models as vm
|
8 |
from chart_groups import ALL_CHART_GROUP, CHART_GROUPS, ChartGroup, IncompletePage
|
9 |
from custom_components import FlexContainer, Markdown
|
|
|
10 |
from vizro import Vizro
|
11 |
|
12 |
|
@@ -115,7 +115,6 @@ app.dash.layout.children.append(
|
|
115 |
["Made with ", html.Img(src=get_asset_url("logo.svg"), id="banner", alt="Vizro logo"), "vizro"],
|
116 |
href="https://github.com/mckinsey/vizro",
|
117 |
target="_blank",
|
118 |
-
external_link=True,
|
119 |
className="anchor-container",
|
120 |
)
|
121 |
)
|
|
|
2 |
|
3 |
from typing import Union
|
4 |
|
|
|
5 |
import dash_bootstrap_components as dbc
|
6 |
import vizro.models as vm
|
7 |
from chart_groups import ALL_CHART_GROUP, CHART_GROUPS, ChartGroup, IncompletePage
|
8 |
from custom_components import FlexContainer, Markdown
|
9 |
+
from dash import get_asset_url, html
|
10 |
from vizro import Vizro
|
11 |
|
12 |
|
|
|
115 |
["Made with ", html.Img(src=get_asset_url("logo.svg"), id="banner", alt="Vizro logo"), "vizro"],
|
116 |
href="https://github.com/mckinsey/vizro",
|
117 |
target="_blank",
|
|
|
118 |
className="anchor-container",
|
119 |
)
|
120 |
)
|
chart_groups.py
CHANGED
@@ -81,7 +81,6 @@ ranking_chart_group = ChartGroup(
|
|
81 |
incomplete_pages=[
|
82 |
IncompletePage("Ordered bubble"),
|
83 |
IncompletePage("Slope"),
|
84 |
-
IncompletePage("Lollipop"),
|
85 |
IncompletePage("Bump"),
|
86 |
],
|
87 |
icon="Stacked Bar Chart",
|
@@ -117,7 +116,6 @@ magnitude_chart_group = ChartGroup(
|
|
117 |
pages=pages.magnitude.pages,
|
118 |
incomplete_pages=[
|
119 |
IncompletePage("Marimekko"),
|
120 |
-
IncompletePage("Lollipop"),
|
121 |
IncompletePage("Pictogram"),
|
122 |
IncompletePage("Bullet"),
|
123 |
IncompletePage("Radial"),
|
@@ -138,7 +136,6 @@ time_chart_group = ChartGroup(
|
|
138 |
IncompletePage("Slope"),
|
139 |
IncompletePage("Fan"),
|
140 |
IncompletePage("Bubble timeline"),
|
141 |
-
IncompletePage("Sparkline"),
|
142 |
],
|
143 |
icon="Timeline",
|
144 |
intro_text=time_intro_text,
|
|
|
81 |
incomplete_pages=[
|
82 |
IncompletePage("Ordered bubble"),
|
83 |
IncompletePage("Slope"),
|
|
|
84 |
IncompletePage("Bump"),
|
85 |
],
|
86 |
icon="Stacked Bar Chart",
|
|
|
116 |
pages=pages.magnitude.pages,
|
117 |
incomplete_pages=[
|
118 |
IncompletePage("Marimekko"),
|
|
|
119 |
IncompletePage("Pictogram"),
|
120 |
IncompletePage("Bullet"),
|
121 |
IncompletePage("Radial"),
|
|
|
136 |
IncompletePage("Slope"),
|
137 |
IncompletePage("Fan"),
|
138 |
IncompletePage("Bubble timeline"),
|
|
|
139 |
],
|
140 |
icon="Timeline",
|
141 |
intro_text=time_intro_text,
|
custom_charts.py
CHANGED
@@ -290,12 +290,18 @@ def diverging_stacked_bar(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
|
|
290 |
orientation = fig.data[0].orientation
|
291 |
x_or_y = "x" if orientation == "h" else "y"
|
292 |
|
293 |
-
for trace_idx in range(len(fig.data) // 2):
|
294 |
fig.update_traces({f"{x_or_y}axis": f"{x_or_y}2"}, selector=trace_idx)
|
295 |
|
|
|
|
|
|
|
296 |
fig.update_layout({f"{x_or_y}axis2": fig.layout[f"{x_or_y}axis"]})
|
297 |
fig.update_layout(
|
298 |
-
{
|
|
|
|
|
|
|
299 |
)
|
300 |
|
301 |
if orientation == "h":
|
@@ -304,3 +310,51 @@ def diverging_stacked_bar(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
|
|
304 |
fig.add_hline(y=0, line_width=2, line_color="grey")
|
305 |
|
306 |
return fig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
orientation = fig.data[0].orientation
|
291 |
x_or_y = "x" if orientation == "h" else "y"
|
292 |
|
293 |
+
for trace_idx in range(len(fig.data) // 2, len(fig.data)):
|
294 |
fig.update_traces({f"{x_or_y}axis": f"{x_or_y}2"}, selector=trace_idx)
|
295 |
|
296 |
+
# Add ticksuffix and range limitations on both sids for correct interpretation of diverging stacked bar
|
297 |
+
# with percentage data
|
298 |
+
fig.update_layout({f"{x_or_y}axis": {"ticksuffix": "%"}})
|
299 |
fig.update_layout({f"{x_or_y}axis2": fig.layout[f"{x_or_y}axis"]})
|
300 |
fig.update_layout(
|
301 |
+
{
|
302 |
+
f"{x_or_y}axis": {"domain": [0, 0.5], "range": [100, 0]},
|
303 |
+
f"{x_or_y}axis2": {"domain": [0.5, 1], "range": [0, 100]},
|
304 |
+
}
|
305 |
)
|
306 |
|
307 |
if orientation == "h":
|
|
|
310 |
fig.add_hline(y=0, line_width=2, line_color="grey")
|
311 |
|
312 |
return fig
|
313 |
+
|
314 |
+
|
315 |
+
@capture("graph")
|
316 |
+
def lollipop(data_frame: pd.DataFrame, **kwargs):
|
317 |
+
"""Creates a lollipop based on px.scatter.
|
318 |
+
|
319 |
+
A lollipop chart is a variation of a bar chart where each data point is represented by a line and a dot at the end
|
320 |
+
to mark the value.
|
321 |
+
|
322 |
+
Inspired by: https://towardsdatascience.com/lollipop-dumbbell-charts-with-plotly-696039d5f85
|
323 |
+
|
324 |
+
Args:
|
325 |
+
data_frame: DataFrame for the chart. Can be long form or wide form.
|
326 |
+
See https://plotly.com/python/wide-form/.
|
327 |
+
**kwargs: Keyword arguments to pass into px.scatter (e.g. x, y, labels).
|
328 |
+
See https://plotly.com/python-api-reference/generated/plotly.scatter.html.
|
329 |
+
|
330 |
+
Returns:
|
331 |
+
go.Figure: Lollipop chart.
|
332 |
+
"""
|
333 |
+
# Plots the dots of the lollipop chart
|
334 |
+
fig = px.scatter(data_frame, **kwargs)
|
335 |
+
|
336 |
+
# Enables the orientation of the chart to be either horizontal or vertical
|
337 |
+
orientation = fig.data[0].orientation
|
338 |
+
x_or_y = "x" if orientation == "h" else "y"
|
339 |
+
y_or_x = "y" if orientation == "h" else "x"
|
340 |
+
|
341 |
+
# Plots the lines of the lollipop chart
|
342 |
+
for x_or_y_value, y_or_x_value in zip(fig.data[0][x_or_y], fig.data[0][y_or_x]):
|
343 |
+
fig.add_trace(go.Scatter({x_or_y: [0, x_or_y_value], y_or_x: [y_or_x_value, y_or_x_value], "mode": "lines"}))
|
344 |
+
|
345 |
+
# Styles the lollipop chart and makes it uni-colored
|
346 |
+
fig.update_traces(
|
347 |
+
marker_size=12,
|
348 |
+
line_width=3,
|
349 |
+
line_color=fig.layout.template.layout.colorway[0],
|
350 |
+
)
|
351 |
+
|
352 |
+
fig.update_layout(
|
353 |
+
{
|
354 |
+
"showlegend": False,
|
355 |
+
f"{x_or_y}axis_showgrid": True,
|
356 |
+
f"{y_or_x}axis_showgrid": False,
|
357 |
+
f"{x_or_y}axis_rangemode": "tozero",
|
358 |
+
},
|
359 |
+
)
|
360 |
+
return fig
|
pages/_factories.py
CHANGED
@@ -7,7 +7,7 @@ each chart type used in different groups.
|
|
7 |
import vizro.models as vm
|
8 |
|
9 |
from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
|
10 |
-
from pages.examples import butterfly, column_and_line, connected_scatter, waterfall
|
11 |
|
12 |
|
13 |
def butterfly_factory(group: str):
|
@@ -179,3 +179,48 @@ def waterfall_factory(group: str):
|
|
179 |
),
|
180 |
],
|
181 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
import vizro.models as vm
|
8 |
|
9 |
from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
|
10 |
+
from pages.examples import butterfly, column_and_line, connected_scatter, lollipop, waterfall
|
11 |
|
12 |
|
13 |
def butterfly_factory(group: str):
|
|
|
179 |
),
|
180 |
],
|
181 |
)
|
182 |
+
|
183 |
+
|
184 |
+
def lollipop_factory(group: str):
|
185 |
+
"""Reusable function to create the page content for the lollipop chart with a unique ID."""
|
186 |
+
return vm.Page(
|
187 |
+
id=f"{group}-lollipop",
|
188 |
+
path=f"{group}/lollipop",
|
189 |
+
title="Lollipop",
|
190 |
+
layout=vm.Layout(grid=PAGE_GRID),
|
191 |
+
components=[
|
192 |
+
vm.Card(
|
193 |
+
text="""
|
194 |
+
|
195 |
+
#### What is a lollipop chart?
|
196 |
+
|
197 |
+
A lollipop chart is a variation of a bar chart where each data point is represented by a line and a
|
198 |
+
dot at the end to mark the value. It functions like a bar chart but offers a cleaner visual,
|
199 |
+
especially useful when dealing with a large number of high values, to avoid the clutter of tall columns.
|
200 |
+
However, it can be less precise due to the difficulty in judging the exact center of the circle.
|
201 |
+
|
202 |
+
|
203 |
+
|
204 |
+
#### When should I use it?
|
205 |
+
|
206 |
+
Use a lollipop chart to compare values across categories, especially when dealing with many high values.
|
207 |
+
It highlights differences and trends clearly without the visual bulk of a bar chart. Ensure clarity by
|
208 |
+
limiting categories, using consistent scales, and clearly labeling axes. Consider alternatives if
|
209 |
+
precise value representation is crucial.
|
210 |
+
"""
|
211 |
+
),
|
212 |
+
vm.Graph(figure=lollipop.fig),
|
213 |
+
vm.Tabs(
|
214 |
+
tabs=[
|
215 |
+
vm.Container(
|
216 |
+
title="Vizro dashboard",
|
217 |
+
components=[make_code_clipboard_from_py_file("lollipop.py", mode="vizro")],
|
218 |
+
),
|
219 |
+
vm.Container(
|
220 |
+
title="Plotly figure",
|
221 |
+
components=[make_code_clipboard_from_py_file("lollipop.py", mode="plotly")],
|
222 |
+
),
|
223 |
+
]
|
224 |
+
),
|
225 |
+
],
|
226 |
+
)
|
pages/examples/diverging_stacked_bar.py
CHANGED
@@ -24,12 +24,16 @@ def diverging_stacked_bar(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
|
|
24 |
orientation = fig.data[0].orientation
|
25 |
x_or_y = "x" if orientation == "h" else "y"
|
26 |
|
27 |
-
for trace_idx in range(len(fig.data) // 2):
|
28 |
fig.update_traces({f"{x_or_y}axis": f"{x_or_y}2"}, selector=trace_idx)
|
29 |
|
|
|
30 |
fig.update_layout({f"{x_or_y}axis2": fig.layout[f"{x_or_y}axis"]})
|
31 |
fig.update_layout(
|
32 |
-
{
|
|
|
|
|
|
|
33 |
)
|
34 |
|
35 |
if orientation == "h":
|
@@ -63,6 +67,6 @@ fig = diverging_stacked_bar(
|
|
63 |
data_frame=pastries,
|
64 |
x=["Strongly Disagree", "Disagree", "Agree", "Strongly Agree"],
|
65 |
y="pastry",
|
66 |
-
labels={"value": "
|
67 |
title="I would recommend this pastry to my friends",
|
68 |
)
|
|
|
24 |
orientation = fig.data[0].orientation
|
25 |
x_or_y = "x" if orientation == "h" else "y"
|
26 |
|
27 |
+
for trace_idx in range(len(fig.data) // 2, len(fig.data)):
|
28 |
fig.update_traces({f"{x_or_y}axis": f"{x_or_y}2"}, selector=trace_idx)
|
29 |
|
30 |
+
fig.update_layout({f"{x_or_y}axis": {"ticksuffix": "%"}})
|
31 |
fig.update_layout({f"{x_or_y}axis2": fig.layout[f"{x_or_y}axis"]})
|
32 |
fig.update_layout(
|
33 |
+
{
|
34 |
+
f"{x_or_y}axis": {"domain": [0, 0.5], "range": [100, 0]},
|
35 |
+
f"{x_or_y}axis2": {"domain": [0.5, 1], "range": [0, 100]},
|
36 |
+
}
|
37 |
)
|
38 |
|
39 |
if orientation == "h":
|
|
|
67 |
data_frame=pastries,
|
68 |
x=["Strongly Disagree", "Disagree", "Agree", "Strongly Agree"],
|
69 |
y="pastry",
|
70 |
+
labels={"value": "", "variable": "", "pastry": ""},
|
71 |
title="I would recommend this pastry to my friends",
|
72 |
)
|
pages/examples/lollipop.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import plotly.express as px
|
3 |
+
import plotly.graph_objects as go
|
4 |
+
from vizro.models.types import capture
|
5 |
+
|
6 |
+
|
7 |
+
@capture("graph")
|
8 |
+
def lollipop(data_frame: pd.DataFrame, **kwargs):
|
9 |
+
"""Creates a lollipop chart using Plotly."""
|
10 |
+
fig = px.scatter(data_frame, **kwargs)
|
11 |
+
|
12 |
+
orientation = fig.data[0].orientation
|
13 |
+
x_or_y = "x" if orientation == "h" else "y"
|
14 |
+
y_or_x = "y" if orientation == "h" else "x"
|
15 |
+
|
16 |
+
for x_or_y_value, y_or_x_value in zip(fig.data[0][x_or_y], fig.data[0][y_or_x]):
|
17 |
+
fig.add_trace(go.Scatter({x_or_y: [0, x_or_y_value], y_or_x: [y_or_x_value, y_or_x_value], "mode": "lines"}))
|
18 |
+
|
19 |
+
fig.update_traces(
|
20 |
+
marker_size=12,
|
21 |
+
line_width=3,
|
22 |
+
line_color=fig.layout.template.layout.colorway[0],
|
23 |
+
)
|
24 |
+
|
25 |
+
fig.update_layout(
|
26 |
+
{
|
27 |
+
"showlegend": False,
|
28 |
+
f"{x_or_y}axis_showgrid": True,
|
29 |
+
f"{y_or_x}axis_showgrid": False,
|
30 |
+
f"{x_or_y}axis_rangemode": "tozero",
|
31 |
+
},
|
32 |
+
)
|
33 |
+
return fig
|
34 |
+
|
35 |
+
|
36 |
+
gapminder = (
|
37 |
+
px.data.gapminder()
|
38 |
+
.query("year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])")
|
39 |
+
.sort_values("pop")
|
40 |
+
)
|
41 |
+
|
42 |
+
fig = lollipop(gapminder, y="country", x="pop")
|
pages/examples/sparkline.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import plotly.express as px
|
2 |
+
from vizro.models.types import capture
|
3 |
+
|
4 |
+
stocks = px.data.stocks()
|
5 |
+
|
6 |
+
|
7 |
+
@capture("graph")
|
8 |
+
def sparkline(data_frame, **kwargs):
|
9 |
+
fig = px.line(data_frame, **kwargs)
|
10 |
+
fig.update_xaxes(ticks="", showgrid=False, title="")
|
11 |
+
fig.update_yaxes(visible=False)
|
12 |
+
fig.update_layout(showlegend=False)
|
13 |
+
return fig
|
14 |
+
|
15 |
+
|
16 |
+
fig = sparkline(stocks, x="date", y=["GOOG", "AMZN", "AAPL"], labels={"variable": "stock"}, facet_row="variable")
|
pages/magnitude.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
import vizro.models as vm
|
4 |
|
|
|
5 |
from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
|
6 |
from pages.examples import bar, magnitude_column, paired_bar, paired_column, parallel_coordinates, radar
|
7 |
|
@@ -238,4 +239,13 @@ radar_page = vm.Page(
|
|
238 |
],
|
239 |
)
|
240 |
|
241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
import vizro.models as vm
|
4 |
|
5 |
+
from pages._factories import lollipop_factory
|
6 |
from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
|
7 |
from pages.examples import bar, magnitude_column, paired_bar, paired_column, parallel_coordinates, radar
|
8 |
|
|
|
239 |
],
|
240 |
)
|
241 |
|
242 |
+
lollipop_page = lollipop_factory("magnitude")
|
243 |
+
pages = [
|
244 |
+
bar_page,
|
245 |
+
column_page,
|
246 |
+
paired_bar_page,
|
247 |
+
paired_column_page,
|
248 |
+
parallel_coordinates_page,
|
249 |
+
radar_page,
|
250 |
+
lollipop_page,
|
251 |
+
]
|
pages/ranking.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
import vizro.models as vm
|
4 |
|
|
|
5 |
from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
|
6 |
from pages.examples import ordered_bar, ordered_column
|
7 |
|
@@ -85,4 +86,6 @@ ordered_column_page = vm.Page(
|
|
85 |
)
|
86 |
|
87 |
|
88 |
-
|
|
|
|
|
|
2 |
|
3 |
import vizro.models as vm
|
4 |
|
5 |
+
from pages._factories import lollipop_factory
|
6 |
from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
|
7 |
from pages.examples import ordered_bar, ordered_column
|
8 |
|
|
|
86 |
)
|
87 |
|
88 |
|
89 |
+
lollipop_page = lollipop_factory("deviation")
|
90 |
+
|
91 |
+
pages = [ordered_bar_page, ordered_column_page, lollipop_page]
|
pages/time.py
CHANGED
@@ -7,7 +7,7 @@ from pages._pages_utils import (
|
|
7 |
PAGE_GRID,
|
8 |
make_code_clipboard_from_py_file,
|
9 |
)
|
10 |
-
from pages.examples import area, gantt, heatmap, line, stepped_line, time_column
|
11 |
|
12 |
line_page = vm.Page(
|
13 |
title="Line",
|
@@ -212,19 +212,19 @@ gantt_page = vm.Page(
|
|
212 |
#### What is a gantt chart?
|
213 |
|
214 |
A gantt chart is a type of bar chart that visualizes a project schedule.
|
215 |
-
It shows the start and end dates of a project element, such as tasks, activities, or
|
216 |
-
events, in a timeline format. Each element is represented by a bar whose length indicates
|
217 |
-
its duration.
|
218 |
|
219 |
|
220 |
|
221 |
#### When should I use it?
|
222 |
|
223 |
Gantt charts are ideal for visualizing project timelines, tracking
|
224 |
-
progress, and managing dependencies. They clearly display task start and end dates, making
|
225 |
-
it easy to monitor project status and manage interdependencies. However, they can become
|
226 |
-
complex if not regularly updated, especially for large projects.
|
227 |
-
|
228 |
),
|
229 |
vm.Graph(figure=gantt.fig),
|
230 |
vm.Tabs(
|
@@ -240,6 +240,46 @@ complex if not regularly updated, especially for large projects.
|
|
240 |
),
|
241 |
],
|
242 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
pages = [
|
244 |
line_page,
|
245 |
column_page,
|
@@ -249,4 +289,5 @@ pages = [
|
|
249 |
stepped_line_page,
|
250 |
heatmap_page,
|
251 |
gantt_page,
|
|
|
252 |
]
|
|
|
7 |
PAGE_GRID,
|
8 |
make_code_clipboard_from_py_file,
|
9 |
)
|
10 |
+
from pages.examples import area, gantt, heatmap, line, sparkline, stepped_line, time_column
|
11 |
|
12 |
line_page = vm.Page(
|
13 |
title="Line",
|
|
|
212 |
#### What is a gantt chart?
|
213 |
|
214 |
A gantt chart is a type of bar chart that visualizes a project schedule.
|
215 |
+
It shows the start and end dates of a project element, such as tasks, activities, or
|
216 |
+
events, in a timeline format. Each element is represented by a bar whose length indicates
|
217 |
+
its duration.
|
218 |
|
219 |
|
220 |
|
221 |
#### When should I use it?
|
222 |
|
223 |
Gantt charts are ideal for visualizing project timelines, tracking
|
224 |
+
progress, and managing dependencies. They clearly display task start and end dates, making
|
225 |
+
it easy to monitor project status and manage interdependencies. However, they can become
|
226 |
+
complex if not regularly updated, especially for large projects.
|
227 |
+
"""
|
228 |
),
|
229 |
vm.Graph(figure=gantt.fig),
|
230 |
vm.Tabs(
|
|
|
240 |
),
|
241 |
],
|
242 |
)
|
243 |
+
|
244 |
+
|
245 |
+
sparkline_page = vm.Page(
|
246 |
+
title="Sparkline",
|
247 |
+
path="time/sparkline",
|
248 |
+
layout=vm.Layout(grid=PAGE_GRID),
|
249 |
+
components=[
|
250 |
+
vm.Card(
|
251 |
+
text="""
|
252 |
+
#### What is a sparkline chart?
|
253 |
+
|
254 |
+
A sparkline chart is a compact line or area chart that displays multiple time series over a continuous
|
255 |
+
period. Without visible axes or labels, they are ideal for embedding within text, tables, or dashboards,
|
256 |
+
highlighting relative movement rather than precise values for a quick visual summary of trends.
|
257 |
+
|
258 |
+
|
259 |
+
|
260 |
+
#### When should I use it?
|
261 |
+
|
262 |
+
Use sparkline charts to show trends for multiple time series sharing the same y-axis quantity over the
|
263 |
+
same x-axis time range. They emphasize relative movement rather than precise values. To keep them
|
264 |
+
effective, ensure simplicity by avoiding clutter. Use consistent scales and distinct colors for
|
265 |
+
different series. Remove labels and gridlines, limit annotations, and place sparklines near relevant
|
266 |
+
text or data.
|
267 |
+
"""
|
268 |
+
),
|
269 |
+
vm.Graph(figure=sparkline.fig),
|
270 |
+
vm.Tabs(
|
271 |
+
tabs=[
|
272 |
+
vm.Container(
|
273 |
+
title="Vizro dashboard", components=[make_code_clipboard_from_py_file("sparkline.py", mode="vizro")]
|
274 |
+
),
|
275 |
+
vm.Container(
|
276 |
+
title="Plotly figure",
|
277 |
+
components=[make_code_clipboard_from_py_file("sparkline.py", mode="plotly")],
|
278 |
+
),
|
279 |
+
]
|
280 |
+
),
|
281 |
+
],
|
282 |
+
)
|
283 |
pages = [
|
284 |
line_page,
|
285 |
column_page,
|
|
|
289 |
stepped_line_page,
|
290 |
heatmap_page,
|
291 |
gantt_page,
|
292 |
+
sparkline_page,
|
293 |
]
|