Skip to content

Commit 60cb6f4

Browse files
feat(seaborn): implement radar-basic (#5543)
## Implementation: `radar-basic` - python/seaborn Implements the **python/seaborn** version of `radar-basic`. **File:** `plots/radar-basic/implementations/python/seaborn.py` **Parent Issue:** #744 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25121287681)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 20beb7e commit 60cb6f4

2 files changed

Lines changed: 241 additions & 181 deletions

File tree

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,96 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
radar-basic: Basic Radar Chart
3-
Library: seaborn 0.13.2 | Python 3.13.11
4-
Quality: 91/100 | Created: 2025-12-23
3+
Library: seaborn 0.13.2 | Python 3.13.13
4+
Quality: 86/100 | Updated: 2026-04-29
55
"""
66

7+
import os
8+
79
import matplotlib.pyplot as plt
810
import numpy as np
9-
import pandas as pd
1011
import seaborn as sns
1112

1213

14+
# Theme tokens
15+
THEME = os.getenv("ANYPLOT_THEME", "light")
16+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
17+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
18+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
19+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
20+
21+
OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"]
22+
23+
sns.set_theme(
24+
style="ticks",
25+
rc={
26+
"figure.facecolor": PAGE_BG,
27+
"axes.facecolor": PAGE_BG,
28+
"axes.edgecolor": INK_SOFT,
29+
"axes.labelcolor": INK,
30+
"text.color": INK,
31+
"xtick.color": INK_SOFT,
32+
"ytick.color": INK_SOFT,
33+
"grid.color": INK_SOFT,
34+
"grid.alpha": 0.15,
35+
"legend.facecolor": ELEVATED_BG,
36+
"legend.edgecolor": INK_SOFT,
37+
},
38+
)
39+
1340
# Data - Employee performance comparison across competencies
1441
categories = ["Communication", "Technical Skills", "Teamwork", "Leadership", "Problem Solving", "Creativity"]
1542
employee_a_values = [85, 90, 75, 70, 88, 82] # Senior Developer
1643
employee_b_values = [78, 65, 92, 85, 72, 75] # Team Lead
1744

18-
# Setup for radar chart
1945
n_vars = len(categories)
2046
angles = np.linspace(0, 2 * np.pi, n_vars, endpoint=False).tolist()
2147
angles += angles[:1] # Close the polygon
2248

23-
# Close the polygons
2449
employee_a = employee_a_values + employee_a_values[:1]
2550
employee_b = employee_b_values + employee_b_values[:1]
2651

27-
# Create DataFrame for seaborn plotting
28-
df = pd.DataFrame(
29-
{
30-
"Category": categories * 2,
31-
"Score": employee_a_values + employee_b_values,
32-
"Employee": ["Senior Developer"] * n_vars + ["Team Lead"] * n_vars,
33-
"angle": (angles[:-1] * 2),
34-
}
35-
)
36-
37-
# Apply seaborn styling with context for proper scaling
38-
sns.set_theme(style="whitegrid", context="poster", font_scale=1.2)
39-
palette = sns.color_palette("colorblind", 2)
40-
41-
# Create square figure for radar chart (3600x3600 at 300 dpi = 12x12 inches)
42-
fig, ax = plt.subplots(figsize=(12, 12), subplot_kw={"projection": "polar"})
52+
# Plot - square canvas for symmetric radar chart (3600x3600 at 300 dpi)
53+
fig, ax = plt.subplots(figsize=(12, 12), subplot_kw={"projection": "polar"}, facecolor=PAGE_BG)
54+
ax.set_facecolor(PAGE_BG)
4355

44-
# Use seaborn scatterplot for data points on the polar axes
45-
sns.scatterplot(data=df, x="angle", y="Score", hue="Employee", palette=palette, s=400, ax=ax, legend=False, zorder=5)
56+
color_a = OKABE_ITO[0] # #009E73 - Senior Developer (first series)
57+
color_b = OKABE_ITO[1] # #D55E00 - Team Lead
4658

47-
# Draw filled polygons and lines (matplotlib needed for fill and closed polygon)
48-
color_senior = palette[0]
49-
color_lead = palette[1]
59+
ax.fill(angles, employee_a, alpha=0.25, color=color_a)
60+
ax.plot(angles, employee_a, color=color_a, linewidth=3.5, label="Senior Developer")
61+
ax.scatter(angles[:-1], employee_a_values, color=color_a, s=150, zorder=5)
5062

51-
ax.fill(angles, employee_a, alpha=0.25, color=color_senior)
52-
ax.plot(angles, employee_a, color=color_senior, linewidth=4, label="Senior Developer")
63+
ax.fill(angles, employee_b, alpha=0.25, color=color_b)
64+
ax.plot(angles, employee_b, color=color_b, linewidth=3.5, label="Team Lead")
65+
ax.scatter(angles[:-1], employee_b_values, color=color_b, s=150, zorder=5)
5366

54-
ax.fill(angles, employee_b, alpha=0.25, color=color_lead)
55-
ax.plot(angles, employee_b, color=color_lead, linewidth=4, label="Team Lead")
56-
57-
# Configure axes with larger tick labels
67+
# Style axes
5868
ax.set_xticks(angles[:-1])
59-
ax.set_xticklabels(categories, fontsize=22, fontweight="medium")
69+
ax.set_xticklabels(categories, fontsize=20, color=INK, fontweight="medium")
6070
ax.set_ylim(0, 100)
6171
ax.set_yticks([20, 40, 60, 80, 100])
62-
ax.set_yticklabels(["20", "40", "60", "80", "100"], fontsize=18, color="gray")
63-
64-
# Style grid
65-
ax.grid(True, alpha=0.3, linestyle="-", linewidth=1.5)
66-
ax.spines["polar"].set_visible(False)
67-
68-
# Title with proper padding
69-
ax.set_title("radar-basic · seaborn · pyplots.ai", fontsize=28, fontweight="bold", pad=35)
70-
71-
# Legend positioned inside the plot area for better balance
72-
ax.legend(loc="upper right", fontsize=18, framealpha=0.95, edgecolor="lightgray", fancybox=True)
72+
ax.set_yticklabels(["20", "40", "60", "80", "100"], fontsize=16, color=INK_SOFT)
73+
74+
# Grid and spines
75+
grid_alpha = 0.20 if THEME == "light" else 0.25
76+
ax.grid(True, alpha=grid_alpha, linestyle="-", linewidth=1.2, color=INK_SOFT)
77+
ax.spines["polar"].set_color(INK_SOFT)
78+
ax.spines["polar"].set_alpha(0.4)
79+
80+
# Title
81+
ax.set_title("radar-basic · seaborn · anyplot.ai", fontsize=26, fontweight="medium", color=INK, pad=40)
82+
83+
# Legend
84+
legend = ax.legend(
85+
loc="upper right",
86+
bbox_to_anchor=(1.35, 1.15),
87+
fontsize=18,
88+
framealpha=0.95,
89+
facecolor=ELEVATED_BG,
90+
edgecolor=INK_SOFT,
91+
)
92+
for text in legend.get_texts():
93+
text.set_color(INK)
7394

74-
plt.tight_layout()
75-
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
95+
# Save
96+
plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG)

0 commit comments

Comments
 (0)