Skip to content

Commit e98f398

Browse files
feat(seaborn): implement pie-basic
Simplify pie chart implementation following KISS principles: - Remove function-based structure - Use sequential script approach like gallery examples - Apply 16:9 figsize for 4800x2700px output at 300 DPI - Follow PyPlots.ai style guide font sizes - Keep seaborn styling context for consistent aesthetics Note: Seaborn lacks native pie chart support, so this uses matplotlib's pie with seaborn styling.
1 parent 27357ca commit e98f398

1 file changed

Lines changed: 58 additions & 162 deletions

File tree

plots/seaborn/pie/pie-basic/default.py

Lines changed: 58 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -6,179 +6,75 @@
66
matplotlib's pie chart with seaborn's styling context for consistent aesthetics.
77
"""
88

9-
from typing import TYPE_CHECKING
10-
119
import matplotlib.pyplot as plt
1210
import pandas as pd
1311
import seaborn as sns
1412

1513

16-
if TYPE_CHECKING:
17-
from matplotlib.figure import Figure
18-
19-
2014
# PyPlots.ai color palette
2115
PYPLOTS_COLORS = [
22-
"#306998", # Python Blue (Primary)
16+
"#306998", # Python Blue
2317
"#FFD43B", # Python Yellow
2418
"#DC2626", # Signal Red
2519
"#059669", # Teal Green
2620
"#8B5CF6", # Violet
2721
"#F97316", # Orange
2822
]
2923

30-
31-
def create_plot(
32-
data: pd.DataFrame,
33-
category: str,
34-
value: str,
35-
figsize: tuple[float, float] = (10, 8),
36-
title: str | None = None,
37-
colors: list[str] | None = None,
38-
startangle: float = 90,
39-
autopct: str = "%1.1f%%",
40-
explode: list[float] | None = None,
41-
shadow: bool = False,
42-
labels: list[str] | None = None,
43-
legend: bool = True,
44-
legend_loc: str = "best",
45-
**kwargs,
46-
) -> "Figure":
47-
"""
48-
Create a basic pie chart visualizing proportions of categorical data.
49-
50-
A fundamental pie chart where each slice represents a category's share of the
51-
whole, ideal for showing composition and distribution across a small number
52-
of categories.
53-
54-
Note: Seaborn does not have a native pie chart function. This implementation
55-
uses matplotlib's pie chart with seaborn's styling context.
56-
57-
Args:
58-
data: Input DataFrame containing category and value columns
59-
category: Column name for category labels
60-
value: Column name for numeric values (proportions)
61-
figsize: Figure size as (width, height) in inches
62-
title: Plot title (optional)
63-
colors: Custom color palette for slices (uses PyPlots.ai palette if None)
64-
startangle: Starting angle for first slice in degrees from positive x-axis
65-
autopct: Format string for percentage labels
66-
explode: Offset distances for each slice (0-0.1 typical)
67-
shadow: Add shadow effect for 3D appearance
68-
labels: Custom labels (defaults to category names if None)
69-
legend: Whether to display legend
70-
legend_loc: Legend location
71-
**kwargs: Additional parameters passed to ax.pie()
72-
73-
Returns:
74-
Matplotlib Figure object
75-
76-
Raises:
77-
ValueError: If data is empty or contains negative values
78-
KeyError: If required columns not found in data
79-
80-
Example:
81-
>>> data = pd.DataFrame({
82-
... 'category': ['Product A', 'Product B', 'Product C'],
83-
... 'value': [35, 40, 25]
84-
... })
85-
>>> fig = create_plot(data, 'category', 'value', title='Market Share')
86-
"""
87-
# Input validation
88-
if data.empty:
89-
raise ValueError("Data cannot be empty")
90-
91-
for col in [category, value]:
92-
if col not in data.columns:
93-
available = ", ".join(data.columns)
94-
raise KeyError(f"Column '{col}' not found. Available: {available}")
95-
96-
# Extract values and validate
97-
values = data[value].values
98-
categories = data[category].values
99-
100-
if (values < 0).any():
101-
raise ValueError("Pie chart values cannot be negative")
102-
103-
if values.sum() == 0:
104-
raise ValueError("Sum of values cannot be zero")
105-
106-
# Set seaborn style context for consistent aesthetics
107-
sns.set_theme(style="white")
108-
109-
# Create figure with equal aspect ratio to prevent elliptical distortion
110-
fig, ax = plt.subplots(figsize=figsize)
111-
ax.set_aspect("equal")
112-
113-
# Determine colors
114-
if colors is None:
115-
# Extend palette if needed for more categories
116-
n_categories = len(categories)
117-
if n_categories <= len(PYPLOTS_COLORS):
118-
pie_colors = PYPLOTS_COLORS[:n_categories]
119-
else:
120-
# Use seaborn color palette for many categories
121-
pie_colors = sns.color_palette("husl", n_categories)
122-
else:
123-
pie_colors = colors
124-
125-
# Determine labels
126-
pie_labels = labels if labels is not None else categories
127-
128-
# Create pie chart
129-
wedges, texts, autotexts = ax.pie(
130-
values,
131-
labels=pie_labels if not legend else None,
132-
autopct=autopct,
133-
startangle=startangle,
134-
explode=explode,
135-
shadow=shadow,
136-
colors=pie_colors,
137-
wedgeprops={"edgecolor": "white", "linewidth": 1.5},
138-
textprops={"fontsize": 12},
139-
pctdistance=0.75,
140-
**kwargs,
141-
)
142-
143-
# Style percentage labels
144-
for autotext in autotexts:
145-
autotext.set_fontsize(11)
146-
autotext.set_fontweight("bold")
147-
autotext.set_color("white")
148-
149-
# Add legend if requested
150-
if legend:
151-
ax.legend(
152-
wedges,
153-
pie_labels,
154-
title=category,
155-
loc=legend_loc,
156-
bbox_to_anchor=(1, 0, 0.5, 1),
157-
frameon=True,
158-
facecolor="white",
159-
edgecolor="gray",
160-
fontsize=11,
161-
)
162-
163-
# Set title if provided
164-
if title is not None:
165-
ax.set_title(title, fontsize=16, fontweight="semibold", pad=20)
166-
167-
# Layout adjustment
168-
plt.tight_layout()
169-
170-
return fig
171-
172-
173-
if __name__ == "__main__":
174-
# Sample data for testing
175-
sample_data = pd.DataFrame(
176-
{"category": ["Product A", "Product B", "Product C", "Product D", "Other"], "value": [35, 25, 20, 15, 5]}
177-
)
178-
179-
# Create plot
180-
fig = create_plot(sample_data, "category", "value", title="Market Share Distribution")
181-
182-
# Save - ALWAYS use 'plot.png'!
183-
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
184-
print("Plot saved to plot.png")
24+
# Data from spec
25+
data = pd.DataFrame(
26+
{"category": ["Product A", "Product B", "Product C", "Product D", "Other"], "value": [35, 25, 20, 15, 5]}
27+
)
28+
29+
# Set seaborn style for consistent aesthetics
30+
sns.set_theme(style="white")
31+
32+
# Create figure (16:9 aspect ratio for 4800x2700 at 300 DPI)
33+
fig, ax = plt.subplots(figsize=(16, 9))
34+
35+
# Extract data
36+
categories = data["category"].tolist()
37+
values = data["value"].tolist()
38+
39+
# Use PyPlots colors
40+
colors = PYPLOTS_COLORS[: len(categories)]
41+
42+
# Create pie chart
43+
wedges, texts, autotexts = ax.pie(
44+
values,
45+
autopct="%1.1f%%",
46+
startangle=90,
47+
colors=colors,
48+
wedgeprops={"edgecolor": "white", "linewidth": 2},
49+
textprops={"fontsize": 16},
50+
pctdistance=0.7,
51+
)
52+
53+
# Style percentage labels
54+
for autotext in autotexts:
55+
autotext.set_fontsize(16)
56+
autotext.set_fontweight("bold")
57+
autotext.set_color("white")
58+
59+
# Ensure circular shape
60+
ax.set_aspect("equal")
61+
62+
# Add legend
63+
ax.legend(
64+
wedges,
65+
categories,
66+
title="Category",
67+
loc="center left",
68+
bbox_to_anchor=(1.0, 0.5),
69+
fontsize=16,
70+
title_fontsize=16,
71+
frameon=True,
72+
facecolor="white",
73+
edgecolor="gray",
74+
)
75+
76+
# Title
77+
ax.set_title("Market Share Distribution", fontsize=20, fontweight="semibold", pad=20)
78+
79+
plt.tight_layout()
80+
plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor="white")

0 commit comments

Comments
 (0)