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 |
]
|