3

I'm trying to use plotly to arrange gauges in a grid layout (to give us a Streamlit dashboard showing SLO gauges for a group of teams).

I can't use subplots because they're not compatible with Indicators:

ValueError: Trace type 'indicator' is not compatible with subplot type 'xy' at grid position (1, 1)
See the docstring for the specs argument to plotly.subplots.make_subplots for more information on subplot types

What's the most elegant (least code) way to arrange gauge Indicators in a grid?

vestland
  • 55,229
  • 37
  • 187
  • 305
quantoid
  • 530
  • 5
  • 16
  • you can use subplots for none xy grids, need to provide appropriate params. edit you question to include a reproducible example. I can't start to answer without more context – Rob Raymond Jun 11 '21 at 06:44
  • @quantoid How did the provided suggestions work out for you? – vestland Jul 09 '21 at 07:20

2 Answers2

2
  • have synthesized data to match what you have described
  • subplots() can be used, subplot types Have used a list comprehension to build this requirement
  • clearly more beautification is required for this example, titles are overlapping gauges
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd

# a bit of data to generate guages from...
df = pd.DataFrame({"team":["sprint 1", "sprint 2", "qa"],"backlog":[45,55,22],"defects":[23,44,33]}).set_index("team")

# need to define types of subplots...
fig = make_subplots(
    rows=len(df),
    cols=len(df.columns),
    specs=[[{"type": "indicator"} for c in df.columns] for t in df.index],
)

for r, team in enumerate(df.index):
    for c, measure in enumerate(df.columns):
        fig.add_trace(
            go.Indicator(mode="gauge+number", value=df.loc[team, measure], title={"text":f"{team} - {measure}"}),
            row=r + 1,
            col=c + 1,
        )

fig.update_layout(margin={"l": 0, "r": 20, "t": 50, "b": 0})

enter image description here

Rob Raymond
  • 29,118
  • 3
  • 14
  • 30
1

go.Indicator is a gauge chart and has a special attribute domain that will let you place your indicators within a figure object by specifying x and y between [0, 1]. Take a look at Indicators in Python for this example:

Plot

enter image description here

Complete code:

import plotly.graph_objects as go

fig = go.Figure()

fig.add_trace(go.Indicator(
    value = 200,
    delta = {'reference': 160},
    gauge = {
        'axis': {'visible': False}},
    domain = {'row': 0, 'column': 0}))

fig.add_trace(go.Indicator(
    value = 120,
    gauge = {
        'shape': "bullet",
        'axis' : {'visible': False}},
    domain = {'x': [0.05, 0.5], 'y': [0.15, 0.35]}))

fig.add_trace(go.Indicator(
    mode = "number+delta",
    value = 300,
    domain = {'row': 0, 'column': 1}))

fig.add_trace(go.Indicator(
    mode = "delta",
    value = 40,
    domain = {'row': 1, 'column': 1}))

fig.update_layout(
    grid = {'rows': 2, 'columns': 2, 'pattern': "independent"},
    template = {'data' : {'indicator': [{
        'title': {'text': "Speed"},
        'mode' : "number+delta+gauge",
        'delta' : {'reference': 90}}]
                         }})

And for those who like to study these things in detail:

| The 'domain' property is an instance of Domain | that may be specified as: | - An instance of :class:plotly.graph_objs.indicator.Domain | - A dict of string/value properties that will be passed | to the Domain constructor | | Supported dict properties: |
| column | If there is a layout grid, use the domain for | this column in the grid for this indicator | trace . | row |
If there is a layout grid, use the domain for | this row in the grid for this indicator trace . | x |
Sets the horizontal domain of this indicator | trace (in plot fraction). | y | Sets the vertical domain of this indicator | trace (in plot fraction).

vestland
  • 55,229
  • 37
  • 187
  • 305