|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | area-basic: Basic Area Chart |
3 | | -Library: matplotlib 3.10.8 | Python 3.13.11 |
4 | | -Quality: 92/100 | Created: 2025-12-23 |
| 3 | +Library: matplotlib 3.10.8 | Python 3.14.2 |
| 4 | +Quality: /100 | Updated: 2026-02-11 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import matplotlib.colors as mcolors |
7 | 8 | import matplotlib.pyplot as plt |
8 | 9 | import numpy as np |
| 10 | +from matplotlib.patches import PathPatch |
| 11 | +from matplotlib.path import Path |
9 | 12 |
|
10 | 13 |
|
11 | | -# Data - daily website visitors over a month |
| 14 | +# Data - daily website visitors over a month with weekend dips |
12 | 15 | np.random.seed(42) |
13 | 16 | days = np.arange(1, 31) |
14 | | -base_visitors = 5000 + np.linspace(0, 2000, 30) # Upward trend |
15 | | -noise = np.random.randn(30) * 500 |
16 | | -visitors = base_visitors + noise |
17 | | -visitors = np.clip(visitors, 3000, 10000) # Realistic bounds |
| 17 | +base_visitors = 5000 + np.linspace(0, 2500, 30) # Upward trend |
| 18 | +weekend_effect = np.array([-1200 if d % 7 in (0, 6) else 0 for d in days]) # Weekend dips |
| 19 | +noise = np.random.randn(30) * 400 |
| 20 | +visitors = base_visitors + weekend_effect + noise |
| 21 | +visitors = np.clip(visitors, 2000, 10000) |
18 | 22 |
|
19 | 23 | # Create plot (4800x2700 px) |
20 | 24 | fig, ax = plt.subplots(figsize=(16, 9)) |
21 | 25 |
|
22 | | -# Area chart with semi-transparent fill |
23 | | -ax.fill_between(days, visitors, alpha=0.4, color="#306998") |
24 | | -ax.plot(days, visitors, color="#306998", linewidth=3) |
| 26 | +y_max = visitors.max() * 1.15 |
| 27 | + |
| 28 | +# Gradient fill using imshow clipped to the area shape |
| 29 | +cmap = mcolors.LinearSegmentedColormap.from_list("area_grad", ["#d6e6f5", "#306998"]) |
| 30 | +gradient = np.linspace(0, 1, 256).reshape(-1, 1) |
| 31 | +gradient = np.hstack([gradient, gradient]) |
| 32 | + |
| 33 | +# Build clip path manually from fill_between polygon |
| 34 | +verts = [(days[0], 0)] |
| 35 | +for d, v in zip(days, visitors, strict=True): |
| 36 | + verts.append((d, v)) |
| 37 | +verts.append((days[-1], 0)) |
| 38 | +verts.append((days[0], 0)) |
| 39 | +codes = [Path.MOVETO] + [Path.LINETO] * (len(verts) - 2) + [Path.CLOSEPOLY] |
| 40 | +clip_path = Path(verts, codes) |
| 41 | + |
| 42 | +im = ax.imshow( |
| 43 | + gradient, aspect="auto", cmap=cmap, alpha=0.6, extent=[days[0], days[-1], 0, y_max], origin="lower", zorder=1 |
| 44 | +) |
| 45 | +patch = PathPatch(clip_path, transform=ax.transData, facecolor="none", edgecolor="none") |
| 46 | +ax.add_patch(patch) |
| 47 | +im.set_clip_path(patch) |
| 48 | + |
| 49 | +# Solid line on top |
| 50 | +ax.plot(days, visitors, color="#306998", linewidth=3, zorder=3) |
25 | 51 |
|
26 | 52 | # Labels and styling |
27 | 53 | ax.set_xlabel("Day of Month", fontsize=20) |
28 | | -ax.set_ylabel("Daily Visitors", fontsize=20) |
| 54 | +ax.set_ylabel("Daily Visitors (count)", fontsize=20) |
29 | 55 | ax.set_title("area-basic · matplotlib · pyplots.ai", fontsize=24) |
30 | 56 | ax.tick_params(axis="both", labelsize=16) |
31 | 57 | ax.grid(True, alpha=0.3, linestyle="--") |
32 | 58 |
|
33 | | -# Set axis limits for better presentation |
| 59 | +# Set axis limits |
34 | 60 | ax.set_xlim(1, 30) |
35 | | -ax.set_ylim(0, ax.get_ylim()[1] * 1.1) |
| 61 | +ax.set_ylim(0, y_max) |
36 | 62 |
|
37 | 63 | plt.tight_layout() |
38 | 64 | plt.savefig("plot.png", dpi=300, bbox_inches="tight") |
0 commit comments