Data Visualization

Interactive charts and graphs with Plotly integration

Data Visualization

Interactive charts and graphs with Plotly integration


Introduction

This page demonstrates how to create interactive data visualizations using Plotly with your Dash Documentation Boilerplate. Plotly provides powerful, interactive charts that integrate seamlessly with Dash callbacks.


Basic Chart Example

Let's start with a simple bar chart example:

:code: false Source code:

# File: docs/data-visualization/basic_chart.py

from dash import dcc, callback, Input, Output
import dash_mantine_components as dmc
import pandas as pd
import plotly.express as px

# Register Mantine templates
dmc.add_figure_templates(default="mantine_light")

# Sample data
df = pd.DataFrame({
    "Category": ["Product A", "Product B", "Product C", "Product D", "Product E"],
    "Sales": [120, 95, 180, 140, 165]
})

# Create initial figure
fig = px.bar(
    df,
    x="Category",
    y="Sales",
    title="Product Sales Comparison",
    color="Sales",
    color_continuous_scale="teal"
)

fig.update_layout(
    xaxis_title="Product Category",
    yaxis_title="Sales (Units)",
    showlegend=False,
    height=400
)

component = dcc.Graph(figure=fig, id='figure-basic-chart', config={'displayModeBar': False})


@callback(
    Output('figure-basic-chart', "figure"),
    Input("color-scheme-storage", "data"),
)
def update_figure_theme(theme):
    """Update chart template based on color scheme"""
    template = "mantine_dark" if theme == "dark" else "mantine_light"

    # Recreate the figure with the correct template
    fig = px.bar(
        df,
        x="Category",
        y="Sales",
        title="Product Sales Comparison",
        color="Sales",
        color_continuous_scale="teal",
        template=template
    )

    fig.update_layout(
        xaxis_title="Product Category",
        yaxis_title="Sales (Units)",
        showlegend=False,
        height=400
    )

    return fig

:defaultExpanded: false :withExpandedButton: true


Interactive Line Chart

This example shows multiple lines with hover tooltips and a legend:

:code: false Source code:

# File: docs/data-visualization/line_chart.py

from dash import dcc, callback, Input, Output
import dash_mantine_components as dmc
import pandas as pd
import plotly.express as px
import numpy as np

# Register Mantine templates
dmc.add_figure_templates(default="mantine_light")

# Generate sample time series data
dates = pd.date_range('2024-01-01', periods=30, freq='D')
np.random.seed(42)

df = pd.DataFrame({
    'Date': dates,
    'Revenue': np.cumsum(np.random.randn(30) * 10 + 100),
    'Costs': np.cumsum(np.random.randn(30) * 8 + 80),
    'Profit': np.cumsum(np.random.randn(30) * 5 + 20)
})

# Melt the dataframe for plotting multiple lines
df_melted = df.melt(id_vars=['Date'], var_name='Metric', value_name='Amount')

# Create initial figure
fig = px.line(
    df_melted,
    x='Date',
    y='Amount',
    color='Metric',
    title='Financial Metrics Over Time',
    color_discrete_map={
        'Revenue': '#12B886',  # Teal
        'Costs': '#FA5252',    # Red
        'Profit': '#228BE6'    # Blue
    }
)

fig.update_layout(
    xaxis_title='Date',
    yaxis_title='Amount ($)',
    hovermode='x unified',
    height=450,
    legend=dict(
        orientation="h",
        yanchor="bottom",
        y=1.02,
        xanchor="right",
        x=1
    )
)

component = dcc.Graph(figure=fig, id='figure-line-chart')


@callback(
    Output('figure-line-chart', "figure"),
    Input("color-scheme-storage", "data"),
)
def update_figure_theme(theme):
    """Update chart template based on color scheme"""
    template = "mantine_dark" if theme == "dark" else "mantine_light"

    # Recreate the figure with the correct template
    fig = px.line(
        df_melted,
        x='Date',
        y='Amount',
        color='Metric',
        title='Financial Metrics Over Time',
        color_discrete_map={
            'Revenue': '#12B886',
            'Costs': '#FA5252',
            'Profit': '#228BE6'
        },
        template=template
    )

    fig.update_layout(
        xaxis_title='Date',
        yaxis_title='Amount ($)',
        hovermode='x unified',
        height=450,
        legend=dict(
            orientation="h",
            yanchor="bottom",
            y=1.02,
            xanchor="right",
            x=1
        )
    )

    return fig

Scatter Plot with Filtering

An interactive scatter plot with dropdown filtering:

:code: false Source code:

# File: docs/data-visualization/scatter_plot.py

from dash import html, dcc, callback, Input, Output, State
import pandas as pd
import plotly.express as px
import dash_mantine_components as dmc
import numpy as np

# Register Mantine templates
dmc.add_figure_templates(default="mantine_light")

# Generate sample data
np.random.seed(42)
df = pd.DataFrame({
    'Height': np.random.normal(170, 10, 100),
    'Weight': np.random.normal(70, 15, 100),
    'Age': np.random.randint(20, 60, 100),
    'Gender': np.random.choice(['Male', 'Female'], 100)
})

component = html.Div([
    dmc.Title("Height vs Weight Analysis", order=4, mb=10),
    dmc.Select(
        label="Filter by Gender",
        data=[
            {"label": "All", "value": "all"},
            {"label": "Male", "value": "Male"},
            {"label": "Female", "value": "Female"}
        ],
        value="all",
        id="gender-filter",
        mb=15,
        style={"maxWidth": "200px"}
    ),
    dcc.Graph(id="scatter-chart")
])


@callback(
    Output("scatter-chart", "figure"),
    Input("gender-filter", "value"),
    Input("color-scheme-storage", "data"),
)
def update_scatter(gender, theme):
    """Update scatter plot based on gender filter and theme"""
    template = "mantine_dark" if theme == "dark" else "mantine_light"

    if gender == "all":
        filtered_df = df
    else:
        filtered_df = df[df['Gender'] == gender]

    fig = px.scatter(
        filtered_df,
        x='Height',
        y='Weight',
        color='Gender',
        size='Age',
        title=f'Height vs Weight{" - " + gender if gender != "all" else ""}',
        hover_data=['Age'],
        color_discrete_map={'Male': '#228BE6', 'Female': '#FA5252'},
        template=template
    )

    fig.update_layout(
        xaxis_title='Height (cm)',
        yaxis_title='Weight (kg)',
        height=450
    )

    return fig

Real-Time Data Updates

This example demonstrates how to update charts in real-time using intervals:

:code: false Source code:

# File: docs/data-visualization/realtime_chart.py

from dash import html, dcc, callback, Input, Output
import dash_mantine_components as dmc
import plotly.graph_objects as go
from collections import deque
import random
from datetime import datetime, timedelta

# Register Mantine templates
dmc.add_figure_templates(default="mantine_light")

# Initialize deque to store recent data points
MAX_DATA_POINTS = 50
time_data = deque(maxlen=MAX_DATA_POINTS)
value_data = deque(maxlen=MAX_DATA_POINTS)

# Initialize with some data
start_time = datetime.now()
for i in range(20):
    time_data.append(start_time + timedelta(seconds=i))
    value_data.append(random.uniform(20, 80))

component = html.Div([
    dmc.Title("Real-Time Data Stream", order=4, mb=10),
    dmc.Alert(
        "This chart updates every 2 seconds with simulated real-time data",
        color="blue",
        mb=15
    ),
    dcc.Graph(id="realtime-graph"),
    dcc.Interval(
        id="interval-component",
        interval=2000,  # Update every 2 seconds
        n_intervals=0
    )
])


@callback(
    Output("realtime-graph", "figure"),
    Input("interval-component", "n_intervals"),
    Input("color-scheme-storage", "data"),
)
def update_realtime(n, theme):
    """Update real-time chart with new data and theme"""
    template = "mantine_dark" if theme == "dark" else "mantine_light"

    # Add new data point
    time_data.append(datetime.now())

    # Generate new value with some randomness
    if len(value_data) > 0:
        last_value = value_data[-1]
        new_value = last_value + random.uniform(-5, 5)
        # Keep value in reasonable range
        new_value = max(10, min(90, new_value))
    else:
        new_value = 50

    value_data.append(new_value)

    # Create figure
    fig = go.Figure()

    fig.add_trace(go.Scatter(
        x=list(time_data),
        y=list(value_data),
        mode='lines+markers',
        name='Sensor Reading',
        line=dict(color='#12B886', width=2),
        marker=dict(size=6)
    ))

    fig.update_layout(
        title='Live Sensor Data',
        xaxis_title='Time',
        yaxis_title='Value',
        yaxis_range=[0, 100],
        hovermode='x',
        height=400,
        showlegend=False,
        template=template
    )

    return fig

Chart Types Reference

Available Plotly Chart Types

Plotly Express provides many chart types:

Basic Charts
Statistical Charts
Scientific Charts
Financial Charts

Customization Tips

Theme Integration

Make charts match your Mantine theme automatically using DMC figure templates:

import dash_mantine_components as dmc
import plotly.express as px

# Register Mantine templates (mantine_light and mantine_dark)
dmc.add_figure_templates(default="mantine_light")

# Charts now automatically use the Mantine template
fig = px.bar(df, x="category", y="value")

# The templates match your theme's colors, fonts, and styling
# For more info: https://www.dash-mantine-components.com/plotly-templates

All examples on this page use dmc.add_figure_templates() to ensure charts render correctly in both light and dark modes.

Responsive Charts

Make charts responsive to window size:

fig.update_layout(
    autosize=True,
    margin=dict(l=20, r=20, t=40, b=20),
)

# In your component
dcc.Graph(
    figure=fig,
    config={'responsive': True},
    style={'height': '400px'}
)

Interactive Features

Enable useful interactions:

config = {
    'displayModeBar': True,
    'displaylogo': False,
    'modeBarButtonsToRemove': ['pan2d', 'lasso2d'],
    'toImageButtonOptions': {
        'format': 'png',
        'filename': 'chart',
        'height': 1080,
        'width': 1920,
        'scale': 2
    }
}

dcc.Graph(figure=fig, config=config)

Performance Tips

1. Limit Data Points

For large datasets, consider:

# Sample data if too large
if len(df) > 10000:
    df = df.sample(10000)

2. Use Scattergl for Large Scatter Plots

import plotly.graph_objects as go

fig = go.Figure(data=go.Scattergl(
    x=x_data,
    y=y_data,
    mode='markers'
))

3. Optimize Update Frequency

# Use longer intervals for real-time updates
dcc.Interval(
    interval=2000,  # Update every 2 seconds
    n_intervals=0
)

Common Patterns

Pattern 1: Chart with Controls

## My Visualization

Use the controls below to customize the view:

.. exec::docs.viz.controlled_chart
component = html.Div([
    dmc.Select(
        label="Metric",
        data=[...],
        id="metric-select"
    ),
    dcc.Graph(id="chart")
])

@callback(Output("chart", "figure"), Input("metric-select", "value"))
def update(metric):
    return create_figure(metric)

Pattern 2: Multi-View Dashboard

component = dmc.SimpleGrid([
    dmc.Card([dcc.Graph(figure=fig1)]),
    dmc.Card([dcc.Graph(figure=fig2)]),
    dmc.Card([dcc.Graph(figure=fig3)]),
    dmc.Card([dcc.Graph(figure=fig4)]),
], cols={"base": 1, "sm": 2})

Pattern 3: Clickable Charts

@callback(
    Output("details", "children"),
    Input("chart", "clickData")
)
def display_click_data(clickData):
    if not clickData:
        return "Click on a data point"
    return f"Selected: {clickData['points'][0]['x']}"

Best Practices

1. Add Axis Labels

Always label your axes:

fig.update_layout(
    xaxis_title="Time (hours)",
    yaxis_title="Temperature (°C)"
)

2. Include Titles

Make charts self-explanatory:

fig.update_layout(
    title="Monthly Sales Performance",
    title_x=0.5  # Center the title
)

3. Use Color Wisely

Choose accessible colors:

# Good - accessible color palette
colors = ['#1f77b4', '#ff7f0e', '#2ca02c']

# Even better - use colorblind-friendly palettes
import plotly.express as px
fig = px.bar(df, color_discrete_sequence=px.colors.qualitative.Safe)

4. Add Hover Information

Provide context on hover:

fig = px.scatter(
    df, x="x", y="y",
    hover_data=["category", "value", "date"]
)

5. Handle Empty Data

Always check for empty datasets:

if df.empty:
    return {
        'data': [],
        'layout': {
            'xaxis': {'visible': False},
            'yaxis': {'visible': False},
            'annotations': [{
                'text': 'No data available',
                'showarrow': False,
                'font': {'size': 20}
            }]
        }
    }

Resources


Next Steps


Happy visualizing! 📊


Source: /examples/visualization

Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: