A radar chart (also known as spider or web chart) displays multivariate data on axes starting from a common center point, with values connected to form a polygon. Each axis represents a different variable, making it ideal for comparing multiple quantitative variables at once or visualizing strengths and weaknesses across categories.

""" anyplot.ai
radar-basic: Basic Radar Chart
Library: pygal 3.1.3 | Python 3.13.14
Quality: 93/100 | Updated: 2026-07-24
"""
import importlib
import os
import sys
# Prevent this file (pygal.py) from shadowing the installed pygal package
_here = os.path.dirname(os.path.abspath(__file__))
sys.path = [p for p in sys.path if os.path.abspath(p) != _here]
pygal = importlib.import_module("pygal")
Style = importlib.import_module("pygal.style").Style
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
INK_FAINT = "rgba(107, 106, 99, 0.35)" if THEME == "light" else "rgba(168, 167, 159, 0.35)"
IMPRINT = ("#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD", "#954477")
# Data: three employees with distinct competency profiles — technical expert,
# collaborative leader, and creative visionary — to highlight trade-offs.
categories = ["Communication", "Technical Skills", "Teamwork", "Problem Solving", "Leadership", "Creativity"]
employee_a = [85, 92, 78, 88, 72, 80] # Technical Expert: peaks at Technical Skills
employee_b = [80, 68, 92, 82, 88, 74] # Team Leader: peaks at Teamwork & Leadership
employee_c = [72, 76, 70, 74, 85, 95] # Creative Visionary: peaks at Creativity & Leadership
# Highest overall average becomes the visual "hero" series — bolder stroke and
# larger dots build a focal point so the viewer immediately spots the top
# all-round performer, while the other two stay legible but recede slightly.
series = [
("Employee A — Technical Expert", employee_a),
("Employee B — Team Leader", employee_b),
("Employee C — Creative Visionary", employee_c),
]
hero_label, _ = max(series, key=lambda s: sum(s[1]) / len(s[1]))
title = "radar-basic · python · pygal · anyplot.ai"
# Style — native-pixel font sizes targeting ~67 source-px title height at the
# canonical 2400x2400 square canvas (see default-style-guide.md "Proportional
# Sizing"); title is well under the 67-char baseline so no length scaling needed.
# Radial gridlines get a two-tier treatment (faint dotted minor rings, slightly
# firmer dashed major rings every 2nd label) instead of pygal's flat default —
# a subtler ring rhythm beyond the mandated style-guide baseline.
custom_style = Style(
font_family='"Liberation Sans", "DejaVu Sans", Arial, sans-serif',
background=PAGE_BG,
plot_background=PAGE_BG,
foreground=INK,
foreground_strong=INK,
foreground_subtle=INK_MUTED,
colors=IMPRINT,
title_font_size=66,
label_font_size=56,
major_label_font_size=44,
legend_font_size=44,
value_font_size=36,
opacity=0.22,
opacity_hover=0.55,
stroke_opacity=0.9,
guide_stroke_color=INK_FAINT,
guide_stroke_dasharray="2,6",
major_guide_stroke_color=INK_MUTED,
major_guide_stroke_dasharray="9,4",
)
# Plot
chart = pygal.Radar(
width=2400,
height=2400,
style=custom_style,
title=title,
show_legend=True,
legend_at_bottom=True,
legend_at_bottom_columns=1,
fill=True,
dots_size=5,
stroke_style={"width": 3, "linecap": "round", "linejoin": "round", "dasharray": "14,6"},
show_y_guides=True,
y_labels_major_every=2,
range=(0, 100),
margin=30,
spacing=16,
)
chart.x_labels = categories
for label, values in series:
is_hero = label == hero_label
# Hero series reads as a bold, solid focal line; supporting series recede
# behind a thinner dashed stroke and smaller dots — a wider gap than a flat
# stroke-width bump alone so the top performer reads at a glance.
chart.add(
label,
values,
dots_size=11 if is_hero else 5,
stroke_style={"width": 7.5, "linecap": "round", "linejoin": "round"}
if is_hero
else {"width": 3, "linecap": "round", "linejoin": "round", "dasharray": "14,6"},
)
# Save
chart.render_to_png(f"plot-{THEME}.png")
with open(f"plot-{THEME}.html", "wb") as f:
f.write(chart.render())
Part of Basic Radar Chart on anyplot.ai.