Skip to content

Commit 0f1f9f4

Browse files
feat(altair): implement line-basic
Simplified implementation following KISS principle: - Removed function wrapping - Removed type hints and docstrings - Sequential script structure - Uses data from spec example
1 parent 3da93d5 commit 0f1f9f4

1 file changed

Lines changed: 22 additions & 153 deletions

File tree

Lines changed: 22 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,35 @@
11
"""
2-
line-basic: Basic Line Chart
2+
line-basic: Basic Line Plot
33
Library: altair
44
"""
55

6-
from typing import TYPE_CHECKING
7-
86
import altair as alt
97
import pandas as pd
108

119

12-
if TYPE_CHECKING:
13-
from altair import Chart
14-
15-
# Style guide colors
16-
PYTHON_BLUE = "#306998"
17-
18-
19-
def create_plot(
20-
data: pd.DataFrame,
21-
x: str,
22-
y: str,
23-
title: str | None = None,
24-
xlabel: str | None = None,
25-
ylabel: str | None = None,
26-
color: str = PYTHON_BLUE,
27-
linewidth: float = 2,
28-
marker: str | None = None,
29-
marker_size: int = 60,
30-
alpha: float = 1.0,
31-
linestyle: str = "solid",
32-
**kwargs,
33-
) -> "Chart":
34-
"""
35-
Create a basic line chart showing trends over a continuous axis.
36-
37-
Args:
38-
data: Input DataFrame with required columns
39-
x: Column name for x-axis values (typically time or sequence)
40-
y: Column name for y-axis values
41-
title: Plot title (default: None)
42-
xlabel: Custom x-axis label (default: uses column name)
43-
ylabel: Custom y-axis label (default: uses column name)
44-
color: Line color (default: Python Blue #306998)
45-
linewidth: Width of the line (default: 2)
46-
marker: Marker style - 'circle', 'square', 'diamond', etc. (default: None)
47-
marker_size: Size of markers if enabled (default: 60)
48-
alpha: Transparency level for the line (default: 1.0)
49-
linestyle: Line style - 'solid', 'dashed', 'dotted' (default: 'solid')
50-
**kwargs: Additional parameters for altair chart configuration
51-
52-
Returns:
53-
Altair Chart object
54-
55-
Raises:
56-
ValueError: If data is empty
57-
KeyError: If required columns not found
58-
59-
Example:
60-
>>> data = pd.DataFrame({
61-
... 'month': [1, 2, 3, 4, 5, 6],
62-
... 'sales': [100, 150, 130, 180, 200, 190]
63-
... })
64-
>>> chart = create_plot(data, x='month', y='sales')
65-
"""
66-
# Input validation
67-
if data.empty:
68-
raise ValueError("Data cannot be empty")
69-
70-
for col in [x, y]:
71-
if col not in data.columns:
72-
available = ", ".join(data.columns)
73-
raise KeyError(f"Column '{col}' not found. Available columns: {available}")
74-
75-
# Sort data by x-axis to ensure proper line connections
76-
plot_data = data.sort_values(by=x).copy()
10+
# Data
11+
data = pd.DataFrame({"time": [1, 2, 3, 4, 5, 6, 7], "value": [10, 15, 13, 18, 22, 19, 25]})
7712

78-
# Determine x encoding type based on data
79-
x_dtype = plot_data[x].dtype
80-
if pd.api.types.is_datetime64_any_dtype(x_dtype):
81-
x_encoding = f"{x}:T"
82-
else:
83-
x_encoding = f"{x}:Q"
84-
85-
# Map linestyle to altair strokeDash
86-
stroke_dash_map = {"solid": [], "dashed": [8, 4], "dotted": [2, 2]}
87-
stroke_dash = stroke_dash_map.get(linestyle, [])
88-
89-
# Create the line chart
90-
line = (
91-
alt.Chart(plot_data)
92-
.mark_line(color=color, strokeWidth=linewidth, opacity=alpha, strokeDash=stroke_dash)
93-
.encode(
94-
x=alt.X(
95-
x_encoding,
96-
title=xlabel or x,
97-
axis=alt.Axis(labelAngle=0, labelLimit=200, labelFontSize=16, titleFontSize=20),
98-
),
99-
y=alt.Y(
100-
f"{y}:Q",
101-
title=ylabel or y,
102-
scale=alt.Scale(zero=False),
103-
axis=alt.Axis(labelFontSize=16, titleFontSize=20),
104-
),
105-
tooltip=[
106-
alt.Tooltip(x_encoding, title=xlabel or x),
107-
alt.Tooltip(f"{y}:Q", title=ylabel or y, format=".2f"),
108-
],
109-
)
110-
)
111-
112-
# Add markers if specified
113-
if marker:
114-
points = (
115-
alt.Chart(plot_data)
116-
.mark_point(color=color, size=marker_size, filled=True, shape=marker, opacity=alpha)
117-
.encode(
118-
x=alt.X(x_encoding),
119-
y=alt.Y(f"{y}:Q"),
120-
tooltip=[
121-
alt.Tooltip(x_encoding, title=xlabel or x),
122-
alt.Tooltip(f"{y}:Q", title=ylabel or y, format=".2f"),
123-
],
124-
)
125-
)
126-
chart_base = line + points
127-
else:
128-
chart_base = line
129-
130-
# Apply properties and configuration
131-
# Target: 4800 × 2700 px with scale_factor=3.0 -> 1600 × 900 base
132-
title_config = alt.TitleParams(text=title, fontSize=20, anchor="middle") if title else None
133-
chart = (
134-
chart_base.properties(width=1600, height=900, title=title_config)
135-
.configure_view(strokeWidth=0)
136-
.configure_axis(grid=True, gridOpacity=0.3, gridDash=[3, 3], domainWidth=1, tickWidth=1)
13+
# Create line chart
14+
line = (
15+
alt.Chart(data)
16+
.mark_line(strokeWidth=2, color="#306998")
17+
.encode(
18+
x=alt.X("time:Q", title="Time", axis=alt.Axis(labelFontSize=16, titleFontSize=20)),
19+
y=alt.Y("value:Q", title="Value", axis=alt.Axis(labelFontSize=16, titleFontSize=20)),
13720
)
21+
)
13822

139-
return chart
23+
# Add points on the line for clarity
24+
points = alt.Chart(data).mark_point(size=100, color="#306998", filled=True).encode(x="time:Q", y="value:Q")
14025

26+
# Combine and configure chart
27+
chart = (
28+
(line + points)
29+
.properties(width=1600, height=900, title=alt.Title("Basic Line Plot", fontSize=20))
30+
.configure_view(strokeWidth=0)
31+
.configure_axis(grid=True, gridOpacity=0.3)
32+
)
14133

142-
if __name__ == "__main__":
143-
# Sample data for testing - monthly sales trend
144-
sample_data = pd.DataFrame(
145-
{
146-
"Month": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
147-
"Sales": [120, 150, 170, 165, 180, 220, 250, 240, 210, 190, 180, 200],
148-
}
149-
)
150-
151-
# Create plot with markers
152-
chart = create_plot(
153-
sample_data,
154-
x="Month",
155-
y="Sales",
156-
title="Monthly Sales Trend (2024)",
157-
xlabel="Month",
158-
ylabel="Sales (thousands)",
159-
linewidth=2.5,
160-
marker="circle",
161-
marker_size=80,
162-
)
163-
164-
# Save as PNG - scale_factor=3.0 gives 4800 × 2700 px
165-
chart.save("plot.png", scale_factor=3.0)
166-
print("Plot saved to plot.png")
34+
# Save as PNG (1600 × 900 at scale 3 = 4800 × 2700 px)
35+
chart.save("plot.png", scale_factor=3.0)

0 commit comments

Comments
 (0)