diff --git a/plotly/03_basic_charts.py b/plotly/03_basic_charts.py
new file mode 100644
index 0000000..24f6972
--- /dev/null
+++ b/plotly/03_basic_charts.py
@@ -0,0 +1,673 @@
+# /// script
+# requires-python = ">=3.11"
+# dependencies = [
+# "marimo",
+# "numpy==2.3.1",
+# "pyarrow==20.0.0",
+# "pandas==2.3.0",
+# "plotly==6.1.2",
+# ]
+# ///
+
+import marimo
+
+__generated_with = "0.14.7"
+app = marimo.App(width="medium", app_title="Plotly Basic Charts")
+
+
+@app.cell(hide_code=True)
+def _():
+ import marimo as mo
+ import numpy as np
+ import pandas as pd
+ import plotly.express as px
+ import plotly.graph_objects as go
+ import pyarrow
+ return go, mo, np, pd, px
+
+
+@app.cell(hide_code=True)
+def _(mo, np, pd):
+ np.random.seed(42)
+ data = (np.random.rand(100, 10)) * 10
+ df = pd.DataFrame(data, columns=[f"Col-{i + 1}" for i in range(10)])
+
+ for col in df.columns:
+ if pd.api.types.is_numeric_dtype(df[col]):
+ df[col] = df[col].round(3)
+
+ dates = pd.date_range(start="2022-01-01", periods=len(df), freq="D")
+ df_time = pd.DataFrame(
+ {
+ "Date": dates,
+ "Value-1": np.random.randn(100).cumsum() + 10,
+ "Value-2": np.random.randn(100).cumsum() + 20,
+ }
+ )
+
+ mo.ui.tabs(
+ {
+ "Regular DataFrame": df,
+ "Time Series DataFrame": df_time,
+ }
+ )
+ return df, df_time
+
+
+@app.cell(hide_code=True)
+def _(df, go, mo):
+ # Create sliders for basic line chart customization
+ line_width_slider = mo.ui.slider(1, 10, step=1, value=2, label="Line Width")
+ marker_size_slider = mo.ui.slider(2, 15, step=1, value=6, label="Marker Size")
+
+
+ # Simple Line Plot
+ def basic_line_plot():
+ fig = go.Figure()
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-1"],
+ mode="lines",
+ name="Line",
+ line=dict(width=line_width_slider.value),
+ )
+ )
+ fig.update_layout(title="Basic Line Plot")
+ return fig
+
+
+ # Multi-Line Plot
+ def multi_line_plot():
+ fig = go.Figure()
+ for i, col in enumerate(["Col-1", "Col-2", "Col-3"]):
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df[col],
+ mode="lines",
+ name=f"Series {i + 1}",
+ line=dict(width=line_width_slider.value),
+ )
+ )
+ fig.update_layout(title="Multi-Line Plot")
+ return fig
+
+
+ # Line and Scatter Plot
+ def line_scatter_plot():
+ fig = go.Figure()
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-1"],
+ mode="lines",
+ name="Line",
+ line=dict(width=line_width_slider.value),
+ )
+ )
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-2"],
+ mode="markers",
+ name="Markers",
+ marker=dict(size=marker_size_slider.value),
+ )
+ )
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-3"],
+ mode="lines+markers",
+ name="Line + Markers",
+ line=dict(width=line_width_slider.value),
+ marker=dict(size=marker_size_slider.value),
+ )
+ )
+ fig.update_layout(title="Line and Scatter Plot")
+ return fig
+ return (
+ basic_line_plot,
+ line_scatter_plot,
+ line_width_slider,
+ marker_size_slider,
+ multi_line_plot,
+ )
+
+
+@app.cell(hide_code=True)
+def _(
+ basic_line_plot,
+ line_scatter_plot,
+ line_width_slider,
+ marker_size_slider,
+ mo,
+ multi_line_plot,
+):
+ line_charts = mo.ui.tabs(
+ {
+ "Line Plot": mo.ui.plotly(basic_line_plot()),
+ "Multi-Line Plot": mo.ui.plotly(multi_line_plot()),
+ "Line and Scatter Plot": mo.ui.plotly(line_scatter_plot()),
+ }
+ )
+ basic_line_charts = mo.vstack(
+ [
+ mo.md("Adjust the parameters below to customize the charts:"),
+ mo.hstack(
+ [line_width_slider, marker_size_slider],
+ align="center",
+ justify="start",
+ ),
+ line_charts,
+ ],
+ gap=2,
+ )
+ return (basic_line_charts,)
+
+
+@app.cell(hide_code=True)
+def _(mo):
+ color_selector = mo.ui.dropdown(
+ options={
+ "firebrick": "Red",
+ "royalblue": "Blue",
+ "green": "Green",
+ "purple": "Purple",
+ "orange": "Orange",
+ "black": "Black",
+ },
+ value="royalblue",
+ label="Primary Line color",
+ )
+
+ dash_style = mo.ui.dropdown(
+ options={
+ "solid": "Solid",
+ "dash": "Dashed",
+ "dot": "Dotted",
+ "dashdot": "Dash-Dot",
+ },
+ value="solid",
+ label="Line Style",
+ )
+
+ marker_size = mo.ui.slider(2, 20, step=2, value=8, label="Marker Size")
+ return color_selector, dash_style, marker_size
+
+
+@app.cell(hide_code=True)
+def _(color_selector, dash_style, df, go, line_width_slider, marker_size, mo):
+ # Function to create styled line chart with live updates
+ def create_styled_line():
+ fig = go.Figure()
+
+ # Add main styled line
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-1"],
+ mode="lines+markers",
+ name="Primary Line",
+ line=dict(
+ color=color_selector.value,
+ width=line_width_slider.value,
+ dash=dash_style.value,
+ ),
+ marker=dict(size=marker_size.value, line=dict(width=2)),
+ )
+ )
+
+ # Add reference line
+ fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-2"],
+ mode="lines",
+ name="Reference Line",
+ line=dict(color="gray", width=1, dash="dot"),
+ opacity=0.7,
+ )
+ )
+
+ fig.update_layout(
+ title="Interactive Styled Line Chart",
+ xaxis_title="X Axis",
+ yaxis_title="Y Axis",
+ legend=dict(
+ orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1
+ ),
+ )
+ return fig
+
+
+ # Combine controls and chart
+ styled_line_ui = mo.hstack(
+ [
+ mo.hstack(
+ [
+ mo.md("#### Style Controls"),
+ color_selector,
+ line_width_slider,
+ dash_style,
+ marker_size,
+ ],
+ gap=2,
+ justify="center",
+ ),
+ create_styled_line,
+ ],
+ align="center",
+ justify="center",
+ widths=[1, 3],
+ )
+
+
+ # Functions for other styled examples (non-interactive)
+ def line_color_customization():
+ color_custom = go.Figure()
+ color_custom.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-1"],
+ line=dict(color="firebrick", width=2),
+ name="Red Line",
+ )
+ )
+ color_custom.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-2"],
+ line=dict(color="royalblue", width=2),
+ name="Blue Line",
+ )
+ )
+ color_custom.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-3"],
+ line=dict(color="green", width=2),
+ name="Green Line",
+ )
+ )
+ color_custom.update_layout(title="Line color Customization")
+ return color_custom
+
+
+ def line_dash_patterns():
+ dash_patterns = go.Figure()
+ dash_patterns.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-1"], line=dict(dash="solid"), name="Solid"
+ )
+ )
+ dash_patterns.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-2"], line=dict(dash="dash"), name="Dash"
+ )
+ )
+ dash_patterns.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-3"], line=dict(dash="dot"), name="Dot"
+ )
+ )
+ dash_patterns.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-4"],
+ line=dict(dash="dashdot"),
+ name="Dash-Dot",
+ )
+ )
+ dash_patterns.update_layout(title="Line Dash Patterns")
+ return dash_patterns
+
+
+ def annotations_example():
+ annotations = go.Figure()
+ annotations.add_trace(go.Scatter(x=df.index, y=df["Col-1"], name="Data"))
+ annotations.add_annotation(
+ x=50,
+ y=df["Col-1"].iloc[50],
+ text="Maximum Point",
+ showarrow=True,
+ arrowhead=1,
+ )
+ annotations.add_annotation(
+ x=25,
+ y=df["Col-1"].iloc[25],
+ text="Interesting Pattern",
+ showarrow=True,
+ arrowhead=1,
+ )
+ annotations.update_layout(title="Annotations and Text Labels")
+ return annotations
+ return (
+ annotations_example,
+ line_color_customization,
+ line_dash_patterns,
+ styled_line_ui,
+ )
+
+
+@app.cell(hide_code=True)
+def _(
+ annotations_example,
+ line_color_customization,
+ line_dash_patterns,
+ mo,
+ styled_line_ui,
+):
+ # Create tabs for all styled examples
+ styled_examples = mo.ui.tabs(
+ {
+ "Interactive Styling": styled_line_ui,
+ "color Examples": mo.ui.plotly(line_color_customization()),
+ "Line Dash Examples": mo.ui.plotly(line_dash_patterns()),
+ "Annotations Example": mo.ui.plotly(annotations_example()),
+ }
+ )
+
+ styled_line_charts = mo.vstack(
+ [
+ mo.md("### Styled Line Charts"),
+ mo.md("Use the interactive controls or explore preset examples:"),
+ styled_examples,
+ ],
+ gap=2,
+ )
+ return (styled_line_charts,)
+
+
+@app.cell(hide_code=True)
+def _(df_time, go, mo, px):
+ # Time Series Line Charts
+
+ # Date and Time on X-axis
+ time_series = px.line(
+ df_time, x="Date", y="Value-1", title="Time Series with Date on X-axis"
+ )
+
+ # Time interval analysis - resampled data
+ df_monthly = df_time.set_index("Date").resample("ME").mean().reset_index()
+ time_interval = px.line(
+ df_monthly,
+ x="Date",
+ y="Value-1",
+ title="Monthly Average (Time Interval Analysis)",
+ )
+
+ # Real-time data simulation
+ rt_fig = go.Figure()
+ rt_fig.add_trace(
+ go.Scatter(
+ x=df_time["Date"],
+ y=df_time["Value-1"],
+ name="Real-time Data",
+ mode="lines",
+ )
+ )
+ rt_fig.add_trace(
+ go.Scatter(
+ x=df_time["Date"].iloc[-10:],
+ y=df_time["Value-1"].iloc[-10:],
+ line=dict(color="red", width=4),
+ name="Latest Data",
+ )
+ )
+ rt_fig.update_layout(title="Real-time Data Streaming Simulation")
+
+ time_series_line_charts = mo.ui.tabs(
+ {
+ "Data and Time on the X-axis": mo.ui.plotly(time_series),
+ "Time Interval Analysis": mo.ui.plotly(time_interval),
+ "Real-time Data Streaming": mo.ui.plotly(rt_fig),
+ }
+ )
+ return (time_series_line_charts,)
+
+
+@app.cell(hide_code=True)
+def _(df, go, mo):
+ # Multi-Axis Line Charts
+
+ # Dual Y-axis line plot
+ dual_y = go.Figure()
+ dual_y.add_trace(
+ go.Scatter(x=df.index, y=df["Col-1"], name="Left Y-axis data")
+ )
+ dual_y.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-5"] * 10, name="Right Y-axis data", yaxis="y2"
+ )
+ )
+ dual_y.update_layout(
+ title="Dual Y-axis Line Plot",
+ yaxis=dict(title="Left Y-axis"),
+ yaxis2=dict(title="Right Y-axis", overlaying="y", side="right"),
+ )
+
+ # Multiple Y-axes
+ multi_y = go.Figure()
+ multi_y.add_trace(go.Scatter(x=df.index, y=df["Col-1"], name="Y-axis 1"))
+ multi_y.add_trace(
+ go.Scatter(x=df.index, y=df["Col-2"] * 5, name="Y-axis 2", yaxis="y2")
+ )
+ multi_y.add_trace(
+ go.Scatter(x=df.index, y=df["Col-3"] * 10, name="Y-axis 3", yaxis="y3")
+ )
+
+ multi_y.update_layout(
+ title="Multiple Y-axes Line Plot",
+ yaxis=dict(title="Y-axis 1"),
+ yaxis2=dict(title="Y-axis 2", overlaying="y", side="right"),
+ yaxis3=dict(
+ title="Y-axis 3",
+ overlaying="y",
+ anchor="free",
+ side="right",
+ position=0.85,
+ ),
+ )
+
+ multi_axis_line_charts = mo.ui.tabs(
+ {
+ "Dual Y-axis Line Plot": mo.ui.plotly(dual_y),
+ "Multiple Y-axes": mo.ui.plotly(multi_y),
+ }
+ )
+ return (multi_axis_line_charts,)
+
+
+@app.cell(hide_code=True)
+def _(df, go, mo):
+ # Interactive Line Charts
+
+ # Hover effects
+ hover_fig = go.Figure()
+ hover_fig.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-1"],
+ name="Hover Data",
+ hovertemplate="Index: %{x}
Value: %{y:.2f}",
+ )
+ )
+ hover_fig.update_layout(title="Enhanced Hover Effects")
+
+ # Zoom and Pan
+ zoom_fig = go.Figure()
+ zoom_fig.add_trace(go.Scatter(x=df.index, y=df["Col-1"], name="Data 1"))
+ zoom_fig.add_trace(go.Scatter(x=df.index, y=df["Col-2"], name="Data 2"))
+ zoom_fig.update_layout(
+ title="Zoom and Pan Features",
+ xaxis=dict(rangeslider=dict(visible=True)),
+ updatemenus=[
+ dict(
+ buttons=[
+ dict(
+ label="Reset Zoom",
+ method="relayout",
+ args=[{"xaxis.range": [None, None]}],
+ )
+ ],
+ direction="left",
+ pad={"r": 10, "t": 10},
+ showactive=False,
+ type="buttons",
+ x=0.1,
+ xanchor="left",
+ y=1.1,
+ yanchor="top",
+ )
+ ],
+ )
+
+ # Click events placeholder - in a real app, this would have callbacks
+ click_fig = go.Figure()
+ click_fig.add_trace(
+ go.Scatter(x=df.index, y=df["Col-1"], name="Clickable Data")
+ )
+ click_fig.update_layout(
+ title="Click Events and Interactions (click points to see)",
+ annotations=[
+ dict(
+ x=50,
+ y=df["Col-1"].iloc[50],
+ xref="x",
+ yref="y",
+ text="Click on points!",
+ showarrow=True,
+ arrowhead=2,
+ ax=0,
+ ay=-40,
+ )
+ ],
+ )
+
+ interactive_line_charts = mo.ui.tabs(
+ {
+ "Hover Effects": mo.ui.plotly(hover_fig),
+ "Zoom and Pan": mo.ui.plotly(zoom_fig),
+ "Click Events and Interactions": mo.ui.plotly(click_fig),
+ }
+ )
+ return (interactive_line_charts,)
+
+
+@app.cell(hide_code=True)
+def _(df, go, mo, px):
+ # Comparative Line Charts
+
+ # Stacked line chart (area chart)
+ stacked = px.area(
+ df, x=df.index, y=["Col-1", "Col-2", "Col-3"], title="Stacked Line Chart"
+ )
+
+ # Grouped line chart
+ grouped = go.Figure()
+ # Group 1
+ grouped.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-1"],
+ name="Group 1 - Series 1",
+ line=dict(color="blue"),
+ )
+ )
+ grouped.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-2"],
+ name="Group 1 - Series 2",
+ line=dict(color="lightblue"),
+ )
+ )
+
+ # Group 2
+ grouped.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-5"],
+ name="Group 2 - Series 1",
+ line=dict(color="red"),
+ )
+ )
+ grouped.add_trace(
+ go.Scatter(
+ x=df.index,
+ y=df["Col-6"],
+ name="Group 2 - Series 2",
+ line=dict(color="lightcoral"),
+ )
+ )
+ grouped.update_layout(title="Grouped Line Chart")
+
+ # Overlapping line chart
+ overlap = go.Figure()
+ overlap.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-1"], name="Series 1", line=dict(color="blue")
+ )
+ )
+ overlap.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-2"], name="Series 2", line=dict(color="red")
+ )
+ )
+ overlap.add_trace(
+ go.Scatter(
+ x=df.index, y=df["Col-3"], name="Series 3", line=dict(color="green")
+ )
+ )
+ overlap.update_layout(title="Overlapping Line Chart")
+
+ comparative_line_charts = mo.ui.tabs(
+ {
+ "Stacked Line Charts": mo.ui.plotly(stacked),
+ "Grouped Line Charts": mo.ui.plotly(grouped),
+ "Overlapping Line Charts": mo.ui.plotly(overlap),
+ }
+ )
+ return (comparative_line_charts,)
+
+
+@app.cell(hide_code=True)
+def _(
+ basic_line_charts,
+ comparative_line_charts,
+ interactive_line_charts,
+ mo,
+ multi_axis_line_charts,
+ styled_line_charts,
+ time_series_line_charts,
+):
+ main_categories = mo.ui.tabs(
+ {
+ "Basic Line Charts": basic_line_charts,
+ "Styled Line Charts": styled_line_charts,
+ "Time Series Line Charts": time_series_line_charts,
+ "Multi-Axis Line Charts": multi_axis_line_charts,
+ "Interactive Line Charts": interactive_line_charts,
+ "Comparative Line Charts": comparative_line_charts,
+ }
+ )
+
+ mo.vstack(
+ [
+ mo.md("""
+ # Basic Line Charts
+
+ This app demonstrates various categories of line charts using Plotly.
+ Select a category below to explore different line chart types.
+ """),
+ main_categories,
+ ],
+ gap=2,
+ )
+ return
+
+
+if __name__ == "__main__":
+ app.run()