antonymilne commited on
Commit
dda021c
1 Parent(s): 2465927

Update demo

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. README.md +60 -71
  2. app.py +3 -3
  3. assets/css/custom.css +18 -8
  4. chart_groups.py +2 -4
  5. custom_charts.py +198 -127
  6. custom_components.py +20 -13
  7. pages/__init__.py +0 -4
  8. pages/_factories.py +52 -23
  9. pages/_pages_utils.py +39 -87
  10. pages/correlation.py +45 -15
  11. pages/deviation.py +60 -17
  12. pages/distribution.py +54 -30
  13. pages/examples/area.py +1 -9
  14. pages/examples/bar.py +3 -20
  15. pages/examples/boxplot.py +1 -11
  16. pages/examples/bubble.py +2 -12
  17. pages/examples/bubble_map.py +2 -20
  18. pages/examples/butterfly.py +24 -35
  19. pages/examples/choropleth.py +2 -16
  20. pages/examples/column_and_line.py +23 -38
  21. pages/examples/connected_scatter.py +2 -12
  22. pages/examples/diverging_bar.py +3 -28
  23. pages/examples/diverging_stacked_bar.py +68 -0
  24. pages/examples/donut.py +1 -9
  25. pages/examples/dot_map.py +1 -19
  26. pages/examples/dumbbell.py +22 -27
  27. pages/examples/funnel.py +1 -9
  28. pages/examples/gantt.py +2 -13
  29. pages/examples/heatmap.py +1 -11
  30. pages/examples/histogram.py +1 -9
  31. pages/examples/line.py +1 -9
  32. pages/examples/magnitude_column.py +3 -19
  33. pages/examples/ordered_bar.py +5 -21
  34. pages/examples/ordered_column.py +5 -20
  35. pages/examples/paired_bar.py +8 -21
  36. pages/examples/paired_column.py +2 -20
  37. pages/examples/parallel_coordinates.py +2 -14
  38. pages/examples/pie.py +1 -9
  39. pages/examples/radar.py +4 -14
  40. pages/examples/sankey.py +26 -47
  41. pages/examples/scatter.py +1 -9
  42. pages/examples/scatter_matrix.py +1 -13
  43. pages/examples/stacked_bar.py +1 -10
  44. pages/examples/stacked_column.py +1 -10
  45. pages/examples/stepped_line.py +1 -17
  46. pages/examples/time_column.py +5 -25
  47. pages/examples/treemap.py +2 -19
  48. pages/examples/violin.py +1 -11
  49. pages/examples/waterfall.py +11 -35
  50. pages/flow.py +16 -14
README.md CHANGED
@@ -1,14 +1,3 @@
1
- ---
2
- title: Visual Vocabulary
3
- emoji: 🎨
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- license: apache-2.0
9
- short_description: Vizro - Visual vocabulary
10
- ---
11
-
12
  # Visual vocabulary
13
 
14
  ### Welcome to our visual vocabulary dashboard! 🎨
@@ -49,66 +38,66 @@ The dashboard is still in development. Below is an overview of the chart types f
49
 
50
  Sure, here's the table with all columns aligned for better readability:
51
 
52
- | Chart Type | Status | Category | Credits & sources | API |
53
- | --------------------- | ------ | ------------------------ | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
- | Arc | ❌ | Part-to-whole | | |
55
- | 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) |
56
- | Bar | ✅ | Magnitude | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar) |
57
- | Barcode | ❌ | Distribution | | |
58
- | Beeswarm | ❌ | Distribution | | |
59
- | 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) |
60
- | 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) |
61
- | 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) |
62
- | Bubble timeline | ❌ | Time | | |
63
- | Bullet | ❌ | Magnitude | | |
64
- | Bump | ❌ | Ranking | | |
65
- | 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) |
66
- | Chord | ❌ | Flow | | |
67
- | 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) |
68
- | 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) |
69
- | 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) |
70
- | 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) |
71
- | Cumulative curve | ❌ | Distribution | | |
72
- | 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) |
73
- | Diverging stacked bar | | Deviation | | |
74
- | 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) |
75
- | 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) |
76
- | 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/) |
77
- | Fan | ❌ | Time | | |
78
- | Flow map | ❌ | Spatial | | |
79
- | Funnel | ✅ | Part-to-whole | [Funnel plot with px](https://plotly.com/python/funnel-charts/) | [px.funnel](https://plotly.com/python/funnel-charts/) |
80
- | Gantt | ✅ | Time | [Gantt chart with px](https://plotly.com/python/gantt/) | [px.timeline](https://plotly.com/python-api-reference/generated/plotly.express.timeline.html) |
81
- | Gridplot | ❌ | Part-to-whole | | |
82
- | 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) |
83
- | Correlation matrix | ❌ | Correlation | | |
84
- | Histogram | ✅ | Distribution | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
85
- | Line | ✅ | Time | [Line plot with px](https://plotly.com/python/line-charts/) | [px.line](https://plotly.com/python-api-reference/generated/plotly.express.line) |
86
- | Lollipop | ❌ | Ranking, Magnitude | | |
87
- | Marimekko | ❌ | Magnitude, Part-to-whole | | |
88
- | Network | ❌ | Flow | | |
89
- | 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) |
90
- | Ordered bubble | ❌ | Ranking | | |
91
- | 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) |
92
- | Paired bar | ✅ | Magnitude | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
93
- | Paired column | ✅ | Magnitude | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
94
- | 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) |
95
- | Pictogram | ❌ | Magnitude | | |
96
- | 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) |
97
- | 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) |
98
- | Radial | ❌ | Magnitude | | |
99
- | 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) |
100
- | 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) |
101
- | 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) |
102
- | Slope | ❌ | Ranking, Time | | |
103
- | Sparkline | ❌ | Time | | |
104
- | 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) |
105
- | 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) |
106
- | 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) |
107
- | Surplus deficit line | ❌ | Deviation | | |
108
- | 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) |
109
- | Venn | ❌ | Part-to-whole | | |
110
- | Violin | ✅ | Distribution | [Violin plot with px](https://plotly.com/python/violin/) | [px.violin](https://plotly.com/python-api-reference/generated/plotly.express.violin.html) |
111
- | 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) |
112
 
113
  ## How to contribute
114
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # Visual vocabulary
2
 
3
  ### Welcome to our visual vocabulary dashboard! 🎨
 
38
 
39
  Sure, here's the table with all columns aligned for better readability:
40
 
41
+ | Chart Type | Status | Category | Credits & sources | API |
42
+ | --------------------- | ------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
43
+ | Arc | ❌ | Part-to-whole | | |
44
+ | 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) |
45
+ | Bar | ✅ | Magnitude | [Bar chart with px](https://plotly.com/python/bar-charts/) | [px.bar](https://plotly.com/python-api-reference/generated/plotly.express.bar) |
46
+ | Barcode | ❌ | Distribution | | |
47
+ | Beeswarm | ❌ | Distribution | | |
48
+ | 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) |
49
+ | 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) |
50
+ | 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) |
51
+ | Bubble timeline | ❌ | Time | | |
52
+ | Bullet | ❌ | Magnitude | | |
53
+ | Bump | ❌ | Ranking | | |
54
+ | 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) |
55
+ | Chord | ❌ | Flow | | |
56
+ | 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) |
57
+ | 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) |
58
+ | 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) |
59
+ | 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) |
60
+ | Cumulative curve | ❌ | Distribution | | |
61
+ | 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) |
62
+ | 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) |
63
+ | 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) |
64
+ | 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) |
65
+ | 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/) |
66
+ | Fan | ❌ | Time | | |
67
+ | Flow map | ❌ | Spatial | | |
68
+ | Funnel | ✅ | Part-to-whole | [Funnel plot with px](https://plotly.com/python/funnel-charts/) | [px.funnel](https://plotly.com/python/funnel-charts/) |
69
+ | Gantt | ✅ | Time | [Gantt chart with px](https://plotly.com/python/gantt/) | [px.timeline](https://plotly.com/python-api-reference/generated/plotly.express.timeline.html) |
70
+ | Gridplot | ❌ | Part-to-whole | | |
71
+ | 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) |
72
+ | Correlation matrix | ❌ | Correlation | | |
73
+ | Histogram | ✅ | Distribution | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
74
+ | Line | ✅ | Time | [Line plot with px](https://plotly.com/python/line-charts/) | [px.line](https://plotly.com/python-api-reference/generated/plotly.express.line) |
75
+ | Lollipop | ❌ | Ranking, Magnitude | | |
76
+ | Marimekko | ❌ | Magnitude, Part-to-whole | | |
77
+ | Network | ❌ | Flow | | |
78
+ | 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) |
79
+ | Ordered bubble | ❌ | Ranking | | |
80
+ | 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) |
81
+ | Paired bar | ✅ | Magnitude | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
82
+ | Paired column | ✅ | Magnitude | [Histograms with px](https://plotly.com/python/histograms/) | [px.histogram](https://plotly.github.io/plotly.py-docs/generated/plotly.express.histogram) |
83
+ | 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) |
84
+ | Pictogram | ❌ | Magnitude | | |
85
+ | 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) |
86
+ | 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) |
87
+ | Radial | ❌ | Magnitude | | |
88
+ | 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) |
89
+ | 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) |
90
+ | 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) |
91
+ | Slope | ❌ | Ranking, Time | | |
92
+ | Sparkline | ❌ | Time | | |
93
+ | 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) |
94
+ | 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) |
95
+ | 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) |
96
+ | Surplus deficit line | ❌ | Deviation | | |
97
+ | 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) |
98
+ | Venn | ❌ | Part-to-whole | | |
99
+ | Violin | ✅ | Distribution | [Violin plot with px](https://plotly.com/python/violin/) | [px.violin](https://plotly.com/python-api-reference/generated/plotly.express.violin.html) |
100
+ | 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) |
101
 
102
  ## How to contribute
103
 
app.py CHANGED
@@ -1,6 +1,6 @@
1
  """App configuration for dashboard."""
2
 
3
- from typing import List, Union
4
 
5
  import vizro.models as vm
6
  from chart_groups import ALL_CHART_GROUP, CHART_GROUPS, ChartGroup, IncompletePage
@@ -60,7 +60,7 @@ def make_homepage_container(chart_group: ChartGroup) -> vm.Container:
60
  )
61
 
62
 
63
- def _remove_duplicates(pages: List[Union[vm.Page, IncompletePage]]) -> List[Union[vm.Page, IncompletePage]]:
64
  # Deduplicate pages that have the same title. Using reversed means that the page that is kept is the first one
65
  # in the dashboard. This will be the one that the card on the homepage links to.
66
  return list({page.title: page for page in reversed(pages)}.values())
@@ -111,4 +111,4 @@ app = Vizro().build(dashboard)
111
  server = app.dash.server
112
 
113
  if __name__ == "__main__":
114
- app.run()
 
1
  """App configuration for dashboard."""
2
 
3
+ from typing import Union
4
 
5
  import vizro.models as vm
6
  from chart_groups import ALL_CHART_GROUP, CHART_GROUPS, ChartGroup, IncompletePage
 
60
  )
61
 
62
 
63
+ def _remove_duplicates(pages: list[Union[vm.Page, IncompletePage]]) -> list[Union[vm.Page, IncompletePage]]:
64
  # Deduplicate pages that have the same title. Using reversed means that the page that is kept is the first one
65
  # in the dashboard. This will be the one that the card on the homepage links to.
66
  return list({page.title: page for page in reversed(pages)}.values())
 
111
  server = app.dash.server
112
 
113
  if __name__ == "__main__":
114
+ app.run(port=8051)
assets/css/custom.css CHANGED
@@ -10,22 +10,36 @@ img[src*="#chart-icon"] {
10
  width: 100%;
11
  }
12
 
 
 
 
 
 
 
13
  .code-clipboard {
 
14
  font-size: 20px;
15
- position: absolute;
16
- right: 14px;
17
- top: 12px;
 
 
18
  }
19
 
20
  .code-clipboard-container {
21
  background: var(--surfaces-bg-card);
22
- font-family: monospace;
23
  max-height: 500px;
24
  overflow: auto;
25
  padding: 1rem;
26
  position: relative;
27
  }
28
 
 
 
 
 
 
 
29
  .code-clipboard-container::-webkit-scrollbar-thumb {
30
  border-color: var(--surfaces-bg-card);
31
  }
@@ -73,10 +87,6 @@ img[src*="#chart-icon"] {
73
  margin: 0;
74
  }
75
 
76
- .intro-text p a {
77
- font-size: inherit;
78
- }
79
-
80
  .intro-text ul:last-of-type {
81
  margin-bottom: 0;
82
  }
 
10
  width: 100%;
11
  }
12
 
13
+ .open-in-new {
14
+ font-size: inherit;
15
+ margin-left: 4px;
16
+ vertical-align: middle;
17
+ }
18
+
19
  .code-clipboard {
20
+ float: right;
21
  font-size: 20px;
22
+ }
23
+
24
+ .code-clipboard pre {
25
+ font-family: monospace;
26
+ margin-bottom: 12px;
27
  }
28
 
29
  .code-clipboard-container {
30
  background: var(--surfaces-bg-card);
 
31
  max-height: 500px;
32
  overflow: auto;
33
  padding: 1rem;
34
  position: relative;
35
  }
36
 
37
+ .code-clipboard-container .pycafe-link,
38
+ .code-clipboard-container .pycafe-link:focus {
39
+ line-height: unset;
40
+ margin-bottom: 12px;
41
+ }
42
+
43
  .code-clipboard-container::-webkit-scrollbar-thumb {
44
  border-color: var(--surfaces-bg-card);
45
  }
 
87
  margin: 0;
88
  }
89
 
 
 
 
 
90
  .intro-text ul:last-of-type {
91
  margin-bottom: 0;
92
  }
chart_groups.py CHANGED
@@ -2,7 +2,6 @@
2
 
3
  import itertools
4
  from dataclasses import dataclass
5
- from typing import List
6
 
7
  import pages.correlation
8
  import pages.deviation
@@ -36,8 +35,8 @@ class ChartGroup:
36
  """Represents a group of charts like "Deviation"."""
37
 
38
  name: str
39
- pages: List[vm.Page]
40
- incomplete_pages: List[IncompletePage]
41
  intro_text: str
42
  icon: str = "" # ALL_CHART_GROUP is the only one that doesn't require an icon.
43
 
@@ -51,7 +50,6 @@ deviation_chart_group = ChartGroup(
51
  name="Deviation",
52
  pages=pages.deviation.pages,
53
  incomplete_pages=[
54
- IncompletePage("Diverging stacked bar"),
55
  IncompletePage(title="Surplus deficit filled line"),
56
  ],
57
  icon="Contrast Square",
 
2
 
3
  import itertools
4
  from dataclasses import dataclass
 
5
 
6
  import pages.correlation
7
  import pages.deviation
 
35
  """Represents a group of charts like "Deviation"."""
36
 
37
  name: str
38
+ pages: list[vm.Page]
39
+ incomplete_pages: list[IncompletePage]
40
  intro_text: str
41
  icon: str = "" # ALL_CHART_GROUP is the only one that doesn't require an icon.
42
 
 
50
  name="Deviation",
51
  pages=pages.deviation.pages,
52
  incomplete_pages=[
 
53
  IncompletePage(title="Surplus deficit filled line"),
54
  ],
55
  icon="Contrast Square",
custom_charts.py CHANGED
@@ -1,6 +1,6 @@
1
  """Contains custom charts used inside the dashboard."""
2
 
3
- from typing import List
4
 
5
  import pandas as pd
6
  import vizro.plotly.express as px
@@ -13,181 +13,185 @@ from vizro.models.types import capture
13
  # it can get out of sync. But probably we don't want the docstrings in the short code snippet.
14
  # Ultimately these charts will probably move to vizro.charts anyway.
15
  @capture("graph")
16
- def butterfly(data_frame: pd.DataFrame, x1: str, x2: str, y: str) -> go.Figure:
17
- """Creates a custom butterfly chart using Plotly's go.Figure.
18
 
19
  A butterfly chart is a type of bar chart where two sets of bars are displayed back-to-back, often used to compare
20
  two sets of data.
21
 
22
  Args:
23
- data_frame (pd.DataFrame): The data source for the chart.
24
- x1 (str): The name of the column in the data frame for the first set of bars (negative values).
25
- x2 (str): The name of the column in the data frame for the second set of bars (positive values).
26
- y (str): The name of the column in the data frame for the y-axis (categories).
27
 
28
  Returns:
29
- go.Figure: A Plotly Figure object representing the butterfly chart.
30
 
31
  """
32
- fig = go.Figure()
33
- fig.add_trace(
34
- go.Bar(
35
- x=-data_frame[x1],
36
- y=data_frame[y],
37
- orientation="h",
38
- name=x1,
39
- )
40
- )
41
- fig.add_trace(
42
- go.Bar(
43
- x=data_frame[x2],
44
- y=data_frame[y],
45
- orientation="h",
46
- name=x2,
47
- )
48
  )
49
- fig.update_layout(barmode="relative")
 
 
 
 
 
50
  return fig
51
 
52
 
53
  @capture("graph")
54
- def sankey(data_frame: pd.DataFrame, source: str, target: str, value: str, labels: List[str]) -> go.Figure:
55
- """Creates a custom sankey chart using Plotly's `go.Sankey`.
56
 
57
  A Sankey chart is a type of flow diagram where the width of the arrows is proportional to the flow rate.
58
  It is used to visualize the flow of resources or data between different stages or categories.
59
 
60
- Args:
61
- data_frame (pd.DataFrame): The data source for the chart.
62
- source (str): The name of the column in the data frame for the source nodes.
63
- target (str): The name of the column in the data frame for the target nodes.
64
- value (str): The name of the column in the data frame for the values representing the flow between nodes.
65
- labels (List[str]): A list of labels for the nodes.
66
-
67
- Returns:
68
- go.Figure: A Plotly Figure object representing the Sankey chart.
69
-
70
  For detailed information on additional parameters and customization, refer to the Plotly documentation:
71
  https://plotly.com/python/reference/sankey/
72
 
 
 
 
 
 
 
 
 
 
73
  """
74
- fig = go.Figure(
75
- data=[
76
- go.Sankey(
77
- node={
78
- "pad": 16,
79
- "thickness": 16,
80
- "label": labels,
81
- },
82
- link={
83
- "source": data_frame[source],
84
- "target": data_frame[target],
85
- "value": data_frame[value],
86
- "label": labels,
87
- "color": "rgba(205, 209, 228, 0.4)",
88
- },
89
- )
90
- ]
91
  )
92
- fig.update_layout(barmode="relative")
93
- return fig
94
 
95
 
96
  @capture("graph")
97
- def column_and_line(data_frame: pd.DataFrame, x: str, y_column: str, y_line: str) -> go.Figure:
98
- """Creates a combined column and line chart using Plotly.
 
 
 
 
 
99
 
100
  This function generates a chart with a bar graph for one variable (y-axis 1) and a line graph for another variable
101
  (y-axis 2), sharing the same x-axis. The y-axes for the bar and line graphs are synchronized and overlaid.
102
 
103
  Args:
104
- data_frame (pd.DataFrame): The data source for the chart.
105
- x (str): The column name to be used for the x-axis.
106
- y_column (str): The column name to be used for the y-axis 1, representing the column chart.
107
- y_line (str): The column name to be used for the y-axis 2, representing the line chart.
 
108
 
109
  Returns:
110
- go.Figure: : A Plotly Figure object representing the combined column and line chart.
111
 
112
  """
113
- fig = make_subplots(specs=[[{"secondary_y": True}]])
 
 
 
 
114
 
115
- fig.add_trace(
116
- go.Bar(x=data_frame[x], y=data_frame[y_column], name=y_column),
117
- secondary_y=False,
 
 
 
118
  )
119
 
120
- fig.add_trace(
121
- go.Scatter(x=data_frame[x], y=data_frame[y_line], name=y_line),
122
- secondary_y=True,
123
- )
124
 
125
- fig.update_layout(
126
- xaxis={"type": "category", "title": x},
127
- yaxis={"tickmode": "sync", "title": y_column},
128
- yaxis2={"tickmode": "sync", "overlaying": "y", "title": y_line},
129
- )
130
 
131
  return fig
132
 
133
 
134
  @capture("graph")
135
- def categorical_column(data_frame: pd.DataFrame, x: str, y: str):
136
- """Creates a column chart where the x-axis values are converted to category type."""
137
- fig = px.bar(
138
- data_frame,
139
- x=x,
140
- y=y,
141
- )
 
 
 
 
 
 
 
142
  # So ticks are aligned with bars when xaxes values are numbers (e.g. years)
143
  fig.update_xaxes(type="category")
144
  return fig
145
 
146
 
147
  @capture("graph")
148
- def waterfall(data_frame: pd.DataFrame, x: str, y: str, measure: List[str]) -> go.Figure:
149
- """Creates a waterfall chart using Plotly's `go.Waterfall`.
150
 
151
  A Waterfall chart visually breaks down the cumulative effect of sequential positive and negative values,
152
  showing how each value contributes to the total.
153
 
154
- Args:
155
- data_frame (pd.DataFrame): The data source for the chart.
156
- x (str): Column name in `data_frame` for x-axis values.
157
- y (str): Column name in `data_frame` for y-axis values.
158
- measure (List[str]): List specifying the type of each bar, can be "relative", "total", or "absolute".
159
-
160
- Returns:
161
- go.Figure: A Plotly Figure object representing the Waterfall chart.
162
-
163
  For additional parameters and customization options, see the Plotly documentation:
164
  https://plotly.com/python/reference/waterfall/
165
 
 
 
 
 
 
 
 
 
166
  """
167
- fig = go.Figure(
168
- go.Waterfall(
169
- x=data_frame[x],
170
- y=data_frame[y],
171
- measure=data_frame[measure],
172
- )
173
  )
174
- fig.update_layout(showlegend=False)
175
- return fig
176
 
177
 
178
  @capture("graph")
179
- def radar(data_frame, **kwargs) -> go.Figure:
180
- """Creates a radar chart using Plotly's `line_polar`.
181
 
182
  A radar chart is a type of data visualization in which there are three or more
183
  variables represented on axes that originate from the same central point.
184
 
185
  Args:
186
- data_frame (pd.DataFrame): The data source for the chart.
187
- **kwargs: Keyword arguments that can be passed into Plotly's line_polar (i.e. r, theta, etc.)
 
188
 
189
  Returns:
190
- go.Figure: A Plotly Figure object representing the radar chart.
191
 
192
  """
193
  fig = px.line_polar(data_frame, **kwargs)
@@ -196,40 +200,107 @@ def radar(data_frame, **kwargs) -> go.Figure:
196
 
197
 
198
  @capture("graph")
199
- def dumbbell(data_frame: pd.DataFrame, x: str, y: str, color: str) -> go.Figure:
200
- """Creates a dumbbell chart using Plotly's `px.scatter` and `add_shape`.
201
 
202
  A dumbbell plot is a type of dot plot where the points, displaying different groups, are connected with a straight
203
  line. They are ideal for illustrating differences or gaps between two points.
204
 
 
 
205
  Args:
206
- data_frame (pd.DataFrame): The data source for the chart.
207
- x (str): Column name in `data_frame` for x-axis values.
208
- y (str): Column name in `data_frame` for y-axis values.
209
- color (str): Column name in `data_frame` used for coloring the markers.
210
 
211
  Returns:
212
- go.Figure: A Plotly Figure object representing the dumbbell chart.
213
-
214
- Inspired by: https://community.plotly.com/t/how-to-make-dumbbell-plots-in-plotly-python/47762
215
-
216
  """
217
- # Add two dots to plot
218
- fig = px.scatter(data_frame, y=y, x=x, color=color)
219
-
220
- # Add lines between dots
221
- for y_value, group in data_frame.groupby(y):
 
 
 
 
 
 
 
 
222
  fig.add_shape(
 
223
  type="line",
224
  layer="below",
225
- y0=y_value,
226
- y1=y_value,
227
- x0=group[x].min(),
228
- x1=group[x].max(),
229
  line_color="grey",
230
  line_width=3,
231
  )
232
 
233
- # Increase size of dots
234
  fig.update_traces(marker_size=12)
235
  return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """Contains custom charts used inside the dashboard."""
2
 
3
+ from typing import Union
4
 
5
  import pandas as pd
6
  import vizro.plotly.express as px
 
13
  # it can get out of sync. But probably we don't want the docstrings in the short code snippet.
14
  # Ultimately these charts will probably move to vizro.charts anyway.
15
  @capture("graph")
16
+ def butterfly(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
17
+ """Creates a butterfly chart based on px.bar.
18
 
19
  A butterfly chart is a type of bar chart where two sets of bars are displayed back-to-back, often used to compare
20
  two sets of data.
21
 
22
  Args:
23
+ data_frame: DataFrame for the chart. Can be long form or wide form.
24
+ See https://plotly.com/python/wide-form/.
25
+ **kwargs: Keyword arguments to pass into px.bar (e.g. x, y, labels).
26
+ See https://plotly.com/python-api-reference/generated/plotly.express.bar.html.
27
 
28
  Returns:
29
+ go.Figure: Butterfly chart.
30
 
31
  """
32
+ fig = px.bar(data_frame, **kwargs)
33
+
34
+ orientation = fig.data[0].orientation
35
+ x_or_y = "x" if orientation == "h" else "y"
36
+
37
+ # Create new x or y axis with scale reversed (so going from 0 at the midpoint outwards) to do back-to-back bars.
38
+ fig.update_traces({f"{x_or_y}axis": f"{x_or_y}2"}, selector=1)
39
+ fig.update_layout({f"{x_or_y}axis2": fig.layout[f"{x_or_y}axis"]})
40
+ fig.update_layout(
41
+ {f"{x_or_y}axis": {"autorange": "reversed", "domain": [0, 0.5]}, f"{x_or_y}axis2": {"domain": [0.5, 1]}}
 
 
 
 
 
 
42
  )
43
+
44
+ if orientation == "h":
45
+ fig.add_vline(x=0, line_width=2, line_color="grey")
46
+ else:
47
+ fig.add_hline(y=0, line_width=2, line_color="grey")
48
+
49
  return fig
50
 
51
 
52
  @capture("graph")
53
+ def sankey(data_frame: pd.DataFrame, source: str, target: str, value: str, labels: list[str]) -> go.Figure:
54
+ """Creates a Sankey chart based on go.Sankey.
55
 
56
  A Sankey chart is a type of flow diagram where the width of the arrows is proportional to the flow rate.
57
  It is used to visualize the flow of resources or data between different stages or categories.
58
 
 
 
 
 
 
 
 
 
 
 
59
  For detailed information on additional parameters and customization, refer to the Plotly documentation:
60
  https://plotly.com/python/reference/sankey/
61
 
62
+ Args:
63
+ data_frame: DataFrame for the chart.
64
+ source: The name of the column in data_frame for source nodes.
65
+ target: The name of the column in data_frame for target nodes.
66
+ value: The name of the column in data_frame for the values representing the flow between nodes.
67
+ labels: A list of labels for the nodes.
68
+
69
+ Returns:
70
+ go.Figure: Sankey chart.
71
  """
72
+ return go.Figure(
73
+ data=go.Sankey(
74
+ node={
75
+ "pad": 16,
76
+ "thickness": 16,
77
+ "label": labels,
78
+ },
79
+ link={
80
+ "source": data_frame[source],
81
+ "target": data_frame[target],
82
+ "value": data_frame[value],
83
+ "label": labels,
84
+ "color": "rgba(205, 209, 228, 0.4)",
85
+ },
86
+ ),
87
+ layout={"barmode": "relative"},
 
88
  )
 
 
89
 
90
 
91
  @capture("graph")
92
+ def column_and_line(
93
+ data_frame: pd.DataFrame,
94
+ x: Union[str, pd.Series, list[str], list[pd.Series]],
95
+ y_column: Union[str, pd.Series, list[str], list[pd.Series]],
96
+ y_line: Union[str, pd.Series, list[str], list[pd.Series]],
97
+ ) -> go.Figure:
98
+ """Creates a combined column and line chart based on px.bar and px.line.
99
 
100
  This function generates a chart with a bar graph for one variable (y-axis 1) and a line graph for another variable
101
  (y-axis 2), sharing the same x-axis. The y-axes for the bar and line graphs are synchronized and overlaid.
102
 
103
  Args:
104
+ data_frame: DataFrame for the chart. Can be long form or wide form.
105
+ See https://plotly.com/python/wide-form/.
106
+ x: Either a name of a column in data_frame, or a pandas Series or array_like object.
107
+ y_column: Either a name of a column in data_frame, or a pandas Series or array_like object.
108
+ y_line: Either a name of a column in data_frame, or a pandas Series or array_like object.
109
 
110
  Returns:
111
+ go.Figure: Combined column and line chart.
112
 
113
  """
114
+ # We use px.bar and px.line so that we get the plotly express hoverdata, axes titles etc. Bar is used arbitrarily
115
+ # selected as the "base" plot and then line added on top of it. This means manually incrementing
116
+ # color_discrete_sequence for the line plot so that the colors are not the same for bar and line.
117
+ bar = px.bar(data_frame, x=x, y=y_column)
118
+ fig = make_subplots(figure=bar, specs=[[{"secondary_y": True}]])
119
 
120
+ line = px.line(
121
+ data_frame,
122
+ x=x,
123
+ y=y_line,
124
+ markers=True,
125
+ color_discrete_sequence=fig.layout.template.layout.colorway[len(bar.data) :],
126
  )
127
 
128
+ for trace in line.data:
129
+ fig.add_trace(trace, secondary_y=True)
 
 
130
 
131
+ fig.update_layout(yaxis2={"tickmode": "sync", "overlaying": "y", "title": line.layout.yaxis.title})
 
 
 
 
132
 
133
  return fig
134
 
135
 
136
  @capture("graph")
137
+ def categorical_column(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
138
+ """Creates categorical bar chart based on px.bar.
139
+
140
+ Args:
141
+ data_frame: DataFrame for the chart. Can be long form or wide form.
142
+ See https://plotly.com/python/wide-form/.
143
+ **kwargs: Keyword arguments to pass into px.bar (e.g. x, y, labels).
144
+ See https://plotly.com/python-api-reference/generated/plotly.express.bar.html.
145
+
146
+ Returns:
147
+ go.Figure: Categorical column chart.
148
+
149
+ """
150
+ fig = px.bar(data_frame, **kwargs)
151
  # So ticks are aligned with bars when xaxes values are numbers (e.g. years)
152
  fig.update_xaxes(type="category")
153
  return fig
154
 
155
 
156
  @capture("graph")
157
+ def waterfall(data_frame: pd.DataFrame, x: str, y: str, measure: list[str]) -> go.Figure:
158
+ """Creates a waterfall chart based on go.Waterfall.
159
 
160
  A Waterfall chart visually breaks down the cumulative effect of sequential positive and negative values,
161
  showing how each value contributes to the total.
162
 
 
 
 
 
 
 
 
 
 
163
  For additional parameters and customization options, see the Plotly documentation:
164
  https://plotly.com/python/reference/waterfall/
165
 
166
+ Args:
167
+ data_frame: TDataFrame for the chart.
168
+ x: Column name in data_frame for x-axis values.
169
+ y: Column name in data_frame for y-axis values.
170
+ measure: List specifying the type of each bar, can be "relative", "total", or "absolute".
171
+
172
+ Returns:
173
+ go.Figure: Waterfall chart.
174
  """
175
+ return go.Figure(
176
+ data=go.Waterfall(x=data_frame[x], y=data_frame[y], measure=data_frame[measure]),
177
+ layout={"showlegend": False},
 
 
 
178
  )
 
 
179
 
180
 
181
  @capture("graph")
182
+ def radar(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
183
+ """Creates a radar chart based on px.line_polar.
184
 
185
  A radar chart is a type of data visualization in which there are three or more
186
  variables represented on axes that originate from the same central point.
187
 
188
  Args:
189
+ data_frame: DataFrame for the chart.
190
+ **kwargs: Keyword arguments to pass into px.line_polar (e.g. r, theta).
191
+ See https://plotly.com/python-api-reference/generated/plotly.express.line_polar.html.
192
 
193
  Returns:
194
+ go.Figure: A Plotly Figure object of the radar chart.
195
 
196
  """
197
  fig = px.line_polar(data_frame, **kwargs)
 
200
 
201
 
202
  @capture("graph")
203
+ def dumbbell(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
204
+ """Creates a dumbbell chart based on px.scatter.
205
 
206
  A dumbbell plot is a type of dot plot where the points, displaying different groups, are connected with a straight
207
  line. They are ideal for illustrating differences or gaps between two points.
208
 
209
+ Inspired by: https://community.plotly.com/t/how-to-make-dumbbell-plots-in-plotly-python/47762
210
+
211
  Args:
212
+ data_frame: DataFrame for the chart. Can be long form or wide form.
213
+ See https://plotly.com/python/wide-form/.
214
+ **kwargs: Keyword arguments to pass into px.scatter (e.g. x, y, labels).
215
+ See https://plotly.com/python-api-reference/generated/plotly.scatter.html.
216
 
217
  Returns:
218
+ go.Figure: Dumbbell chart.
 
 
 
219
  """
220
+ fig = px.scatter(data_frame, **kwargs)
221
+
222
+ orientation = fig.data[0].orientation
223
+ x_or_y = "x" if orientation == "h" else "y"
224
+ y_or_x = "y" if orientation == "h" else "x"
225
+
226
+ # Add lines between every pair of points.
227
+ for x_or_y_0, x_or_y_1, y_or_x_0, y_or_x_1 in zip(
228
+ fig.data[0][x_or_y],
229
+ fig.data[1][x_or_y],
230
+ fig.data[0][y_or_x],
231
+ fig.data[1][y_or_x],
232
+ ):
233
  fig.add_shape(
234
+ **{f"{x_or_y}0": x_or_y_0, f"{x_or_y}1": x_or_y_1, f"{y_or_x}0": y_or_x_0, f"{y_or_x}1": y_or_x_1},
235
  type="line",
236
  layer="below",
 
 
 
 
237
  line_color="grey",
238
  line_width=3,
239
  )
240
 
 
241
  fig.update_traces(marker_size=12)
242
  return fig
243
+
244
+
245
+ @capture("graph")
246
+ def diverging_stacked_bar(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
247
+ """Creates a diverging stacked bar chart based on px.bar.
248
+
249
+ This type of chart is a variant of the standard stacked bar chart, with bars aligned on a central baseline to
250
+ show both positive and negative values. Each bar is segmented to represent different categories.
251
+
252
+ This function is not suitable for diverging stacked bar charts that include a neutral category. The first half of
253
+ bars plotted are assumed to be negative ("Disagree") and the second half are assumed to be positive ("Agree").
254
+
255
+ Inspired by: https://community.plotly.com/t/need-help-in-making-diverging-stacked-bar-charts/34023
256
+
257
+ Args:
258
+ data_frame: DataFrame for the chart. Can be long form or wide form.
259
+ See https://plotly.com/python/wide-form/.
260
+ **kwargs: Keyword arguments to pass into px.bar (e.g. x, y, labels).
261
+ See https://plotly.com/python-api-reference/generated/plotly.express.bar.html.
262
+
263
+ Returns:
264
+ go.Figure: Diverging stacked bar chart.
265
+ """
266
+ fig = px.bar(data_frame, **kwargs)
267
+
268
+ # Fix legend position according to the order of traces. This ensures that "Strongly disagree" comes before
269
+ # "Disagree".
270
+ for i, trace in enumerate(fig.data):
271
+ trace.update(legendrank=i)
272
+
273
+ if "color_discrete_sequence" not in kwargs and "color_discrete_map" not in kwargs:
274
+ # Make a discrete diverging colorscale by sampling the right number of colors.
275
+ # Need to explicitly convert colorscale to list of lists due to plotly bug/inconsistency:
276
+ # https://github.com/plotly/plotly.py/issues/4808
277
+ colorscale = [list(x) for x in fig.layout.template.layout.colorscale.diverging]
278
+ colors = px.colors.sample_colorscale(colorscale, len(fig.data), 0.2, 0.8)
279
+ for trace, color in zip(fig.data, colors):
280
+ trace.update(marker_color=color)
281
+
282
+ # Plotly draws traces in order they appear in fig.data, starting from x=0 and then stacking outwards.
283
+ # We need negative traces to be ordered so that "Disagree" comes before "Strongly disagree", so reverse the
284
+ # order of first half of traces.
285
+ mutable_traces = list(fig.data)
286
+ mutable_traces[: len(fig.data) // 2] = reversed(fig.data[: len(fig.data) // 2])
287
+ fig.data = mutable_traces
288
+
289
+ # Create new x or y axis with scale reversed (so going from 0 at the midpoint outwards) to do negative bars.
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
+ {f"{x_or_y}axis": {"autorange": "reversed", "domain": [0, 0.5]}, f"{x_or_y}axis2": {"domain": [0.5, 1]}}
299
+ )
300
+
301
+ if orientation == "h":
302
+ fig.add_vline(x=0, line_width=2, line_color="grey")
303
+ else:
304
+ fig.add_hline(y=0, line_width=2, line_color="grey")
305
+
306
+ return fig
custom_components.py CHANGED
@@ -11,31 +11,38 @@ try:
11
  except ImportError: # pragma: no cov
12
  from pydantic import Field
13
 
 
 
14
 
15
  class CodeClipboard(vm.VizroBaseModel):
16
  """Code snippet with a copy to clipboard button."""
17
 
18
  type: Literal["code_clipboard"] = "code_clipboard"
19
  code: str
 
20
  language: str = ""
21
 
22
  def build(self):
23
  """Returns the code clipboard component inside an accordion."""
24
  markdown_code = "\n".join([f"```{self.language}", self.code, "```"])
25
- return dbc.Accordion(
 
 
 
 
 
 
 
 
 
 
 
26
  [
27
- dbc.AccordionItem(
28
- html.Div(
29
- [
30
- dcc.Markdown(markdown_code, id=self.id),
31
- dcc.Clipboard(target_id=self.id, className="code-clipboard"),
32
- ],
33
- className="code-clipboard-container",
34
- ),
35
- title="SHOW CODE",
36
- )
37
  ],
38
- start_collapsed=False,
39
  )
40
 
41
 
@@ -68,4 +75,4 @@ class FlexContainer(vm.Container):
68
 
69
  vm.Container.add_type("components", FlexContainer)
70
  vm.Container.add_type("components", Markdown)
71
- vm.Page.add_type("components", CodeClipboard)
 
11
  except ImportError: # pragma: no cov
12
  from pydantic import Field
13
 
14
+ from urllib.parse import quote
15
+
16
 
17
  class CodeClipboard(vm.VizroBaseModel):
18
  """Code snippet with a copy to clipboard button."""
19
 
20
  type: Literal["code_clipboard"] = "code_clipboard"
21
  code: str
22
+ mode: Literal["vizro", "plotly"]
23
  language: str = ""
24
 
25
  def build(self):
26
  """Returns the code clipboard component inside an accordion."""
27
  markdown_code = "\n".join([f"```{self.language}", self.code, "```"])
28
+
29
+ pycafe_link = dbc.Button(
30
+ [
31
+ "Edit code live on PyCafe",
32
+ html.Span("open_in_new", className="material-symbols-outlined open-in-new"),
33
+ ],
34
+ href=f"https://py.cafe/snippet/vizro/v1#code={quote(self.code)}",
35
+ target="_blank",
36
+ className="pycafe-link",
37
+ )
38
+
39
+ return html.Div(
40
  [
41
+ pycafe_link if self.mode == "vizro" else None,
42
+ dcc.Clipboard(target_id=self.id, className="code-clipboard"),
43
+ dcc.Markdown(markdown_code, id=self.id),
 
 
 
 
 
 
 
44
  ],
45
+ className="code-clipboard-container",
46
  )
47
 
48
 
 
75
 
76
  vm.Container.add_type("components", FlexContainer)
77
  vm.Container.add_type("components", Markdown)
78
+ vm.Container.add_type("components", CodeClipboard)
pages/__init__.py CHANGED
@@ -1,5 +1 @@
1
  # TODO: eventually deduplicate page generation into a function rather than copying and pasting across files?
2
- # TODO: think about the best way to do code examples, e.g.
3
- # - do we want full dashboard example or plot-only example?
4
- # - or both? Could be done using a toggle switch or multiple tabs.
5
- # - a link to PyCafe showing the dashboard code?
 
1
  # TODO: eventually deduplicate page generation into a function rather than copying and pasting across files?
 
 
 
 
pages/_factories.py CHANGED
@@ -5,10 +5,9 @@ each chart type used in different groups.
5
  """
6
 
7
  import vizro.models as vm
8
- import vizro.plotly.express as px
9
- from custom_charts import butterfly, column_and_line, waterfall
10
 
11
- from pages._pages_utils import PAGE_GRID, ages, gapminder, make_code_clipboard_from_py_file, waterfall_data
 
12
 
13
 
14
  def butterfly_factory(group: str):
@@ -37,8 +36,19 @@ def butterfly_factory(group: str):
37
  categories.
38
  """
39
  ),
40
- vm.Graph(figure=butterfly(ages, x1="Male", x2="Female", y="Age")),
41
- make_code_clipboard_from_py_file("butterfly.py"),
 
 
 
 
 
 
 
 
 
 
 
42
  ],
43
  )
44
 
@@ -69,8 +79,19 @@ def connected_scatter_factory(group: str):
69
  avoid misinterpretation.
70
  """
71
  ),
72
- vm.Graph(figure=px.line(gapminder.query("country == 'Australia'"), x="year", y="lifeExp", markers=True)),
73
- make_code_clipboard_from_py_file("connected_scatter.py"),
 
 
 
 
 
 
 
 
 
 
 
74
  ],
75
  )
76
 
@@ -99,15 +120,19 @@ def column_and_line_factory(group: str):
99
  for other types of data comparisons.
100
  """
101
  ),
102
- vm.Graph(
103
- figure=column_and_line(
104
- gapminder.query("country == 'Vietnam'"),
105
- y_column="gdpPercap",
106
- y_line="lifeExp",
107
- x="year",
108
- )
 
 
 
 
 
109
  ),
110
- make_code_clipboard_from_py_file("column_and_line.py"),
111
  ],
112
  )
113
 
@@ -139,14 +164,18 @@ def waterfall_factory(group: str):
139
  colors for positive and negative values, and arrange categories logically to tell a coherent story.
140
  """
141
  ),
142
- vm.Graph(
143
- figure=waterfall(
144
- waterfall_data,
145
- x="x",
146
- y="y",
147
- measure="measure",
148
- )
 
 
 
 
 
149
  ),
150
- make_code_clipboard_from_py_file("waterfall.py"),
151
  ],
152
  )
 
5
  """
6
 
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):
 
36
  categories.
37
  """
38
  ),
39
+ vm.Graph(figure=butterfly.fig),
40
+ vm.Tabs(
41
+ tabs=[
42
+ vm.Container(
43
+ title="Vizro dashboard",
44
+ components=[make_code_clipboard_from_py_file("butterfly.py", mode="vizro")],
45
+ ),
46
+ vm.Container(
47
+ title="Plotly figure",
48
+ components=[make_code_clipboard_from_py_file("butterfly.py", mode="plotly")],
49
+ ),
50
+ ]
51
+ ),
52
  ],
53
  )
54
 
 
79
  avoid misinterpretation.
80
  """
81
  ),
82
+ vm.Graph(figure=connected_scatter.fig),
83
+ vm.Tabs(
84
+ tabs=[
85
+ vm.Container(
86
+ title="Vizro dashboard",
87
+ components=[make_code_clipboard_from_py_file("connected_scatter.py", mode="vizro")],
88
+ ),
89
+ vm.Container(
90
+ title="Plotly figure",
91
+ components=[make_code_clipboard_from_py_file("connected_scatter.py", mode="plotly")],
92
+ ),
93
+ ]
94
+ ),
95
  ],
96
  )
97
 
 
120
  for other types of data comparisons.
121
  """
122
  ),
123
+ vm.Graph(figure=column_and_line.fig),
124
+ vm.Tabs(
125
+ tabs=[
126
+ vm.Container(
127
+ title="Vizro dashboard",
128
+ components=[make_code_clipboard_from_py_file("column_and_line.py", mode="vizro")],
129
+ ),
130
+ vm.Container(
131
+ title="Plotly figure",
132
+ components=[make_code_clipboard_from_py_file("column_and_line.py", mode="plotly")],
133
+ ),
134
+ ]
135
  ),
 
136
  ],
137
  )
138
 
 
164
  colors for positive and negative values, and arrange categories logically to tell a coherent story.
165
  """
166
  ),
167
+ vm.Graph(figure=waterfall.fig),
168
+ vm.Tabs(
169
+ tabs=[
170
+ vm.Container(
171
+ title="Vizro dashboard",
172
+ components=[make_code_clipboard_from_py_file("waterfall.py", mode="vizro")],
173
+ ),
174
+ vm.Container(
175
+ title="Plotly figure",
176
+ components=[make_code_clipboard_from_py_file("waterfall.py", mode="plotly")],
177
+ ),
178
+ ]
179
  ),
 
180
  ],
181
  )
pages/_pages_utils.py CHANGED
@@ -3,105 +3,57 @@
3
  import logging
4
  from pathlib import Path
5
 
 
6
  import black
7
- import pandas as pd
8
- import vizro.plotly.express as px
9
  from custom_components import CodeClipboard
10
 
11
  # To disable logging info messages caused by black.format_str: https://github.com/psf/black/issues/2058
12
  logging.getLogger("blib2to3").setLevel(logging.ERROR)
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- def make_code_clipboard_from_py_file(filepath: str):
16
  # Black doesn't yet have a Python API, so format_str might not work at some point in the future.
17
  # https://black.readthedocs.io/en/stable/faq.html#does-black-have-an-api
18
- filepath = Path(__file__).parents[1] / "pages/examples" / filepath
 
 
 
 
 
 
 
 
19
  return CodeClipboard(
20
- code=black.format_str(filepath.read_text(encoding="utf-8"), mode=black.Mode(line_length=80)),
 
21
  language="python",
22
  )
23
 
24
 
25
  PAGE_GRID = [[0, 0, 0, 0, 0, 0, 0]] * 2 + [[1, 1, 1, 1, 2, 2, 2]] * 5
26
-
27
- # DATA --------------------------------------------------------------
28
- gapminder = px.data.gapminder()
29
- iris = px.data.iris()
30
- stocks = px.data.stocks()
31
- tips = px.data.tips()
32
- wind = px.data.wind()
33
-
34
- ages = pd.DataFrame(
35
- {
36
- "Age": ["0-19", "20-29", "30-39", "40-49", "50-59", ">=60"],
37
- "Male": [800, 2000, 4200, 5000, 2100, 800],
38
- "Female": [1000, 3000, 3500, 3800, 3600, 700],
39
- }
40
- )
41
- sankey_data = pd.DataFrame(
42
- {
43
- "Origin": [0, 1, 0, 2, 3, 3],
44
- "Destination": [2, 3, 3, 4, 4, 5],
45
- "Value": [8, 4, 2, 8, 4, 2],
46
- }
47
- )
48
-
49
- funnel_data = pd.DataFrame(
50
- {"Stage": ["Leads", "Sales calls", "Follow-up", "Conversion", "Sales"], "Value": [10, 7, 4, 2, 1]}
51
- )
52
-
53
- stepped_line_data = pd.DataFrame(
54
- {
55
- "year": [1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003],
56
- "rate": [0.10, 0.12, 0.15, 0.13, 0.14, 0.13, 0.14, 0.16, 0.15],
57
- }
58
- )
59
-
60
-
61
- carshare = px.data.carshare()
62
-
63
- tasks = pd.DataFrame(
64
- [
65
- {"Task": "Job A", "Start": "2009-01-01", "Finish": "2009-02-28"},
66
- {"Task": "Job B", "Start": "2009-03-05", "Finish": "2009-04-15"},
67
- {"Task": "Job C", "Start": "2009-02-20", "Finish": "2009-05-30"},
68
- ]
69
- )
70
-
71
- waterfall_data = pd.DataFrame(
72
- {
73
- "x": ["Sales", "Consulting", "Net revenue", "Purchases", "Other expenses", "Profit before tax"],
74
- "y": [60, 80, 0, -40, -20, 0],
75
- "measure": ["relative", "relative", "total", "relative", "relative", "total"],
76
- }
77
- )
78
-
79
-
80
- pastries = pd.DataFrame(
81
- {
82
- "pastry": [
83
- "Scones",
84
- "Bagels",
85
- "Muffins",
86
- "Cakes",
87
- "Donuts",
88
- "Cookies",
89
- "Croissants",
90
- "Eclairs",
91
- "Brownies",
92
- "Tarts",
93
- "Macarons",
94
- "Pies",
95
- ],
96
- "Profit Ratio": [-0.10, -0.15, -0.05, 0.10, 0.05, 0.20, 0.15, -0.08, 0.08, -0.12, 0.02, -0.07],
97
- }
98
- )
99
-
100
-
101
- salaries = pd.DataFrame(
102
- {
103
- "Job": ["Developer", "Analyst", "Manager", "Specialist"] * 2,
104
- "Salary": [60000, 55000, 70000, 50000, 130000, 110000, 96400, 80000],
105
- "Range": ["Min"] * 4 + ["Max"] * 4,
106
- }
107
- )
 
3
  import logging
4
  from pathlib import Path
5
 
6
+ import autoflake
7
  import black
8
+ import isort
 
9
  from custom_components import CodeClipboard
10
 
11
  # To disable logging info messages caused by black.format_str: https://github.com/psf/black/issues/2058
12
  logging.getLogger("blib2to3").setLevel(logging.ERROR)
13
 
14
+ VIZRO_CODE_TEMPLATE = """
15
+ import vizro.models as vm
16
+ from vizro import Vizro
17
+ {example_code}
18
+ page = vm.Page(title="My page", components=[vm.Graph(figure=fig)])
19
+ dashboard = vm.Dashboard(pages=[page])
20
+ Vizro().build(dashboard).run()
21
+ """
22
+
23
+
24
+ def _format_and_lint(code_string: str, line_length: int) -> str:
25
+ """Inspired by vizro.models._base._format_and_lint. The only difference is that this does isort too."""
26
+ # Tracking https://github.com/astral-sh/ruff/issues/659 for proper Python API
27
+ # Good example: https://github.com/astral-sh/ruff/issues/8401#issuecomment-1788806462
28
+ # While we wait for the API, we can use autoflake and black to process code strings
29
+ # Isort is needed since otherwise example code looks quite strange sometimes. Autoflake is needed since isort can't
30
+ # remove imports by itself: https://github.com/PyCQA/isort/issues/1105.
31
+
32
+ removed_imports = autoflake.fix_code(code_string, remove_all_unused_imports=True)
33
+ sorted_imports = isort.code(removed_imports)
34
+ # Black doesn't yet have a Python API, so format_str might not work at some point in the future.
35
+ # https://black.readthedocs.io/en/stable/faq.html#does-black-have-an-api
36
+ formatted = black.format_str(sorted_imports, mode=black.Mode(line_length=line_length))
37
+ return formatted
38
+
39
 
40
+ def make_code_clipboard_from_py_file(filepath: str, mode="vizro"):
41
  # Black doesn't yet have a Python API, so format_str might not work at some point in the future.
42
  # https://black.readthedocs.io/en/stable/faq.html#does-black-have-an-api
43
+ example_code = (Path(__file__).parents[1] / "pages/examples" / filepath).read_text()
44
+
45
+ if mode == "vizro":
46
+ example_code = VIZRO_CODE_TEMPLATE.format(example_code=example_code)
47
+ else:
48
+ replacements = {"import vizro.plotly.express as px": "import plotly.express as px", '@capture("graph")': ""}
49
+ for old_code, new_code in replacements.items():
50
+ example_code = example_code.replace(old_code, new_code)
51
+
52
  return CodeClipboard(
53
+ code=_format_and_lint(example_code, line_length=80),
54
+ mode=mode,
55
  language="python",
56
  )
57
 
58
 
59
  PAGE_GRID = [[0, 0, 0, 0, 0, 0, 0]] * 2 + [[1, 1, 1, 1, 2, 2, 2]] * 5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/correlation.py CHANGED
@@ -1,12 +1,12 @@
1
  """Correlation charts."""
2
 
3
  import vizro.models as vm
4
- import vizro.plotly.express as px
5
 
6
  from pages._factories import column_and_line_factory, connected_scatter_factory
7
- from pages._pages_utils import PAGE_GRID, gapminder, iris, make_code_clipboard_from_py_file
 
8
 
9
- scatter = vm.Page(
10
  title="Scatter",
11
  path="correlation/scatter",
12
  layout=vm.Layout(grid=PAGE_GRID),
@@ -29,14 +29,24 @@ scatter = vm.Page(
29
  that correlation is not causation. Make sure your audience does not draw the wrong conclusions.
30
  """
31
  ),
32
- vm.Graph(figure=px.scatter(iris, x="sepal_width", y="sepal_length", color="species")),
33
- make_code_clipboard_from_py_file("scatter.py"),
 
 
 
 
 
 
 
 
 
 
34
  ],
35
  )
36
 
37
- connected_scatter = connected_scatter_factory("correlation")
38
 
39
- scatter_matrix = vm.Page(
40
  title="Scatter matrix",
41
  path="correlation/scatter-matrix",
42
  layout=vm.Layout(grid=PAGE_GRID),
@@ -60,14 +70,23 @@ scatter_matrix = vm.Page(
60
  ensure clarity and readability of the chart.
61
  """
62
  ),
63
- vm.Graph(
64
- figure=px.scatter_matrix(iris, dimensions=["sepal_length", "sepal_width", "petal_length", "petal_width"])
 
 
 
 
 
 
 
 
 
 
65
  ),
66
- make_code_clipboard_from_py_file("scatter_matrix.py"),
67
  ],
68
  )
69
 
70
- bubble = vm.Page(
71
  title="Bubble",
72
  path="correlation/bubble",
73
  layout=vm.Layout(grid=PAGE_GRID),
@@ -91,10 +110,21 @@ bubble = vm.Page(
91
  providing deeper insights than a standard scatter plot.
92
  """
93
  ),
94
- vm.Graph(figure=px.scatter(gapminder.query("year==2007"), x="gdpPercap", y="lifeExp", size="pop", size_max=60)),
95
- make_code_clipboard_from_py_file("bubble.py"),
 
 
 
 
 
 
 
 
 
 
96
  ],
97
  )
98
 
99
- column_and_line = column_and_line_factory("correlation")
100
- pages = [scatter, connected_scatter, scatter_matrix, bubble, column_and_line]
 
 
1
  """Correlation charts."""
2
 
3
  import vizro.models as vm
 
4
 
5
  from pages._factories import column_and_line_factory, connected_scatter_factory
6
+ from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
7
+ from pages.examples import bubble, scatter, scatter_matrix
8
 
9
+ scatter_page = vm.Page(
10
  title="Scatter",
11
  path="correlation/scatter",
12
  layout=vm.Layout(grid=PAGE_GRID),
 
29
  that correlation is not causation. Make sure your audience does not draw the wrong conclusions.
30
  """
31
  ),
32
+ vm.Graph(figure=scatter.fig),
33
+ vm.Tabs(
34
+ tabs=[
35
+ vm.Container(
36
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("scatter.py", mode="vizro")]
37
+ ),
38
+ vm.Container(
39
+ title="Plotly figure",
40
+ components=[make_code_clipboard_from_py_file("scatter.py", mode="plotly")],
41
+ ),
42
+ ]
43
+ ),
44
  ],
45
  )
46
 
47
+ connected_scatter_page = connected_scatter_factory("correlation")
48
 
49
+ scatter_matrix_page = vm.Page(
50
  title="Scatter matrix",
51
  path="correlation/scatter-matrix",
52
  layout=vm.Layout(grid=PAGE_GRID),
 
70
  ensure clarity and readability of the chart.
71
  """
72
  ),
73
+ vm.Graph(figure=scatter_matrix.fig),
74
+ vm.Tabs(
75
+ tabs=[
76
+ vm.Container(
77
+ title="Vizro dashboard",
78
+ components=[make_code_clipboard_from_py_file("scatter_matrix.py", mode="vizro")],
79
+ ),
80
+ vm.Container(
81
+ title="Plotly figure",
82
+ components=[make_code_clipboard_from_py_file("scatter_matrix.py", mode="plotly")],
83
+ ),
84
+ ]
85
  ),
 
86
  ],
87
  )
88
 
89
+ bubble_page = vm.Page(
90
  title="Bubble",
91
  path="correlation/bubble",
92
  layout=vm.Layout(grid=PAGE_GRID),
 
110
  providing deeper insights than a standard scatter plot.
111
  """
112
  ),
113
+ vm.Graph(figure=bubble.fig),
114
+ vm.Tabs(
115
+ tabs=[
116
+ vm.Container(
117
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("bubble.py", mode="vizro")]
118
+ ),
119
+ vm.Container(
120
+ title="Plotly figure",
121
+ components=[make_code_clipboard_from_py_file("bubble.py", mode="plotly")],
122
+ ),
123
+ ]
124
+ ),
125
  ],
126
  )
127
 
128
+ column_and_line_page = column_and_line_factory("correlation")
129
+
130
+ pages = [scatter_page, connected_scatter_page, scatter_matrix_page, bubble_page, column_and_line_page]
pages/deviation.py CHANGED
@@ -1,16 +1,15 @@
1
  """Deviation charts."""
2
 
3
- import plotly.io as pio
4
  import vizro.models as vm
5
- import vizro.plotly.express as px
6
 
7
  from pages._factories import butterfly_factory
8
- from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file, pastries
 
9
 
10
- butterfly = butterfly_factory("deviation")
11
 
12
 
13
- diverging_bar = vm.Page(
14
  title="Diverging bar",
15
  path="deviation/diverging-bar",
16
  layout=vm.Layout(grid=PAGE_GRID),
@@ -36,19 +35,63 @@ diverging_bar = vm.Page(
36
  of values. Ensure a consistent scale on both sides of the baseline to avoid misleading interpretations.
37
  """
38
  ),
39
- vm.Graph(
40
- figure=px.bar(
41
- pastries.sort_values("Profit Ratio"),
42
- orientation="h",
43
- x="Profit Ratio",
44
- y="pastry",
45
- color="Profit Ratio",
46
- color_continuous_scale=pio.templates["vizro_dark"].layout.colorscale.diverging,
47
- color_continuous_midpoint=0,
48
- ),
 
 
49
  ),
50
- make_code_clipboard_from_py_file("diverging_bar.py"),
51
  ],
52
  )
53
 
54
- pages = [butterfly, diverging_bar]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """Deviation charts."""
2
 
 
3
  import vizro.models as vm
 
4
 
5
  from pages._factories import butterfly_factory
6
+ from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
7
+ from pages.examples import diverging_bar, diverging_stacked_bar
8
 
9
+ butterfly_page = butterfly_factory("deviation")
10
 
11
 
12
+ diverging_bar_page = vm.Page(
13
  title="Diverging bar",
14
  path="deviation/diverging-bar",
15
  layout=vm.Layout(grid=PAGE_GRID),
 
35
  of values. Ensure a consistent scale on both sides of the baseline to avoid misleading interpretations.
36
  """
37
  ),
38
+ vm.Graph(figure=diverging_bar.fig),
39
+ vm.Tabs(
40
+ tabs=[
41
+ vm.Container(
42
+ title="Vizro dashboard",
43
+ components=[make_code_clipboard_from_py_file("diverging_bar.py", mode="vizro")],
44
+ ),
45
+ vm.Container(
46
+ title="Plotly figure",
47
+ components=[make_code_clipboard_from_py_file("diverging_bar.py", mode="plotly")],
48
+ ),
49
+ ]
50
  ),
 
51
  ],
52
  )
53
 
54
+ diverging_stacked_bar_page = vm.Page(
55
+ title="Diverging stacked bar",
56
+ path="deviation/diverging-stacked-bar",
57
+ layout=vm.Layout(grid=PAGE_GRID),
58
+ components=[
59
+ vm.Card(
60
+ text="""
61
+
62
+ #### What is a diverging stacked bar?
63
+
64
+ A diverging stacked bar chart is like a stacked bar chart but aligns bars on a central baseline instead of
65
+ the left or right. It displays positive and negative values, with each bar divided into segments for
66
+ different categories. This type of chart is commonly used for percentage shares, especially in survey
67
+ results using Likert scales (e.g., Strongly Disagree, Disagree, Agree, Strongly Agree).
68
+
69
+  
70
+
71
+ #### When should I use it?
72
+
73
+ A diverging stacked bar chart is useful for comparing positive and negative values and showing the
74
+ composition of each bar. However, use this chart with caution: since none of the segments share a
75
+ common baseline, direct comparisons can be more challenging. For clearer comparisons, consider using a
76
+ 100% stacked bar chart with a baseline starting from the left or right. For more insights on the potential
77
+ pitfalls, we recommend reading the article from
78
+ [Datawrapper on diverging stacked bar charts](https://blog.datawrapper.de/divergingbars/).
79
+ """
80
+ ),
81
+ vm.Graph(figure=diverging_stacked_bar.fig),
82
+ vm.Tabs(
83
+ tabs=[
84
+ vm.Container(
85
+ title="Vizro dashboard",
86
+ components=[make_code_clipboard_from_py_file("diverging_stacked_bar.py", mode="vizro")],
87
+ ),
88
+ vm.Container(
89
+ title="Plotly figure",
90
+ components=[make_code_clipboard_from_py_file("diverging_stacked_bar.py", mode="plotly")],
91
+ ),
92
+ ]
93
+ ),
94
+ ],
95
+ )
96
+
97
+ pages = [butterfly_page, diverging_bar_page, diverging_stacked_bar_page]
pages/distribution.py CHANGED
@@ -1,13 +1,12 @@
1
  """Distribution charts."""
2
 
3
  import vizro.models as vm
4
- import vizro.plotly.express as px
5
- from custom_charts import dumbbell
6
 
7
  from pages._factories import butterfly_factory
8
- from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file, salaries, tips
 
9
 
10
- violin = vm.Page(
11
  title="Violin",
12
  path="distribution/violin",
13
  layout=vm.Layout(grid=PAGE_GRID),
@@ -28,20 +27,22 @@ violin = vm.Page(
28
  inter-quartile range, the confidence intervals and the median.
29
  """
30
  ),
31
- vm.Graph(
32
- figure=px.violin(
33
- tips,
34
- y="total_bill",
35
- x="day",
36
- color="day",
37
- box=True,
38
- )
 
 
 
39
  ),
40
- make_code_clipboard_from_py_file("violin.py"),
41
  ],
42
  )
43
 
44
- boxplot = vm.Page(
45
  title="Boxplot",
46
  path="distribution/boxplot",
47
  layout=vm.Layout(grid=PAGE_GRID),
@@ -66,21 +67,24 @@ boxplot = vm.Page(
66
  the whiskers.
67
  """
68
  ),
69
- vm.Graph(
70
- figure=px.box(
71
- tips,
72
- y="total_bill",
73
- x="day",
74
- color="day",
75
- )
 
 
 
 
76
  ),
77
- make_code_clipboard_from_py_file("boxplot.py"),
78
  ],
79
  )
80
 
81
- butterfly = butterfly_factory("distribution")
82
 
83
- histogram = vm.Page(
84
  title="Histogram",
85
  path="distribution/histogram",
86
  layout=vm.Layout(grid=PAGE_GRID),
@@ -102,12 +106,22 @@ histogram = vm.Page(
102
  immediately clear.
103
  """
104
  ),
105
- vm.Graph(figure=px.histogram(tips, x="total_bill")),
106
- make_code_clipboard_from_py_file("histogram.py"),
 
 
 
 
 
 
 
 
 
 
107
  ],
108
  )
109
 
110
- dumbbell = vm.Page(
111
  title="Dumbbell",
112
  path="distribution/dumbbell",
113
  layout=vm.Layout(grid=PAGE_GRID),
@@ -129,10 +143,20 @@ dumbbell = vm.Page(
129
  of changes or to distinguish between categories.
130
  """
131
  ),
132
- vm.Graph(figure=dumbbell(salaries, y="Job", x="Salary", color="Range")),
133
- make_code_clipboard_from_py_file("dumbbell.py"),
 
 
 
 
 
 
 
 
 
 
134
  ],
135
  )
136
 
137
 
138
- pages = [violin, boxplot, butterfly, dumbbell, histogram]
 
1
  """Distribution charts."""
2
 
3
  import vizro.models as vm
 
 
4
 
5
  from pages._factories import butterfly_factory
6
+ from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
7
+ from pages.examples import boxplot, dumbbell, histogram, violin
8
 
9
+ violin_page = vm.Page(
10
  title="Violin",
11
  path="distribution/violin",
12
  layout=vm.Layout(grid=PAGE_GRID),
 
27
  inter-quartile range, the confidence intervals and the median.
28
  """
29
  ),
30
+ vm.Graph(figure=violin.fig),
31
+ vm.Tabs(
32
+ tabs=[
33
+ vm.Container(
34
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("violin.py", mode="vizro")]
35
+ ),
36
+ vm.Container(
37
+ title="Plotly figure",
38
+ components=[make_code_clipboard_from_py_file("violin.py", mode="plotly")],
39
+ ),
40
+ ]
41
  ),
 
42
  ],
43
  )
44
 
45
+ boxplot_page = vm.Page(
46
  title="Boxplot",
47
  path="distribution/boxplot",
48
  layout=vm.Layout(grid=PAGE_GRID),
 
67
  the whiskers.
68
  """
69
  ),
70
+ vm.Graph(figure=boxplot.fig),
71
+ vm.Tabs(
72
+ tabs=[
73
+ vm.Container(
74
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("boxplot.py", mode="vizro")]
75
+ ),
76
+ vm.Container(
77
+ title="Plotly figure",
78
+ components=[make_code_clipboard_from_py_file("boxplot.py", mode="plotly")],
79
+ ),
80
+ ]
81
  ),
 
82
  ],
83
  )
84
 
85
+ butterfly_page = butterfly_factory("distribution")
86
 
87
+ histogram_page = vm.Page(
88
  title="Histogram",
89
  path="distribution/histogram",
90
  layout=vm.Layout(grid=PAGE_GRID),
 
106
  immediately clear.
107
  """
108
  ),
109
+ vm.Graph(figure=histogram.fig),
110
+ vm.Tabs(
111
+ tabs=[
112
+ vm.Container(
113
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("histogram.py", mode="vizro")]
114
+ ),
115
+ vm.Container(
116
+ title="Plotly figure",
117
+ components=[make_code_clipboard_from_py_file("histogram.py", mode="plotly")],
118
+ ),
119
+ ]
120
+ ),
121
  ],
122
  )
123
 
124
+ dumbbell_page = vm.Page(
125
  title="Dumbbell",
126
  path="distribution/dumbbell",
127
  layout=vm.Layout(grid=PAGE_GRID),
 
143
  of changes or to distinguish between categories.
144
  """
145
  ),
146
+ vm.Graph(figure=dumbbell.fig),
147
+ vm.Tabs(
148
+ tabs=[
149
+ vm.Container(
150
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("dumbbell.py", mode="vizro")]
151
+ ),
152
+ vm.Container(
153
+ title="Plotly figure",
154
+ components=[make_code_clipboard_from_py_file("dumbbell.py", mode="plotly")],
155
+ ),
156
+ ]
157
+ ),
158
  ],
159
  )
160
 
161
 
162
+ pages = [violin_page, boxplot_page, butterfly_page, dumbbell_page, histogram_page]
pages/examples/area.py CHANGED
@@ -1,13 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  stocks = px.data.stocks()
6
 
7
- page = vm.Page(
8
- title="Area",
9
- components=[vm.Graph(figure=px.area(stocks, x="date", y="GOOG"))],
10
- )
11
-
12
- dashboard = vm.Dashboard(pages=[page])
13
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  stocks = px.data.stocks()
4
 
5
+ fig = px.area(stocks, x="date", y="GOOG")
 
 
 
 
 
 
pages/examples/bar.py CHANGED
@@ -1,24 +1,7 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
-
7
- page = vm.Page(
8
- title="Bar",
9
- components=[
10
- vm.Graph(
11
- figure=px.bar(
12
- gapminder.query(
13
- "year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])"
14
- ),
15
- x="pop",
16
- y="country",
17
- orientation="h",
18
- )
19
- )
20
- ],
21
  )
22
 
23
- dashboard = vm.Dashboard(pages=[page])
24
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = px.data.gapminder().query(
4
+ "year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  )
6
 
7
+ fig = px.bar(gapminder, x="pop", y="country", orientation="h")
 
pages/examples/boxplot.py CHANGED
@@ -1,15 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
- page = vm.Page(
8
- title="Boxplot",
9
- components=[
10
- vm.Graph(figure=px.boxplot(tips, y="total_bill", x="day", color="day")),
11
- ],
12
- )
13
-
14
- dashboard = vm.Dashboard(pages=[page])
15
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.box(tips, y="total_bill", x="day", color="day")
 
 
 
 
 
 
 
 
pages/examples/bubble.py CHANGED
@@ -1,15 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
 
7
- page = vm.Page(
8
- title="Bubble",
9
- components=[
10
- vm.Graph(figure=px.scatter(gapminder.query("year==2007"), x="gdpPercap", y="lifeExp", size="pop", size_max=60))
11
- ],
12
- )
13
-
14
- dashboard = vm.Dashboard(pages=[page])
15
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = px.data.gapminder().query("year==2007")
4
 
5
+ fig = px.scatter(gapminder, x="gdpPercap", y="lifeExp", size="pop", size_max=60)
 
 
 
 
 
 
 
 
pages/examples/bubble_map.py CHANGED
@@ -1,25 +1,7 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  carshare = px.data.carshare()
6
 
7
- page = vm.Page(
8
- title="Bubble map",
9
- components=[
10
- vm.Graph(
11
- figure=px.scatter_map(
12
- carshare,
13
- lat="centroid_lat",
14
- lon="centroid_lon",
15
- size="car_hours",
16
- size_max=15,
17
- opacity=0.5,
18
- zoom=10,
19
- )
20
- )
21
- ],
22
  )
23
-
24
- dashboard = vm.Dashboard(pages=[page])
25
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  carshare = px.data.carshare()
4
 
5
+ fig = px.scatter_map(
6
+ carshare, lat="centroid_lat", lon="centroid_lon", size="car_hours", size_max=15, opacity=0.5, zoom=10
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  )
 
 
 
pages/examples/butterfly.py CHANGED
@@ -1,9 +1,30 @@
1
  import pandas as pd
 
2
  import plotly.graph_objects as go
3
- import vizro.models as vm
4
- from vizro import Vizro
5
  from vizro.models.types import capture
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  ages = pd.DataFrame(
8
  {
9
  "Age": ["0-19", "20-29", "30-39", "40-49", "50-59", ">=60"],
@@ -12,36 +33,4 @@ ages = pd.DataFrame(
12
  }
13
  )
14
 
15
-
16
- @capture("graph")
17
- def butterfly(data_frame: pd.DataFrame, x1: str, x2: str, y: str):
18
- fig = go.Figure()
19
- fig.add_trace(
20
- go.Bar(
21
- x=-data_frame[x1],
22
- y=data_frame[y],
23
- orientation="h",
24
- name=x1,
25
- )
26
- )
27
- fig.add_trace(
28
- go.Bar(
29
- x=data_frame[x2],
30
- y=data_frame[y],
31
- orientation="h",
32
- name=x2,
33
- )
34
- )
35
- fig.update_layout(barmode="relative")
36
- return fig
37
-
38
-
39
- dashboard = vm.Dashboard(
40
- pages=[
41
- vm.Page(
42
- title="Butterfly",
43
- components=[vm.Graph(figure=butterfly(ages, x1="Male", x2="Female", y="Age"))],
44
- )
45
- ]
46
- )
47
- Vizro().build(dashboard).run()
 
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 butterfly(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
9
+ fig = px.bar(data_frame, **kwargs)
10
+
11
+ orientation = fig.data[0].orientation
12
+ x_or_y = "x" if orientation == "h" else "y"
13
+
14
+ fig.update_traces({f"{x_or_y}axis": f"{x_or_y}2"}, selector=1)
15
+ fig.update_layout({f"{x_or_y}axis2": fig.layout[f"{x_or_y}axis"]})
16
+ fig.update_layout(
17
+ {f"{x_or_y}axis": {"autorange": "reversed", "domain": [0, 0.5]}, f"{x_or_y}axis2": {"domain": [0.5, 1]}}
18
+ )
19
+
20
+ if orientation == "h":
21
+ fig.add_vline(x=0, line_width=2, line_color="grey")
22
+ else:
23
+ fig.add_hline(y=0, line_width=2, line_color="grey")
24
+
25
+ return fig
26
+
27
+
28
  ages = pd.DataFrame(
29
  {
30
  "Age": ["0-19", "20-29", "30-39", "40-49", "50-59", ">=60"],
 
33
  }
34
  )
35
 
36
+ fig = butterfly(ages, x=["Male", "Female"], y="Age", labels={"value": "Population", "variable": "Sex"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/choropleth.py CHANGED
@@ -1,19 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
 
7
- page = vm.Page(
8
- title="Choropleth",
9
- components=[
10
- vm.Graph(
11
- figure=px.choropleth(
12
- gapminder.query("year == 2007"), locations="iso_alpha", color="lifeExp", hover_name="country"
13
- )
14
- )
15
- ],
16
- )
17
-
18
- dashboard = vm.Dashboard(pages=[page])
19
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = px.data.gapminder().query("year == 2007")
4
 
5
+ fig = px.choropleth(gapminder, locations="iso_alpha", color="lifeExp", hover_name="country")
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/column_and_line.py CHANGED
@@ -1,53 +1,38 @@
 
 
1
  import pandas as pd
2
  import plotly.graph_objects as go
3
- import vizro.models as vm
4
  import vizro.plotly.express as px
5
  from plotly.subplots import make_subplots
6
- from vizro import Vizro
7
  from vizro.models.types import capture
8
 
9
- gapminder = px.data.gapminder()
10
-
11
 
12
  @capture("graph")
13
- def column_and_line(data_frame: pd.DataFrame, x: str, y_column: str, y_line: str) -> go.Figure:
14
- """Creates a combined column and line chart using Plotly."""
15
- fig = make_subplots(specs=[[{"secondary_y": True}]])
16
-
17
- fig.add_trace(
18
- go.Bar(x=data_frame[x], y=data_frame[y_column], name=y_column),
19
- secondary_y=False,
 
 
 
 
 
 
 
 
20
  )
21
 
22
- fig.add_trace(
23
- go.Scatter(x=data_frame[x], y=data_frame[y_line], name=y_line),
24
- secondary_y=True,
25
- )
26
 
27
- fig.update_layout(
28
- xaxis={"type": "category", "title": x},
29
- yaxis={"tickmode": "sync", "title": y_column},
30
- yaxis2={"tickmode": "sync", "overlaying": "y", "title": y_line},
31
- )
32
 
33
  return fig
34
 
35
 
36
- dashboard = vm.Dashboard(
37
- pages=[
38
- vm.Page(
39
- title="Column and line",
40
- components=[
41
- vm.Graph(
42
- figure=column_and_line(
43
- gapminder.query("country == 'Vietnam'"),
44
- y_column="gdpPercap",
45
- y_line="lifeExp",
46
- x="year",
47
- )
48
- )
49
- ],
50
- )
51
- ]
52
- )
53
- Vizro().build(dashboard).run()
 
1
+ from typing import Union
2
+
3
  import pandas as pd
4
  import plotly.graph_objects as go
 
5
  import vizro.plotly.express as px
6
  from plotly.subplots import make_subplots
 
7
  from vizro.models.types import capture
8
 
 
 
9
 
10
  @capture("graph")
11
+ def column_and_line(
12
+ data_frame: pd.DataFrame,
13
+ x: Union[str, pd.Series, list[str], list[pd.Series]],
14
+ y_column: Union[str, pd.Series, list[str], list[pd.Series]],
15
+ y_line: Union[str, pd.Series, list[str], list[pd.Series]],
16
+ ) -> go.Figure:
17
+ bar = px.bar(data_frame, x=x, y=y_column)
18
+ fig = make_subplots(figure=bar, specs=[[{"secondary_y": True}]])
19
+
20
+ line = px.line(
21
+ data_frame,
22
+ x=x,
23
+ y=y_line,
24
+ markers=True,
25
+ color_discrete_sequence=fig.layout.template.layout.colorway[len(bar.data) :],
26
  )
27
 
28
+ for trace in line.data:
29
+ fig.add_trace(trace, secondary_y=True)
 
 
30
 
31
+ fig.update_layout(yaxis2={"tickmode": "sync", "overlaying": "y", "title": line.layout.yaxis.title})
 
 
 
 
32
 
33
  return fig
34
 
35
 
36
+ gapminder = px.data.gapminder().query("country == 'Vietnam'")
37
+
38
+ fig = column_and_line(gapminder, y_column="gdpPercap", y_line="lifeExp", x="year")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/connected_scatter.py CHANGED
@@ -1,15 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
 
7
- page = vm.Page(
8
- title="Connected scatter",
9
- components=[
10
- vm.Graph(figure=px.line(gapminder.query("country == 'Australia'"), x="year", y="lifeExp", markers=True))
11
- ],
12
- )
13
-
14
- dashboard = vm.Dashboard(pages=[page])
15
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = px.data.gapminder().query("country == 'Australia'")
4
 
5
+ fig = px.line(gapminder, x="year", y="lifeExp", markers=True)
 
 
 
 
 
 
 
 
pages/examples/diverging_bar.py CHANGED
@@ -1,8 +1,5 @@
1
  import pandas as pd
2
- import plotly.io as pio
3
- import vizro.models as vm
4
  import vizro.plotly.express as px
5
- from vizro import Vizro
6
 
7
  pastries = pd.DataFrame(
8
  {
@@ -15,31 +12,9 @@ pastries = pd.DataFrame(
15
  "Cookies",
16
  "Croissants",
17
  "Eclairs",
18
- "Brownies",
19
- "Tarts",
20
- "Macarons",
21
- "Pies",
22
  ],
23
- "Profit Ratio": [-0.10, -0.15, -0.05, 0.10, 0.05, 0.20, 0.15, -0.08, 0.08, -0.12, 0.02, -0.07],
24
  }
25
- )
26
 
27
- page = vm.Page(
28
- title="Diverging bar",
29
- components=[
30
- vm.Graph(
31
- figure=px.bar(
32
- pastries.sort_values("Profit Ratio"),
33
- orientation="h",
34
- x="Profit Ratio",
35
- y="pastry",
36
- color="Profit Ratio",
37
- color_continuous_scale=pio.templates["vizro_dark"].layout.colorscale.diverging,
38
- color_continuous_midpoint=0,
39
- ),
40
- ),
41
- ],
42
- )
43
-
44
- dashboard = vm.Dashboard(pages=[page])
45
- Vizro().build(dashboard).run()
 
1
  import pandas as pd
 
 
2
  import vizro.plotly.express as px
 
3
 
4
  pastries = pd.DataFrame(
5
  {
 
12
  "Cookies",
13
  "Croissants",
14
  "Eclairs",
 
 
 
 
15
  ],
16
+ "Profit Ratio": [-0.10, -0.05, 0.10, 0.05, 0.15, -0.08, 0.08, -0.12],
17
  }
18
+ ).sort_values("Profit Ratio")
19
 
20
+ fig = px.bar(pastries, x="Profit Ratio", y="pastry")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/diverging_stacked_bar.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 diverging_stacked_bar(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
9
+ fig = px.bar(data_frame, **kwargs)
10
+
11
+ for i, trace in enumerate(fig.data):
12
+ trace.update(legendrank=i)
13
+
14
+ if "color_discrete_sequence" not in kwargs and "color_discrete_map" not in kwargs:
15
+ colorscale = [list(x) for x in fig.layout.template.layout.colorscale.diverging]
16
+ colors = px.colors.sample_colorscale(colorscale, len(fig.data), 0.2, 0.8)
17
+ for trace, color in zip(fig.data, colors):
18
+ trace.update(marker_color=color)
19
+
20
+ mutable_traces = list(fig.data)
21
+ mutable_traces[: len(fig.data) // 2] = reversed(fig.data[: len(fig.data) // 2])
22
+ fig.data = mutable_traces
23
+
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
+ {f"{x_or_y}axis": {"autorange": "reversed", "domain": [0, 0.5]}, f"{x_or_y}axis2": {"domain": [0.5, 1]}}
33
+ )
34
+
35
+ if orientation == "h":
36
+ fig.add_vline(x=0, line_width=2, line_color="grey")
37
+ else:
38
+ fig.add_hline(y=0, line_width=2, line_color="grey")
39
+
40
+ return fig
41
+
42
+
43
+ pastries = pd.DataFrame(
44
+ {
45
+ "pastry": [
46
+ "Scones",
47
+ "Bagels",
48
+ "Muffins",
49
+ "Cakes",
50
+ "Donuts",
51
+ "Cookies",
52
+ "Croissants",
53
+ "Eclairs",
54
+ ],
55
+ "Strongly Disagree": [20, 30, 10, 5, 15, 5, 10, 25],
56
+ "Disagree": [30, 25, 20, 10, 20, 10, 15, 30],
57
+ "Agree": [30, 25, 40, 40, 45, 40, 40, 25],
58
+ "Strongly Agree": [20, 20, 30, 45, 20, 45, 35, 20],
59
+ }
60
+ )
61
+
62
+ fig = diverging_stacked_bar(
63
+ data_frame=pastries,
64
+ x=["Strongly Disagree", "Disagree", "Agree", "Strongly Agree"],
65
+ y="pastry",
66
+ labels={"value": "Response count", "variable": "Opinion"},
67
+ title="I would recommend this pastry to my friends",
68
+ )
pages/examples/donut.py CHANGED
@@ -1,13 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
- page = vm.Page(
8
- title="Donut",
9
- components=[vm.Graph(figure=px.pie(tips, values="tip", names="day", hole=0.4))],
10
- )
11
-
12
- dashboard = vm.Dashboard(pages=[page])
13
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.pie(tips, values="tip", names="day", hole=0.4)
 
 
 
 
 
 
pages/examples/dot_map.py CHANGED
@@ -1,23 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  carshare = px.data.carshare()
6
 
7
- page = vm.Page(
8
- title="Dot map",
9
- components=[
10
- vm.Graph(
11
- figure=px.scatter_map(
12
- carshare,
13
- lat="centroid_lat",
14
- lon="centroid_lon",
15
- opacity=0.5,
16
- zoom=10,
17
- )
18
- )
19
- ],
20
- )
21
-
22
- dashboard = vm.Dashboard(pages=[page])
23
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  carshare = px.data.carshare()
4
 
5
+ fig = px.scatter_map(carshare, lat="centroid_lat", lon="centroid_lon", opacity=0.5, zoom=10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/dumbbell.py CHANGED
@@ -1,46 +1,41 @@
1
  import pandas as pd
2
- import vizro.models as vm
3
  import vizro.plotly.express as px
4
- from plotly import graph_objects as go
5
- from vizro import Vizro
6
  from vizro.models.types import capture
7
 
8
- salaries = pd.DataFrame(
9
- {
10
- "Job": ["Developer", "Analyst", "Manager", "Specialist"] * 2,
11
- "Salary": [60000, 55000, 70000, 50000, 130000, 110000, 96400, 80000],
12
- "Range": ["Min"] * 4 + ["Max"] * 4,
13
- }
14
- )
15
-
16
 
17
  @capture("graph")
18
- def dumbbell(data_frame: pd.DataFrame, x: str, y: str, color: str) -> go.Figure:
19
- # Add two dots to plot
20
- fig = px.scatter(data_frame, y=y, x=x, color=color)
21
-
22
- # Add lines between dots
23
- for y_value, group in data_frame.groupby(y):
 
 
 
 
 
 
 
24
  fig.add_shape(
 
25
  type="line",
26
  layer="below",
27
- y0=y_value,
28
- y1=y_value,
29
- x0=group[x].min(),
30
- x1=group[x].max(),
31
  line_color="grey",
32
  line_width=3,
33
  )
34
 
35
- # Increase size of dots
36
  fig.update_traces(marker_size=12)
37
  return fig
38
 
39
 
40
- page = vm.Page(
41
- title="Dumbbell",
42
- components=[vm.Graph(figure=dumbbell(salaries, y="Job", x="Salary", color="Range"))],
 
 
 
43
  )
44
 
45
- dashboard = vm.Dashboard(pages=[page])
46
- Vizro().build(dashboard).run()
 
1
  import pandas as pd
2
+ import plotly.graph_objects as go
3
  import vizro.plotly.express as px
 
 
4
  from vizro.models.types import capture
5
 
 
 
 
 
 
 
 
 
6
 
7
  @capture("graph")
8
+ def dumbbell(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
9
+ fig = px.scatter(data_frame, **kwargs)
10
+
11
+ orientation = fig.data[0].orientation
12
+ x_or_y = "x" if orientation == "h" else "y"
13
+ y_or_x = "y" if orientation == "h" else "x"
14
+
15
+ for x_or_y_0, x_or_y_1, y_or_x_0, y_or_x_1 in zip(
16
+ fig.data[0][x_or_y],
17
+ fig.data[1][x_or_y],
18
+ fig.data[0][y_or_x],
19
+ fig.data[1][y_or_x],
20
+ ):
21
  fig.add_shape(
22
+ **{f"{x_or_y}0": x_or_y_0, f"{x_or_y}1": x_or_y_1, f"{y_or_x}0": y_or_x_0, f"{y_or_x}1": y_or_x_1},
23
  type="line",
24
  layer="below",
 
 
 
 
25
  line_color="grey",
26
  line_width=3,
27
  )
28
 
 
29
  fig.update_traces(marker_size=12)
30
  return fig
31
 
32
 
33
+ salaries = pd.DataFrame(
34
+ {
35
+ "Job": ["Developer", "Analyst", "Manager", "Specialist"],
36
+ "Min": [60000, 55000, 70000, 50000],
37
+ "Max": [130000, 110000, 96400, 80000],
38
+ }
39
  )
40
 
41
+ fig = dumbbell(salaries, y="Job", x=["Min", "Max"], labels={"variable": "", "value": "Salary in $"})
 
pages/examples/funnel.py CHANGED
@@ -1,16 +1,8 @@
1
  import pandas as pd
2
- import vizro.models as vm
3
  import vizro.plotly.express as px
4
- from vizro import Vizro
5
 
6
  funnel_data = pd.DataFrame(
7
  {"Stage": ["Leads", "Sales calls", "Follow-up", "Conversion", "Sales"], "Value": [10, 7, 4, 2, 1]}
8
  )
9
 
10
- page = vm.Page(
11
- title="Funnel",
12
- components=[vm.Graph(figure=px.funnel_area(funnel_data, names="Stage", values="Value"))],
13
- )
14
-
15
- dashboard = vm.Dashboard(pages=[page])
16
- Vizro().build(dashboard).run()
 
1
  import pandas as pd
 
2
  import vizro.plotly.express as px
 
3
 
4
  funnel_data = pd.DataFrame(
5
  {"Stage": ["Leads", "Sales calls", "Follow-up", "Conversion", "Sales"], "Value": [10, 7, 4, 2, 1]}
6
  )
7
 
8
+ fig = px.funnel_area(funnel_data, names="Stage", values="Value")
 
 
 
 
 
 
pages/examples/gantt.py CHANGED
@@ -1,7 +1,5 @@
1
  import pandas as pd
2
- import vizro.models as vm
3
  import vizro.plotly.express as px
4
- from vizro import Vizro
5
 
6
  tasks = pd.DataFrame(
7
  [
@@ -9,15 +7,6 @@ tasks = pd.DataFrame(
9
  {"Task": "Job B", "Start": "2009-03-05", "Finish": "2009-04-15"},
10
  {"Task": "Job C", "Start": "2009-02-20", "Finish": "2009-05-30"},
11
  ]
12
- )
13
 
14
-
15
- page = vm.Page(
16
- title="Gantt",
17
- components=[
18
- vm.Graph(px.timeline(tasks.sort_values("Start", ascending=False), x_start="Start", x_end="Finish", y="Task"))
19
- ],
20
- )
21
-
22
- dashboard = vm.Dashboard(pages=[page])
23
- Vizro().build(dashboard).run()
 
1
  import pandas as pd
 
2
  import vizro.plotly.express as px
 
3
 
4
  tasks = pd.DataFrame(
5
  [
 
7
  {"Task": "Job B", "Start": "2009-03-05", "Finish": "2009-04-15"},
8
  {"Task": "Job C", "Start": "2009-02-20", "Finish": "2009-05-30"},
9
  ]
10
+ ).sort_values("Start", ascending=False)
11
 
12
+ fig = px.timeline(tasks, x_start="Start", x_end="Finish", y="Task")
 
 
 
 
 
 
 
 
 
pages/examples/heatmap.py CHANGED
@@ -1,15 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
- page = vm.Page(
8
- title="Heatmap",
9
- components=[
10
- vm.Graph(figure=px.density_heatmap(tips, x="day", y="size", z="tip", histfunc="avg", text_auto="$.2f")),
11
- ],
12
- )
13
-
14
- dashboard = vm.Dashboard(pages=[page])
15
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.density_heatmap(tips, x="day", y="size", z="tip", histfunc="avg", text_auto="$.2f")
 
 
 
 
 
 
 
 
pages/examples/histogram.py CHANGED
@@ -1,13 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
- page = vm.Page(
8
- title="Histogram",
9
- components=[vm.Graph(px.histogram(tips, x="total_bill"))],
10
- )
11
-
12
- dashboard = vm.Dashboard(pages=[page])
13
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.histogram(tips, x="total_bill")
 
 
 
 
 
 
pages/examples/line.py CHANGED
@@ -1,13 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  stocks = px.data.stocks()
6
 
7
- page = vm.Page(
8
- title="Line",
9
- components=[vm.Graph(figure=px.line(stocks, x="date", y="GOOG"))],
10
- )
11
-
12
- dashboard = vm.Dashboard(pages=[page])
13
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  stocks = px.data.stocks()
4
 
5
+ fig = px.line(stocks, x="date", y="GOOG")
 
 
 
 
 
 
pages/examples/magnitude_column.py CHANGED
@@ -1,23 +1,7 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
-
7
- page = vm.Page(
8
- title="Column",
9
- components=[
10
- vm.Graph(
11
- figure=px.bar(
12
- gapminder.query(
13
- "year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])"
14
- ),
15
- y="pop",
16
- x="country",
17
- )
18
- )
19
- ],
20
  )
21
 
22
- dashboard = vm.Dashboard(pages=[page])
23
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = px.data.gapminder().query(
4
+ "year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])"
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  )
6
 
7
+ fig = px.bar(gapminder, y="pop", x="country")
 
pages/examples/ordered_bar.py CHANGED
@@ -1,25 +1,9 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
-
7
-
8
- page = vm.Page(
9
- title="Ordered bar",
10
- components=[
11
- vm.Graph(
12
- figure=px.bar(
13
- gapminder.query(
14
- "year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])"
15
- ).sort_values("pop"),
16
- x="pop",
17
- y="country",
18
- orientation="h",
19
- )
20
- )
21
- ],
22
  )
23
 
24
- dashboard = vm.Dashboard(pages=[page])
25
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = (
4
+ px.data.gapminder()
5
+ .query("year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])")
6
+ .sort_values("pop")
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  )
8
 
9
+ fig = px.bar(gapminder, x="pop", y="country", orientation="h")
 
pages/examples/ordered_column.py CHANGED
@@ -1,24 +1,9 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
-
7
-
8
- page = vm.Page(
9
- title="Ordered column",
10
- components=[
11
- vm.Graph(
12
- figure=px.bar(
13
- gapminder.query(
14
- "year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])"
15
- ).sort_values("pop"),
16
- y="pop",
17
- x="country",
18
- )
19
- )
20
- ],
21
  )
22
 
23
- dashboard = vm.Dashboard(pages=[page])
24
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = (
4
+ px.data.gapminder()
5
+ .query("year == 2007 and country.isin(['United States', 'Pakistan', 'India', 'China', 'Indonesia'])")
6
+ .sort_values("pop")
 
 
 
 
 
 
 
 
 
 
 
 
7
  )
8
 
9
+ fig = px.bar(gapminder, y="pop", x="country")
 
pages/examples/paired_bar.py CHANGED
@@ -1,26 +1,13 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
-
8
- page = vm.Page(
9
- title="Paired bar",
10
- components=[
11
- vm.Graph(
12
- figure=px.histogram(
13
- tips,
14
- y="day",
15
- x="total_bill",
16
- color="sex",
17
- barmode="group",
18
- orientation="h",
19
- category_orders={"day": ["Thur", "Fri", "Sat", "Sun"]},
20
- ),
21
- )
22
- ],
23
  )
24
-
25
- dashboard = vm.Dashboard(pages=[page])
26
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.histogram(
6
+ tips,
7
+ y="day",
8
+ x="total_bill",
9
+ color="sex",
10
+ barmode="group",
11
+ orientation="h",
12
+ category_orders={"day": ["Thur", "Fri", "Sat", "Sun"]},
 
 
 
 
 
 
 
 
13
  )
 
 
 
pages/examples/paired_column.py CHANGED
@@ -1,25 +1,7 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
-
8
- page = vm.Page(
9
- title="Paired column",
10
- components=[
11
- vm.Graph(
12
- figure=px.histogram(
13
- tips,
14
- x="day",
15
- y="total_bill",
16
- color="sex",
17
- barmode="group",
18
- category_orders={"day": ["Thur", "Fri", "Sat", "Sun"]},
19
- ),
20
- )
21
- ],
22
  )
23
-
24
- dashboard = vm.Dashboard(pages=[page])
25
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.histogram(
6
+ tips, x="day", y="total_bill", color="sex", barmode="group", category_orders={"day": ["Thur", "Fri", "Sat", "Sun"]}
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  )
 
 
 
pages/examples/parallel_coordinates.py CHANGED
@@ -1,19 +1,7 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  iris = px.data.iris()
6
 
7
- page = vm.Page(
8
- title="Parallel coordinates",
9
- components=[
10
- vm.Graph(
11
- figure=px.parallel_coordinates(
12
- iris, color="species_id", dimensions=["sepal_width", "sepal_length", "petal_width", "petal_length"]
13
- )
14
- )
15
- ],
16
  )
17
-
18
- dashboard = vm.Dashboard(pages=[page])
19
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  iris = px.data.iris()
4
 
5
+ fig = px.parallel_coordinates(
6
+ iris, color="species_id", dimensions=["sepal_width", "sepal_length", "petal_width", "petal_length"]
 
 
 
 
 
 
 
7
  )
 
 
 
pages/examples/pie.py CHANGED
@@ -1,13 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
- page = vm.Page(
8
- title="Pie",
9
- components=[vm.Graph(figure=px.pie(tips, values="tip", names="day"))],
10
- )
11
-
12
- dashboard = vm.Dashboard(pages=[page])
13
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.pie(tips, values="tip", names="day")
 
 
 
 
 
 
pages/examples/radar.py CHANGED
@@ -1,25 +1,15 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
  from vizro.models.types import capture
5
 
6
- wind = px.data.wind()
7
-
8
 
9
  @capture("graph")
10
- def radar(data_frame, **kwargs):
11
- """Creates a radar chart using Plotly's line_polar."""
12
  fig = px.line_polar(data_frame, **kwargs)
13
  fig.update_traces(fill="toself")
14
  return fig
15
 
16
 
17
- page = vm.Page(
18
- title="Radar",
19
- components=[
20
- vm.Graph(figure=radar(wind.query("strength == '1-2'"), r="frequency", theta="direction", line_close=True))
21
- ],
22
- )
23
 
24
- dashboard = vm.Dashboard(pages=[page])
25
- Vizro().build(dashboard).run()
 
1
+ import pandas as pd
2
  import vizro.plotly.express as px
 
3
  from vizro.models.types import capture
4
 
 
 
5
 
6
  @capture("graph")
7
+ def radar(data_frame: pd.DataFrame, **kwargs):
 
8
  fig = px.line_polar(data_frame, **kwargs)
9
  fig.update_traces(fill="toself")
10
  return fig
11
 
12
 
13
+ wind = px.data.wind().query("strength == '1-2'")
 
 
 
 
 
14
 
15
+ fig = radar(wind, r="frequency", theta="direction", line_close=True)
 
pages/examples/sankey.py CHANGED
@@ -1,19 +1,7 @@
1
- from typing import List
2
-
3
  import pandas as pd
4
  import plotly.graph_objects as go
5
- import vizro.models as vm
6
- from vizro import Vizro
7
  from vizro.models.types import capture
8
 
9
- sankey_data = pd.DataFrame(
10
- {
11
- "Origin": [0, 1, 0, 2, 3, 3], # indices inside labels
12
- "Destination": [2, 3, 3, 4, 4, 5], # indices inside labels
13
- "Value": [8, 4, 2, 8, 4, 2],
14
- }
15
- )
16
-
17
 
18
  @capture("graph")
19
  def sankey(
@@ -21,44 +9,35 @@ def sankey(
21
  source: str,
22
  target: str,
23
  value: str,
24
- labels: List[str],
25
  ):
26
- fig = go.Figure(
27
- data=[
28
- go.Sankey(
29
- node={
30
- "pad": 16,
31
- "thickness": 16,
32
- "label": labels,
33
- },
34
- link={
35
- "source": data_frame[source],
36
- "target": data_frame[target],
37
- "value": data_frame[value],
38
- "label": labels,
39
- "color": "rgba(205, 209, 228, 0.4)",
40
- },
41
- )
42
- ]
43
  )
44
- fig.update_layout(barmode="relative")
45
- return fig
46
 
47
 
48
- page = vm.Page(
49
- title="Sankey",
50
- components=[
51
- vm.Graph(
52
- figure=sankey(
53
- sankey_data,
54
- labels=["A1", "A2", "B1", "B2", "C1", "C2"],
55
- source="Origin",
56
- target="Destination",
57
- value="Value",
58
- ),
59
- ),
60
- ],
61
  )
62
 
63
- dashboard = vm.Dashboard(pages=[page])
64
- Vizro().build(dashboard).run()
 
 
 
 
1
  import pandas as pd
2
  import plotly.graph_objects as go
 
 
3
  from vizro.models.types import capture
4
 
 
 
 
 
 
 
 
 
5
 
6
  @capture("graph")
7
  def sankey(
 
9
  source: str,
10
  target: str,
11
  value: str,
12
+ labels: list[str],
13
  ):
14
+ return go.Figure(
15
+ data=go.Sankey(
16
+ node={
17
+ "pad": 16,
18
+ "thickness": 16,
19
+ "label": labels,
20
+ },
21
+ link={
22
+ "source": data_frame[source],
23
+ "target": data_frame[target],
24
+ "value": data_frame[value],
25
+ "label": labels,
26
+ "color": "rgba(205, 209, 228, 0.4)",
27
+ },
28
+ ),
29
+ layout={"barmode": "relative"},
 
30
  )
 
 
31
 
32
 
33
+ sankey_data = pd.DataFrame(
34
+ {
35
+ "Origin": [0, 1, 0, 2, 3, 3], # indices inside labels
36
+ "Destination": [2, 3, 3, 4, 4, 5], # indices inside labels
37
+ "Value": [8, 4, 2, 8, 4, 2],
38
+ }
 
 
 
 
 
 
 
39
  )
40
 
41
+ fig = sankey(
42
+ sankey_data, labels=["A1", "A2", "B1", "B2", "C1", "C2"], source="Origin", target="Destination", value="Value"
43
+ )
pages/examples/scatter.py CHANGED
@@ -1,13 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  iris = px.data.iris()
6
 
7
- page = vm.Page(
8
- title="Scatter",
9
- components=[vm.Graph(figure=px.scatter(iris, x="sepal_width", y="sepal_length", color="species"))],
10
- )
11
-
12
- dashboard = vm.Dashboard(pages=[page])
13
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  iris = px.data.iris()
4
 
5
+ fig = px.scatter(iris, x="sepal_width", y="sepal_length", color="species")
 
 
 
 
 
 
pages/examples/scatter_matrix.py CHANGED
@@ -1,17 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  iris = px.data.iris()
6
 
7
- page = vm.Page(
8
- title="Scatter matrix",
9
- components=[
10
- vm.Graph(
11
- figure=px.scatter_matrix(iris, dimensions=["sepal_length", "sepal_width", "petal_length", "petal_width"])
12
- )
13
- ],
14
- )
15
-
16
- dashboard = vm.Dashboard(pages=[page])
17
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  iris = px.data.iris()
4
 
5
+ fig = px.scatter_matrix(iris, dimensions=["sepal_length", "sepal_width", "petal_length", "petal_width"])
 
 
 
 
 
 
 
 
 
 
pages/examples/stacked_bar.py CHANGED
@@ -1,14 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
-
8
- page = vm.Page(
9
- title="Stacked bar",
10
- components=[vm.Graph(figure=px.histogram(tips, y="sex", x="total_bill", color="day", orientation="h"))],
11
- )
12
-
13
- dashboard = vm.Dashboard(pages=[page])
14
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.histogram(tips, y="sex", x="total_bill", color="day", orientation="h")
 
 
 
 
 
 
 
pages/examples/stacked_column.py CHANGED
@@ -1,14 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
-
8
- page = vm.Page(
9
- title="Stacked column",
10
- components=[vm.Graph(figure=px.histogram(tips, x="sex", y="total_bill", color="day"))],
11
- )
12
-
13
- dashboard = vm.Dashboard(pages=[page])
14
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.histogram(tips, x="sex", y="total_bill", color="day")
 
 
 
 
 
 
 
pages/examples/stepped_line.py CHANGED
@@ -1,7 +1,5 @@
1
  import pandas as pd
2
- import vizro.models as vm
3
  import vizro.plotly.express as px
4
- from vizro import Vizro
5
 
6
  stepped_line_data = pd.DataFrame(
7
  {
@@ -10,18 +8,4 @@ stepped_line_data = pd.DataFrame(
10
  }
11
  )
12
 
13
- page = vm.Page(
14
- title="Stepped line",
15
- components=[
16
- vm.Graph(
17
- figure=px.line(
18
- data_frame=stepped_line_data,
19
- x="year",
20
- y="rate",
21
- line_shape="vh",
22
- ),
23
- )
24
- ],
25
- )
26
- dashboard = vm.Dashboard(pages=[page])
27
- Vizro().build(dashboard).run()
 
1
  import pandas as pd
 
2
  import vizro.plotly.express as px
 
3
 
4
  stepped_line_data = pd.DataFrame(
5
  {
 
8
  }
9
  )
10
 
11
+ fig = px.line(data_frame=stepped_line_data, x="year", y="rate", line_shape="vh")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/time_column.py CHANGED
@@ -1,36 +1,16 @@
1
  import pandas as pd
2
- import vizro.models as vm
3
  import vizro.plotly.express as px
4
- from vizro import Vizro
5
  from vizro.models.types import capture
6
 
7
- gapminder = px.data.gapminder()
8
-
9
 
10
  @capture("graph")
11
- def categorical_column(data_frame: pd.DataFrame, x: str, y: str):
12
- fig = px.bar(
13
- data_frame,
14
- x=x,
15
- y=y,
16
- )
17
- # So ticks are aligned with bars when xaxes values are numbers (e.g. years)
18
  fig.update_xaxes(type="category")
19
  return fig
20
 
21
 
22
- page = vm.Page(
23
- title="Column",
24
- components=[
25
- vm.Graph(
26
- figure=categorical_column(
27
- gapminder.query("country == 'Nigeria' and year > 1970"),
28
- y="lifeExp",
29
- x="year",
30
- )
31
- )
32
- ],
33
- )
34
 
35
- dashboard = vm.Dashboard(pages=[page])
36
- Vizro().build(dashboard).run()
 
1
  import pandas as pd
2
+ import plotly.graph_objects as go
3
  import vizro.plotly.express as px
 
4
  from vizro.models.types import capture
5
 
 
 
6
 
7
  @capture("graph")
8
+ def categorical_column(data_frame: pd.DataFrame, **kwargs) -> go.Figure:
9
+ fig = px.bar(data_frame, **kwargs)
 
 
 
 
 
10
  fig.update_xaxes(type="category")
11
  return fig
12
 
13
 
14
+ gapminder = px.data.gapminder().query("country == 'Nigeria' and year > 1970")
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ fig = categorical_column(gapminder, x="year", y="lifeExp")
 
pages/examples/treemap.py CHANGED
@@ -1,22 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
- gapminder = px.data.gapminder()
6
 
7
- page = vm.Page(
8
- title="Treemap",
9
- components=[
10
- vm.Graph(
11
- figure=px.treemap(
12
- gapminder.query("year == 2007"),
13
- path=[px.Constant("world"), "continent", "country"],
14
- values="pop",
15
- color="lifeExp",
16
- )
17
- ),
18
- ],
19
- )
20
-
21
- dashboard = vm.Dashboard(pages=[page])
22
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
+ gapminder = px.data.gapminder().query("year == 2007")
4
 
5
+ fig = px.treemap(gapminder, path=[px.Constant("world"), "continent", "country"], values="pop", color="lifeExp")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/examples/violin.py CHANGED
@@ -1,15 +1,5 @@
1
- import vizro.models as vm
2
  import vizro.plotly.express as px
3
- from vizro import Vizro
4
 
5
  tips = px.data.tips()
6
 
7
- page = vm.Page(
8
- title="Violin",
9
- components=[
10
- vm.Graph(figure=px.violin(tips, y="total_bill", x="day", color="day", box=True)),
11
- ],
12
- )
13
-
14
- dashboard = vm.Dashboard(pages=[page])
15
- Vizro().build(dashboard).run()
 
 
1
  import vizro.plotly.express as px
 
2
 
3
  tips = px.data.tips()
4
 
5
+ fig = px.violin(tips, y="total_bill", x="day", color="day", box=True)
 
 
 
 
 
 
 
 
pages/examples/waterfall.py CHANGED
@@ -1,51 +1,27 @@
1
- from typing import List
2
-
3
  import pandas as pd
4
  import plotly.graph_objects as go
5
- import vizro.models as vm
6
- from vizro import Vizro
7
  from vizro.models.types import capture
8
 
9
- waterfall_data = pd.DataFrame(
10
- {
11
- "x": ["Sales", "Consulting", "Net revenue", "Purchases", "Other expenses", "Profit before tax"],
12
- "y": [60, 80, 0, -40, -20, 0],
13
- "measure": ["relative", "relative", "total", "relative", "relative", "total"],
14
- }
15
- )
16
-
17
 
18
  @capture("graph")
19
  def waterfall(
20
  data_frame: pd.DataFrame,
21
  x: str,
22
  y: str,
23
- measure: List[str],
24
  ):
25
- fig = go.Figure(
26
- go.Waterfall(
27
- x=data_frame[x],
28
- y=data_frame[y],
29
- measure=data_frame[measure],
30
- )
31
  )
32
- fig.update_layout(showlegend=False)
33
- return fig
34
 
35
 
36
- page = vm.Page(
37
- title="Waterfall",
38
- components=[
39
- vm.Graph(
40
- figure=waterfall(
41
- waterfall_data,
42
- x="x",
43
- y="y",
44
- measure="measure",
45
- )
46
- )
47
- ],
48
  )
49
 
50
- dashboard = vm.Dashboard(pages=[page])
51
- Vizro().build(dashboard).run()
 
 
 
1
  import pandas as pd
2
  import plotly.graph_objects as go
 
 
3
  from vizro.models.types import capture
4
 
 
 
 
 
 
 
 
 
5
 
6
  @capture("graph")
7
  def waterfall(
8
  data_frame: pd.DataFrame,
9
  x: str,
10
  y: str,
11
+ measure: list[str],
12
  ):
13
+ return go.Figure(
14
+ data=go.Waterfall(x=data_frame[x], y=data_frame[y], measure=data_frame[measure]),
15
+ layout={"showlegend": False},
 
 
 
16
  )
 
 
17
 
18
 
19
+ waterfall_data = pd.DataFrame(
20
+ {
21
+ "x": ["Sales", "Consulting", "Net revenue", "Purchases", "Other expenses", "Profit before tax"],
22
+ "y": [60, 80, 0, -40, -20, 0],
23
+ "measure": ["relative", "relative", "total", "relative", "relative", "total"],
24
+ }
 
 
 
 
 
 
25
  )
26
 
27
+ fig = waterfall(waterfall_data, x="x", y="y", measure="measure")
 
pages/flow.py CHANGED
@@ -1,12 +1,12 @@
1
  """Flow charts."""
2
 
3
  import vizro.models as vm
4
- from custom_charts import sankey
5
 
6
  from pages._factories import waterfall_factory
7
- from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file, sankey_data
 
8
 
9
- sankey = vm.Page(
10
  title="Sankey",
11
  path="flow/sankey",
12
  layout=vm.Layout(grid=PAGE_GRID),
@@ -32,19 +32,21 @@ sankey = vm.Page(
32
  possible.
33
  """
34
  ),
35
- vm.Graph(
36
- figure=sankey(
37
- sankey_data,
38
- labels=["A1", "A2", "B1", "B2", "C1", "C2"],
39
- source="Origin",
40
- target="Destination",
41
- value="Value",
42
- ),
 
 
 
43
  ),
44
- make_code_clipboard_from_py_file("sankey.py"),
45
  ],
46
  )
47
 
48
- waterfall = waterfall_factory("flow")
49
 
50
- pages = [sankey, waterfall]
 
1
  """Flow charts."""
2
 
3
  import vizro.models as vm
 
4
 
5
  from pages._factories import waterfall_factory
6
+ from pages._pages_utils import PAGE_GRID, make_code_clipboard_from_py_file
7
+ from pages.examples import sankey
8
 
9
+ sankey_page = vm.Page(
10
  title="Sankey",
11
  path="flow/sankey",
12
  layout=vm.Layout(grid=PAGE_GRID),
 
32
  possible.
33
  """
34
  ),
35
+ vm.Graph(figure=sankey.fig),
36
+ vm.Tabs(
37
+ tabs=[
38
+ vm.Container(
39
+ title="Vizro dashboard", components=[make_code_clipboard_from_py_file("sankey.py", mode="vizro")]
40
+ ),
41
+ vm.Container(
42
+ title="Plotly figure",
43
+ components=[make_code_clipboard_from_py_file("sankey.py", mode="plotly")],
44
+ ),
45
+ ]
46
  ),
 
47
  ],
48
  )
49
 
50
+ waterfall_page = waterfall_factory("flow")
51
 
52
+ pages = [sankey_page, waterfall_page]