Polar Line Plot — Plotly

A line plot rendered in polar coordinates, where data points are connected with lines around a circular axis. The angle (theta) typically represents a cyclical variable while the radius shows magnitude.

Polar Line Plot rendered with Plotly

Python source (Plotly)

""" anyplot.ai
polar-line: Polar Line Plot
Library: plotly 6.7.0 | Python 3.13.13
Quality: 93/100 | Updated: 2026-05-12
"""

import os

import numpy as np
import plotly.graph_objects as go


# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)"

# Okabe-Ito palette
IMPRINT = ["#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD"]

# Data - Average hourly temperature pattern (two seasons)
np.random.seed(42)
hours = np.arange(0, 360, 15)  # 24 hours mapped to 360 degrees (15 deg = 1 hour)
hour_labels = [f"{h}:00" for h in range(24)]

# Summer pattern: warmer during day (12-18h), cooler at night
summer_base = 22 + 8 * np.sin(np.radians(hours - 90))  # Peak at 180 deg (noon)
summer_temp = summer_base + np.random.normal(0, 0.5, len(hours))

# Winter pattern: colder overall, less variation
winter_base = 5 + 5 * np.sin(np.radians(hours - 90))  # Peak at 180 deg (noon)
winter_temp = winter_base + np.random.normal(0, 0.3, len(hours))

# Close the loop by appending the first value
hours_closed = np.append(hours, hours[0])
summer_closed = np.append(summer_temp, summer_temp[0])
winter_closed = np.append(winter_temp, winter_temp[0])

# Create figure
fig = go.Figure()

# Summer line
fig.add_trace(
    go.Scatterpolar(
        r=summer_closed,
        theta=hours_closed,
        mode="lines+markers",
        name="Summer",
        line=dict(color=IMPRINT[0], width=4),
        marker=dict(size=10, color=IMPRINT[0]),
        hovertemplate="Hour: %{theta}°<br>Temp: %{r:.1f}°C<extra>Summer</extra>",
    )
)

# Winter line
fig.add_trace(
    go.Scatterpolar(
        r=winter_closed,
        theta=hours_closed,
        mode="lines+markers",
        name="Winter",
        line=dict(color=IMPRINT[1], width=4),
        marker=dict(size=10, color=IMPRINT[1]),
        hovertemplate="Hour: %{theta}°<br>Temp: %{r:.1f}°C<extra>Winter</extra>",
    )
)

# Layout
fig.update_layout(
    title=dict(
        text="Hourly Temperature Pattern · polar-line · plotly · anyplot.ai",
        font=dict(size=28, color=INK),
        x=0.5,
        xanchor="center",
    ),
    polar=dict(
        radialaxis=dict(
            visible=True,
            range=[0, 35],
            tickfont=dict(size=18, color=INK_SOFT),
            title=dict(text="Temperature (°C)", font=dict(size=22, color=INK)),
            gridcolor=GRID,
        ),
        angularaxis=dict(
            tickfont=dict(size=16, color=INK_SOFT),
            direction="clockwise",
            rotation=90,
            tickmode="array",
            tickvals=list(range(0, 360, 15)),
            ticktext=hour_labels,
            gridcolor=GRID,
        ),
        bgcolor=PAGE_BG,
    ),
    paper_bgcolor=PAGE_BG,
    plot_bgcolor=PAGE_BG,
    legend=dict(
        font=dict(size=18, color=INK_SOFT), x=1.05, y=0.5, bgcolor=ELEVATED_BG, bordercolor=INK_SOFT, borderwidth=1
    ),
    margin=dict(l=80, r=150, t=100, b=80),
)

# Save outputs
script_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(script_dir)
fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")

Part of Polar Line Plot on anyplot.ai.

Other implementations