# Data Visualization

> Interactive charts and graphs with Plotly integration

**Site index:** [https://boilerplate.2plot.dev/llms.txt](https://boilerplate.2plot.dev/llms.txt) — every page on this site, as Markdown.  
**Network index:** [https://2plot.dev/llms.txt](https://2plot.dev/llms.txt) — The 2plot network; start here to discover sibling sites.  
**Sibling sites:** 8 more in The 2plot network — listed in the site index above.  
**Sitemap:** https://boilerplate.2plot.dev/sitemap.xml  


---

.. llms_copy::Data Visualization

.. toc::

### 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:

.. exec::docs.data-visualization.basic_chart
    :code: false
Source code:


```python
# 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:

.. exec::docs.data-visualization.line_chart
    :code: false
Source code:


```python
# 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:

.. exec::docs.data-visualization.scatter_plot
    :code: false
Source code:


```python
# 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:

.. exec::docs.data-visualization.realtime_chart
    :code: false
Source code:


```python
# 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
- **Bar Charts** - `px.bar()`
- **Line Charts** - `px.line()`
- **Scatter Plots** - `px.scatter()`
- **Pie Charts** - `px.pie()`
- **Histograms** - `px.histogram()`

##### Statistical Charts
- **Box Plots** - `px.box()`
- **Violin Plots** - `px.violin()`
- **Density Heatmaps** - `px.density_heatmap()`

##### Scientific Charts
- **Scatter Matrix** - `px.scatter_matrix()`
- **Parallel Coordinates** - `px.parallel_coordinates()`
- **3D Scatter** - `px.scatter_3d()`

##### Financial Charts
- **Candlestick** - `go.Candlestick()`
- **OHLC** - `go.Ohlc()`
- **Waterfall** - `go.Waterfall()`

---

### Customization Tips

#### Theme Integration

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

```python
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:

```python
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:

```python
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:

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

#### 2. Use Scattergl for Large Scatter Plots

```python
import plotly.graph_objects as go

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

#### 3. Optimize Update Frequency

```python
# 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

```markdown
## My Visualization

Use the controls below to customize the view:

.. exec::docs.viz.controlled_chart
```

```python
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

```python
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

```python
@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:

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

#### 2. Include Titles

Make charts self-explanatory:

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

#### 3. Use Color Wisely

Choose accessible colors:

```python
# 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:

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

#### 5. Handle Empty Data

Always check for empty datasets:

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

---

### Resources

- **Plotly Express**: [plotly.com/python/plotly-express/](https://plotly.com/python/plotly-express/)
- **Plotly Graph Objects**: [plotly.com/python/graph-objects/](https://plotly.com/python/graph-objects/)
- **Dash Core Components**: [dash.plotly.com/dash-core-components/graph](https://dash.plotly.com/dash-core-components/graph)
- **Color Scales**: [plotly.com/python/builtin-colorscales/](https://plotly.com/python/builtin-colorscales/)

---

### Next Steps

- **Interactive Components** - Learn advanced callback patterns
- **AI Integration** - Make your visualizations AI-friendly
- **Getting Started** - Create your first documentation page

---

Happy visualizing! 📊


---

*Source: /examples/visualization*
