Skip to content

Commit 3cafedf

Browse files
feat(pygal): implement bar-basic (#128)
## Summary Implements `bar-basic` for **pygal** library. - Creates a basic vertical bar chart for categorical data comparison - Uses custom styling with subtle grid and proper colors - Supports configurable figure size, colors, alpha, title, and axis labels - Handles missing values gracefully - Y-axis starts at zero for accurate visual comparison **Parent Issue:** #117 **Sub-Issue:** #124 **Base Branch:** `plot/bar-basic` **Attempt:** 1/3 ## Implementation - `plots/pygal/bar/bar-basic/default.py` ## Quality Checklist - [x] X-axis displays category labels clearly - [x] Y-axis shows numeric scale with appropriate tick marks - [x] Both axes are labeled - [x] Grid lines are visible but subtle on y-axis only - [x] Bars have consistent width and spacing - [x] Bar colors are distinguishable from background - [x] Title is present when specified - [x] Y-axis starts at zero Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
1 parent eabafca commit 3cafedf

1 file changed

Lines changed: 117 additions & 0 deletions

File tree

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
bar-basic: Basic Bar Chart
3+
Library: pygal
4+
"""
5+
6+
import pandas as pd
7+
import pygal
8+
from pygal.style import Style
9+
10+
11+
def create_plot(
12+
data: pd.DataFrame,
13+
category: str,
14+
value: str,
15+
figsize: tuple[int, int] = (1600, 900),
16+
color: str = "#3498db",
17+
alpha: float = 0.8,
18+
title: str | None = None,
19+
xlabel: str | None = None,
20+
ylabel: str | None = None,
21+
rotation: int = 0,
22+
**kwargs,
23+
) -> pygal.Bar:
24+
"""
25+
Create a basic vertical bar chart for categorical data comparison.
26+
27+
Args:
28+
data: Input DataFrame containing the data to plot.
29+
category: Column name for category labels (x-axis).
30+
value: Column name for numeric values (bar heights).
31+
figsize: Figure size as (width, height) in pixels.
32+
color: Bar fill color.
33+
alpha: Transparency level for bars (0.0 to 1.0).
34+
title: Optional plot title.
35+
xlabel: X-axis label (defaults to category column name).
36+
ylabel: Y-axis label (defaults to value column name).
37+
rotation: Rotation angle for x-axis labels.
38+
**kwargs: Additional parameters passed to pygal.Bar.
39+
40+
Returns:
41+
pygal.Bar chart object.
42+
43+
Raises:
44+
ValueError: If data is empty.
45+
KeyError: If required columns are not found in data.
46+
47+
Example:
48+
>>> data = pd.DataFrame({
49+
... 'category': ['A', 'B', 'C'],
50+
... 'value': [10, 20, 30]
51+
... })
52+
>>> chart = create_plot(data, 'category', 'value', title='Sample Chart')
53+
"""
54+
# Input validation
55+
if data.empty:
56+
raise ValueError("Data cannot be empty")
57+
58+
for col in [category, value]:
59+
if col not in data.columns:
60+
available = ", ".join(data.columns)
61+
raise KeyError(f"Column '{col}' not found. Available: {available}")
62+
63+
# Handle missing values
64+
clean_data = data[[category, value]].dropna()
65+
66+
# Create custom style with subtle grid and proper colors
67+
custom_style = Style(
68+
background="white",
69+
plot_background="white",
70+
foreground="#333333",
71+
foreground_strong="#333333",
72+
foreground_subtle="#666666",
73+
opacity=str(alpha),
74+
opacity_hover=str(min(alpha + 0.1, 1.0)),
75+
colors=(color,),
76+
guide_stroke_color="#cccccc",
77+
major_guide_stroke_color="#cccccc",
78+
)
79+
80+
# Create chart
81+
chart = pygal.Bar(
82+
width=figsize[0],
83+
height=figsize[1],
84+
title=title,
85+
x_title=xlabel if xlabel else category,
86+
y_title=ylabel if ylabel else value,
87+
style=custom_style,
88+
show_legend=False,
89+
show_y_guides=True,
90+
show_x_guides=False,
91+
x_label_rotation=rotation,
92+
print_values=False,
93+
range=(0, None),
94+
**kwargs,
95+
)
96+
97+
# Set x-axis labels
98+
chart.x_labels = [str(cat) for cat in clean_data[category].tolist()]
99+
100+
# Add data series
101+
chart.add("", clean_data[value].tolist())
102+
103+
return chart
104+
105+
106+
if __name__ == "__main__":
107+
# Sample data for testing
108+
sample_data = pd.DataFrame(
109+
{"category": ["Product A", "Product B", "Product C", "Product D", "Product E"], "value": [45, 78, 52, 91, 63]}
110+
)
111+
112+
# Create plot
113+
chart = create_plot(sample_data, "category", "value", title="Sales by Product")
114+
115+
# Save to PNG
116+
chart.render_to_png("plot.png")
117+
print("Plot saved to plot.png")

0 commit comments

Comments
 (0)