Install
openclaw skills install plotly-vizInteractive data visualization using plotly.py. Create publication-quality interactive charts, dashboards, and animated visualizations. Use when creating interactive charts/graphs/plots from data, building dashboards, creating animated visualizations, or when hover/zoom/pan interactivity is needed. Supports HTML (interactive) and PNG/SVG/PDF (static) export. Specialized for plotly.py only - for matplotlib/seaborn use python-dataviz.
openclaw skills install plotly-vizCreate interactive, publication-quality visualizations with plotly.py - Python's leading interactive graphing library.
import plotly.express as px
# Simple scatter plot
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species")
fig.show()
# Export
fig.write_html("chart.html") # Interactive
fig.write_image("chart.png", width=800, height=600, scale=2) # Static (requires kaleido)
| Data Type | Chart | Function |
|---|---|---|
| Distribution | Histogram | px.histogram() |
| Distribution | Box plot | px.box() |
| Distribution | Violin | px.violin() |
| Comparison | Bar | px.bar() |
| Comparison | Grouped bar | px.bar(barmode='group') |
| Relationship | Scatter | px.scatter() |
| Relationship | Line | px.line() |
| Relationship | Heatmap | px.density_heatmap() |
| Part-to-whole | Pie | px.pie() |
| Part-to-whole | Treemap | px.treemap() |
| Part-to-whole | Sunburst | px.sunburst() |
| Hierarchical | Treemap | px.treemap(path=[...]) |
| Hierarchical | Sunburst | px.sunburst(path=[...]) |
| Geographic | Choropleth | px.choropleth() |
| Geographic | Scatter map | px.scatter_geo() |
| 3D | 3D Scatter | px.scatter_3d() |
| 3D | 3D Line | px.line_3d() |
| Time Series | Line + range slider | fig.update_layout(xaxis_rangeslider_visible=True) |
| Animation | Animated scatter | px.scatter(animation_frame=...) |
Choose API level:
plotly.express (px) → Quick, declarative, ~30 chart typesplotly.graph_objects (go) → Fine-grained control, all featuresCreate figure:
# Express (recommended for most cases)
fig = px.scatter(df, x="col1", y="col2", color="category")
# Graph Objects (for complex customization)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='Trace'))
Customize:
fig.update_layout(title="Title", xaxis_title="X", yaxis_title="Y")
fig.update_traces(marker=dict(size=10, opacity=0.8))
Export:
fig.write_html("interactive.html")
fig.write_image("static.png", width=800, height=600, scale=2)
Built-in templates for consistent styling:
# Available templates: plotly, plotly_white, plotly_dark, ggplot2, seaborn, simple_white, presentation
fig = px.scatter(df, x="x", y="y", template="plotly_white")
# Set default template
import plotly.io as pio
pio.templates.default = "plotly_white"
Template guide:
plotly_white → Clean, white background (default for publications)plotly_dark → Dark theme, good for dashboardsggplot2 → R ggplot2 styleseaborn → Seaborn-inspired stylingpresentation → Larger fonts for presentationsimport plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y1, name='Series 1'))
fig.add_trace(go.Bar(x=x, y=y2, name='Series 2'))
fig.show()
from plotly.subplots import make_subplots
fig = make_subplots(rows=2, cols=2, subplot_titles=("Plot 1", "Plot 2", "Plot 3", "Plot 4"))
fig.add_trace(go.Scatter(x=x1, y=y1), row=1, col=1)
fig.add_trace(go.Bar(x=x2, y=y2), row=1, col=2)
fig.add_trace(go.Histogram(x=x3), row=2, col=1)
fig.add_trace(go.Pie(labels=labels, values=values), row=2, col=2)
fig.update_layout(height=600, title_text="Multi-Panel Dashboard")
fig.show()
# Animated scatter plot
df = px.data.gapminder()
fig = px.scatter(
df, x="gdpPercap", y="lifeExp",
animation_frame="year", animation_group="country",
size="pop", color="continent", hover_name="country",
log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90]
)
fig.show()
Animation best practices:
range_x and range_y to prevent axis jumpinganimation_group to link points across framesfig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 500# Custom hover template
fig.update_traces(
hovertemplate='<b>%{text}</b><br>X: %{x}<br>Y: %{y}<extra></extra>',
text=df['names']
)
# Unified hover (show all traces at x position)
fig.update_layout(hovermode='x unified')
# Compare hover (show closest point from each trace)
fig.update_layout(hovermode='x')
import pandas as pd
import plotly.express as px
df = pd.read_csv("data.csv")
fig = px.scatter(df, x="col1", y="col2", color="category", size="value")
fig.write_html("output.html")
data = {'Category': ['A', 'B', 'C'], 'Value': [10, 20, 15]}
fig = px.bar(data, x='Category', y='Value')
df = pd.read_csv("timeseries.csv", parse_dates=['date'])
fig = px.line(df, x='date', y='value')
fig.update_layout(xaxis_rangeslider_visible=True)
# Histogram with marginal plots
fig = px.histogram(df, x="value", marginal="box", nbins=30)
# Box with points
fig = px.box(df, x="category", y="value", points="all")
# Violin with box inside
fig = px.violin(df, y="value", x="category", box=True, points="all")
# Interactive HTML (standalone)
fig.write_html("chart.html", include_plotlyjs=True)
# Interactive HTML (CDN, smaller file)
fig.write_html("chart.html", include_plotlyjs='cdn')
# Static images (requires kaleido: pip install kaleido)
fig.write_image("chart.png", width=800, height=600, scale=2)
fig.write_image("chart.svg")
fig.write_image("chart.pdf")
# Get HTML string for embedding
html_str = fig.to_html(include_plotlyjs=False, full_html=False)
fig.add_annotation(x=2, y=10, text="Peak", showarrow=True, arrowhead=1)
fig.add_hline(y=5, line_dash="dash", line_color="red")
fig.add_vrect(x0=1, x1=3, fillcolor="gray", opacity=0.2)
from plotly.subplots import make_subplots
fig = make_subplots(specs=[[{"secondary_y": True}]])
fig.add_trace(go.Scatter(x=x, y=y1, name="Primary"), secondary_y=False)
fig.add_trace(go.Scatter(x=x, y=y2, name="Secondary"), secondary_y=True)
# Sequential
fig = px.scatter(df, x="x", y="y", color="value", color_continuous_scale="Viridis")
# Diverging
fig = px.scatter(df, x="x", y="y", color="value", color_continuous_scale="RdBu_r")
# Custom discrete
fig = px.bar(df, x="cat", y="val", color="cat",
color_discrete_map={"A": "red", "B": "blue", "C": "green"})
"kaleido not found" (for static export)
pip install kaleido
Blank figure / No output
fig.show() or export after adding tracesfig.write_html() instead of fig.show()Large file sizes
include_plotlyjs='cdn' for smaller HTML filesSlow rendering with many points
px.scatter with render_mode='webgl' for 100K+ pointsscripts/ for ready-to-use chart templatesreferences/templates.md for template customizationreferences/colors.md for color scales and palettesreferences/advanced.md for specialized visualizationspip install plotly pandas kaleido
Dependencies:
plotly - Core librarypandas - Data manipulation (recommended)kaleido - Static image export (optional)