Skip to content

Commit 075fc51

Browse files
feat(seaborn): implement venn-basic (#2454)
## Implementation: `venn-basic` - seaborn Implements the **seaborn** version of `venn-basic`. **File:** `plots/venn-basic/implementations/seaborn.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20584328752)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 23ba53e commit 075fc51

2 files changed

Lines changed: 160 additions & 0 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
""" pyplots.ai
2+
venn-basic: Venn Diagram
3+
Library: seaborn 0.13.2 | Python 3.13.11
4+
Quality: 90/100 | Created: 2025-12-29
5+
"""
6+
7+
import matplotlib.patches as mpatches
8+
import matplotlib.pyplot as plt
9+
import numpy as np
10+
import seaborn as sns
11+
12+
13+
np.random.seed(42)
14+
15+
# Data - Survey results on programming language preferences
16+
# Set A: Python users, Set B: JavaScript users, Set C: SQL users
17+
set_labels = ["Python", "JavaScript", "SQL"]
18+
set_sizes = [100, 80, 60] # Total in each group
19+
# Overlaps: AB=30, AC=20, BC=25, ABC=10
20+
intersections = {"AB": 30, "AC": 20, "BC": 25, "ABC": 10}
21+
22+
# Calculate exclusive counts for each region
23+
only_a = set_sizes[0] - intersections["AB"] - intersections["AC"] + intersections["ABC"]
24+
only_b = set_sizes[1] - intersections["AB"] - intersections["BC"] + intersections["ABC"]
25+
only_c = set_sizes[2] - intersections["AC"] - intersections["BC"] + intersections["ABC"]
26+
ab_only = intersections["AB"] - intersections["ABC"]
27+
ac_only = intersections["AC"] - intersections["ABC"]
28+
bc_only = intersections["BC"] - intersections["ABC"]
29+
abc = intersections["ABC"]
30+
31+
# Total unique respondents using inclusion-exclusion principle
32+
total_respondents = sum(set_sizes) - sum(intersections.values()) + intersections["ABC"]
33+
34+
# Set seaborn style with custom context
35+
sns.set_theme(style="white", context="talk", font_scale=1.2)
36+
37+
# Create figure (square for symmetric diagram)
38+
fig, ax = plt.subplots(figsize=(12, 12))
39+
40+
# Get colors from seaborn palette - using colorblind-safe Set2
41+
palette = sns.color_palette("Set2", n_colors=3)
42+
colors = list(palette)
43+
44+
# Circle positions (equilateral triangle arrangement)
45+
r = 1.5 # Circle radius
46+
center_offset = 0.9 # Distance from center
47+
48+
# Calculate centers for three overlapping circles
49+
centers = [
50+
(0, center_offset), # Top (A - Python)
51+
(-center_offset * np.cos(np.pi / 6), -center_offset * np.sin(np.pi / 6)), # Bottom-left (B - JavaScript)
52+
(center_offset * np.cos(np.pi / 6), -center_offset * np.sin(np.pi / 6)), # Bottom-right (C - SQL)
53+
]
54+
55+
# Draw circles with transparency
56+
circles = []
57+
for center, color, label in zip(centers, colors, set_labels, strict=True):
58+
circle = mpatches.Circle(center, r, alpha=0.4, facecolor=color, edgecolor=color, linewidth=3, label=label)
59+
ax.add_patch(circle)
60+
circles.append(circle)
61+
62+
# Position labels outside circles
63+
label_offset = 2.3
64+
label_positions = [
65+
(0, label_offset), # Top
66+
(-label_offset * np.cos(np.pi / 6) - 0.3, -label_offset * np.sin(np.pi / 6) - 0.3), # Bottom-left
67+
(label_offset * np.cos(np.pi / 6) + 0.3, -label_offset * np.sin(np.pi / 6) - 0.3), # Bottom-right
68+
]
69+
70+
for pos, label, size in zip(label_positions, set_labels, set_sizes, strict=True):
71+
ax.text(
72+
pos[0],
73+
pos[1],
74+
f"{label}\n(n={size})",
75+
ha="center",
76+
va="center",
77+
fontsize=22,
78+
fontweight="bold",
79+
color="#333333",
80+
)
81+
82+
# Add counts to each region
83+
# Region positions (approximate centers of each region)
84+
region_positions = {
85+
"A": (0, 1.3), # Only Python
86+
"B": (-1.2, -0.8), # Only JavaScript
87+
"C": (1.2, -0.8), # Only SQL
88+
"AB": (-0.55, 0.3), # Python & JavaScript
89+
"AC": (0.55, 0.3), # Python & SQL
90+
"BC": (0, -0.7), # JavaScript & SQL
91+
"ABC": (0, 0), # All three
92+
}
93+
94+
region_counts = {"A": only_a, "B": only_b, "C": only_c, "AB": ab_only, "AC": ac_only, "BC": bc_only, "ABC": abc}
95+
96+
for region, pos in region_positions.items():
97+
count = region_counts[region]
98+
pct = count / total_respondents * 100
99+
ax.text(
100+
pos[0],
101+
pos[1],
102+
f"{count}\n({pct:.0f}%)",
103+
ha="center",
104+
va="center",
105+
fontsize=20,
106+
fontweight="bold",
107+
color="#333333",
108+
bbox={"boxstyle": "round,pad=0.3", "facecolor": "white", "edgecolor": "none", "alpha": 0.8},
109+
)
110+
111+
# Set axis properties - tighter bounds for better canvas utilization
112+
ax.set_xlim(-3.0, 3.0)
113+
ax.set_ylim(-2.8, 3.0)
114+
ax.set_aspect("equal")
115+
ax.axis("off")
116+
117+
# Title
118+
ax.set_title("venn-basic · seaborn · pyplots.ai", fontsize=24, fontweight="bold", pad=20)
119+
120+
# Add subtitle annotation explaining data context (using computed total)
121+
fig.text(
122+
0.5,
123+
0.02,
124+
f"Developer Survey 2024: Language preferences among {total_respondents} respondents",
125+
ha="center",
126+
va="bottom",
127+
fontsize=14,
128+
style="italic",
129+
color="#666666",
130+
)
131+
132+
plt.tight_layout()
133+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library: seaborn
2+
specification_id: venn-basic
3+
created: '2025-12-29T22:47:29Z'
4+
updated: '2025-12-29T23:14:11Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20584328752
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 0.13.2
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/venn-basic/seaborn/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/venn-basic/seaborn/plot_thumb.png
12+
preview_html: null
13+
quality_score: 90
14+
review:
15+
strengths:
16+
- Excellent text legibility with white background boxes ensuring readability against
17+
all overlay colors
18+
- Mathematically correct implementation using inclusion-exclusion principle for
19+
region counts
20+
- Good use of seaborn Set2 colorblind-safe palette and styling context
21+
- Clear labeling with both counts and percentages in each region
22+
- Clean code structure following KISS principles
23+
weaknesses:
24+
- Minor asymmetry in external label positioning (manual -0.3 offsets for bottom
25+
labels)
26+
- Limited use of seaborn-specific features (seaborn has no native Venn support,
27+
so matplotlib patches are required)

0 commit comments

Comments
 (0)