Show Sidebar Hide Sidebar

Gauge Charts in Python

How to make guage meter charts in Python with Plotly.

New to Plotly?

Plotly's Python library is free and open source! Get started by downloading the client and reading the primer.
You can set up Plotly to work in online or offline mode, or in jupyter notebooks.
We also have a quick-reference cheatsheet (new!) to help you get started!

Gauge Chart Outline

We will use donut charts with custom colors to create a semi-circular gauge meter, such that lower half of the chart is invisible(same color as background).

This semi-circular meter will be overlapped on a base donut chart to create the analog range of the meter. We will have to rotate the base chart to align the range marks in the edges of meter's section, because by default Plotly places them at the center of a pie section.

Base Chart (rotated)

To make a gauge meter with 5 equally sized sections, we will create 6 sections in the base chart. So that center(position of label) aligns with the edges of each section.

In [1]:
import plotly.plotly as py
import plotly.graph_objs as go

base_chart = {
    "values": [40, 10, 10, 10, 10, 10, 10],
    "labels": ["-", "0", "20", "40", "60", "80", "100"],
    "domain": {"x": [0, .48]},
    "marker": {
        "colors": [
            'rgb(255, 255, 255)',
            'rgb(255, 255, 255)',
            'rgb(255, 255, 255)',
            'rgb(255, 255, 255)',
            'rgb(255, 255, 255)',
            'rgb(255, 255, 255)',
            'rgb(255, 255, 255)'
        ],
        "line": {
            "width": 1
        }
    },
    "name": "Gauge",
    "hole": .4,
    "type": "pie",
    "direction": "clockwise",
    "rotation": 108,
    "showlegend": False,
    "hoverinfo": "none",
    "textinfo": "label",
    "textposition": "outside"
}

Outline of the generated base chart will look like the one below.

Gauge
Meter Chart

Now we will superimpose our semi-circular meter on top of this.
For that, we will also use 6 sections, but one of them will be invisible to form the lower half (colored same as the background).

In [2]:
meter_chart = {
    "values": [50, 10, 10, 10, 10, 10],
    "labels": ["Log Level", "Debug", "Info", "Warn", "Error", "Fatal"],
    "marker": {
        'colors': [
            'rgb(255, 255, 255)',
            'rgb(232,226,202)',
            'rgb(226,210,172)',
            'rgb(223,189,139)',
            'rgb(223,162,103)',
            'rgb(226,126,64)'
        ]
    },
    "domain": {"x": [0, 0.48]},
    "name": "Gauge",
    "hole": .3,
    "type": "pie",
    "direction": "clockwise",
    "rotation": 90,
    "showlegend": False,
    "textinfo": "label",
    "textposition": "inside",
    "hoverinfo": "none"
}

You can see that the first section's value is equal to the sum of other sections.
We are using rotation and direction parameters to start the sections from 3 o'clock [rotation=90] instead of the default value of 12 o'clock [rotation=0].

After imposing on the base chart, it'll look like this.

Gauge vs Gauge
Dial

Now we need a dial to show the current position in the meter at a particular time.
Plotly's path shape can be used for this. A nice explanation of SVG path is available here by Mozilla.
We can use a filled triangle to create our Dial.

...
'shapes': [
    {
        'type': 'path',
        'path': 'M 0.235 0.5 L 0.24 0.62 L 0.245 0.5 Z',
        'fillcolor': 'rgba(44, 160, 101, 0.5)',
        'line': {
            'width': 0.5
        },
        'xref': 'paper',
        'yref': 'paper'
    }
]
...

For the filled-triangle, the first point (0.235, 0.5) is left to the center of meter (0.24, 0.5), the second point (0.24 0.62) is representing the current position on the semi-circle and the third point (0.245, 0.5) is just right to the center.

M represents the 'Move' command that moves cursor to a particular point, L is the 'Line To' command and Z represents the 'Close Path' command. This way, this path string makes a triangle with those three points.

In [3]:
layout = {
    'xaxis': {
        'showticklabels': False,
        'autotick': False,
        'showgrid': False,
        'zeroline': False,
    },
    'yaxis': {
        'showticklabels': False,
        'autotick': False,
        'showgrid': False,
        'zeroline': False,
    },
    'shapes': [
        {
            'type': 'path',
            'path': 'M 0.235 0.5 L 0.24 0.65 L 0.245 0.5 Z',
            'fillcolor': 'rgba(44, 160, 101, 0.5)',
            'line': {
                'width': 0.5
            },
            'xref': 'paper',
            'yref': 'paper'
        }
    ],
    'annotations': [
        {
            'xref': 'paper',
            'yref': 'paper',
            'x': 0.23,
            'y': 0.45,
            'text': '50',
            'showarrow': False
        }
    ]
}

# we don't want the boundary now
base_chart['marker']['line']['width'] = 0

fig = {"data": [base_chart, meter_chart],
       "layout": layout}
py.iplot(fig, filename='gauge-meter-chart')
Out[3]:

Reference

See https://plot.ly/python/reference/ for more information and chart attribute options!

Still need help?
Contact Us

For guaranteed 24 hour response turnarounds, upgrade to a Developer Support Plan.