303 lines
5.8 KiB
Markdown
303 lines
5.8 KiB
Markdown
# Graph Objects - Low-Level API
|
|
|
|
The `plotly.graph_objects` module provides fine-grained control over figure construction through Python classes representing Plotly components.
|
|
|
|
## Core Classes
|
|
|
|
- **`go.Figure`** - Main figure container
|
|
- **`go.FigureWidget`** - Jupyter-compatible interactive widget
|
|
- **Trace types** - 40+ chart types (Scatter, Bar, Heatmap, etc.)
|
|
- **Layout components** - Axes, annotations, shapes, etc.
|
|
|
|
## Key Advantages
|
|
|
|
1. **Data validation** - Helpful error messages for invalid properties
|
|
2. **Built-in documentation** - Accessible via docstrings
|
|
3. **Flexible syntax** - Dictionary or attribute access
|
|
4. **Convenience methods** - `.add_trace()`, `.update_layout()`, etc.
|
|
5. **Magic underscore notation** - Compact nested property access
|
|
6. **Integrated I/O** - `.show()`, `.write_html()`, `.write_image()`
|
|
|
|
## Basic Figure Construction
|
|
|
|
### Creating Empty Figure
|
|
|
|
```python
|
|
import plotly.graph_objects as go
|
|
|
|
fig = go.Figure()
|
|
```
|
|
|
|
### Adding Traces
|
|
|
|
```python
|
|
# Method 1: Add traces one at a time
|
|
fig = go.Figure()
|
|
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6], name='Line 1'))
|
|
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 3, 4], name='Line 2'))
|
|
|
|
# Method 2: Pass data to constructor
|
|
fig = go.Figure(data=[
|
|
go.Scatter(x=[1, 2, 3], y=[4, 5, 6], name='Line 1'),
|
|
go.Scatter(x=[1, 2, 3], y=[2, 3, 4], name='Line 2')
|
|
])
|
|
```
|
|
|
|
## Common Trace Types
|
|
|
|
### Scatter (Lines and Markers)
|
|
|
|
```python
|
|
fig.add_trace(go.Scatter(
|
|
x=[1, 2, 3, 4],
|
|
y=[10, 11, 12, 13],
|
|
mode='lines+markers', # 'lines', 'markers', 'lines+markers', 'text'
|
|
name='Trace 1',
|
|
line=dict(color='red', width=2, dash='dash'),
|
|
marker=dict(size=10, color='blue', symbol='circle')
|
|
))
|
|
```
|
|
|
|
### Bar
|
|
|
|
```python
|
|
fig.add_trace(go.Bar(
|
|
x=['A', 'B', 'C'],
|
|
y=[1, 3, 2],
|
|
name='Bar Chart',
|
|
marker=dict(color='lightblue'),
|
|
text=[1, 3, 2],
|
|
textposition='auto'
|
|
))
|
|
```
|
|
|
|
### Heatmap
|
|
|
|
```python
|
|
fig.add_trace(go.Heatmap(
|
|
z=[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
|
|
x=['A', 'B', 'C'],
|
|
y=['X', 'Y', 'Z'],
|
|
colorscale='Viridis'
|
|
))
|
|
```
|
|
|
|
### 3D Scatter
|
|
|
|
```python
|
|
fig.add_trace(go.Scatter3d(
|
|
x=[1, 2, 3],
|
|
y=[4, 5, 6],
|
|
z=[7, 8, 9],
|
|
mode='markers',
|
|
marker=dict(size=5, color='red')
|
|
))
|
|
```
|
|
|
|
## Layout Configuration
|
|
|
|
### Update Layout
|
|
|
|
```python
|
|
fig.update_layout(
|
|
title='Figure Title',
|
|
title_font_size=20,
|
|
xaxis_title='X Axis',
|
|
yaxis_title='Y Axis',
|
|
width=800,
|
|
height=600,
|
|
template='plotly_white',
|
|
showlegend=True,
|
|
hovermode='closest' # 'x', 'y', 'closest', 'x unified', False
|
|
)
|
|
```
|
|
|
|
### Magic Underscore Notation
|
|
|
|
Compact way to set nested properties:
|
|
|
|
```python
|
|
# Instead of:
|
|
fig.update_layout(title=dict(text='Title', font=dict(size=20)))
|
|
|
|
# Use underscores:
|
|
fig.update_layout(
|
|
title_text='Title',
|
|
title_font_size=20
|
|
)
|
|
```
|
|
|
|
### Axis Configuration
|
|
|
|
```python
|
|
fig.update_xaxes(
|
|
title='X Axis',
|
|
range=[0, 10],
|
|
showgrid=True,
|
|
gridwidth=1,
|
|
gridcolor='lightgray',
|
|
type='log', # 'linear', 'log', 'date', 'category'
|
|
tickformat='.2f',
|
|
dtick=1 # Tick spacing
|
|
)
|
|
|
|
fig.update_yaxes(
|
|
title='Y Axis',
|
|
zeroline=True,
|
|
zerolinewidth=2,
|
|
zerolinecolor='black'
|
|
)
|
|
```
|
|
|
|
## Updating Traces
|
|
|
|
```python
|
|
# Update all traces
|
|
fig.update_traces(
|
|
marker=dict(size=10, opacity=0.7)
|
|
)
|
|
|
|
# Update specific trace
|
|
fig.update_traces(
|
|
marker=dict(color='red'),
|
|
selector=dict(name='Line 1')
|
|
)
|
|
|
|
# Update by position
|
|
fig.data[0].marker.size = 15
|
|
```
|
|
|
|
## Adding Annotations
|
|
|
|
```python
|
|
fig.add_annotation(
|
|
x=2, y=5,
|
|
text='Important Point',
|
|
showarrow=True,
|
|
arrowhead=2,
|
|
arrowsize=1,
|
|
arrowwidth=2,
|
|
arrowcolor='red',
|
|
ax=40, # Arrow x offset
|
|
ay=-40 # Arrow y offset
|
|
)
|
|
```
|
|
|
|
## Adding Shapes
|
|
|
|
```python
|
|
# Rectangle
|
|
fig.add_shape(
|
|
type='rect',
|
|
x0=1, y0=2, x1=3, y1=4,
|
|
line=dict(color='red', width=2),
|
|
fillcolor='lightblue',
|
|
opacity=0.3
|
|
)
|
|
|
|
# Line
|
|
fig.add_shape(
|
|
type='line',
|
|
x0=0, y0=0, x1=5, y1=5,
|
|
line=dict(color='green', width=2, dash='dash')
|
|
)
|
|
|
|
# Convenience methods for horizontal/vertical lines
|
|
fig.add_hline(y=5, line_dash='dash', line_color='red')
|
|
fig.add_vline(x=3, line_dash='dot', line_color='blue')
|
|
```
|
|
|
|
## Figure Structure
|
|
|
|
Figures follow a tree hierarchy:
|
|
|
|
```python
|
|
fig = go.Figure(data=[trace1, trace2], layout=go.Layout(...))
|
|
|
|
# Access via dictionary syntax
|
|
fig['layout']['title'] = 'New Title'
|
|
fig['data'][0]['marker']['color'] = 'red'
|
|
|
|
# Or attribute syntax
|
|
fig.layout.title = 'New Title'
|
|
fig.data[0].marker.color = 'red'
|
|
```
|
|
|
|
## Complex Chart Types
|
|
|
|
### Candlestick
|
|
|
|
```python
|
|
fig.add_trace(go.Candlestick(
|
|
x=df['date'],
|
|
open=df['open'],
|
|
high=df['high'],
|
|
low=df['low'],
|
|
close=df['close'],
|
|
name='Stock Price'
|
|
))
|
|
```
|
|
|
|
### Sankey Diagram
|
|
|
|
```python
|
|
fig = go.Figure(data=[go.Sankey(
|
|
node=dict(
|
|
label=['A', 'B', 'C', 'D'],
|
|
color='blue'
|
|
),
|
|
link=dict(
|
|
source=[0, 1, 0, 2],
|
|
target=[2, 3, 3, 3],
|
|
value=[8, 4, 2, 8]
|
|
)
|
|
)])
|
|
```
|
|
|
|
### Surface (3D)
|
|
|
|
```python
|
|
fig = go.Figure(data=[go.Surface(
|
|
z=z_data, # 2D array
|
|
x=x_data,
|
|
y=y_data,
|
|
colorscale='Viridis'
|
|
)])
|
|
```
|
|
|
|
## Working with DataFrames
|
|
|
|
Build traces from pandas DataFrames:
|
|
|
|
```python
|
|
import pandas as pd
|
|
|
|
df = pd.DataFrame({
|
|
'x': [1, 2, 3, 4],
|
|
'y': [10, 11, 12, 13]
|
|
})
|
|
|
|
fig = go.Figure()
|
|
for group_name, group_df in df.groupby('category'):
|
|
fig.add_trace(go.Scatter(
|
|
x=group_df['x'],
|
|
y=group_df['y'],
|
|
name=group_name,
|
|
mode='lines+markers'
|
|
))
|
|
```
|
|
|
|
## When to Use Graph Objects
|
|
|
|
Use graph_objects when:
|
|
- Creating chart types not available in Plotly Express
|
|
- Building complex multi-trace figures from scratch
|
|
- Need precise control over individual components
|
|
- Creating specialized visualizations (3D mesh, isosurface, custom shapes)
|
|
- Building subplots with mixed chart types
|
|
|
|
Use Plotly Express when:
|
|
- Creating standard charts quickly
|
|
- Working with tidy DataFrame data
|
|
- Want automatic styling and legends
|