|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | line-timeseries: Time Series Line Plot |
3 | | -Library: plotnine 0.15.2 | Python 3.13.11 |
4 | | -Quality: 92/100 | Created: 2025-12-26 |
| 3 | +Library: plotnine 0.15.4 | Python 3.13.13 |
| 4 | +Quality: 92/100 | Updated: 2026-05-09 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import numpy as np |
8 | 10 | import pandas as pd |
9 | 11 | from mizani.breaks import breaks_date |
10 | 12 | from mizani.labels import label_date |
11 | 13 | from plotnine import ( |
12 | 14 | aes, |
13 | 15 | element_line, |
| 16 | + element_rect, |
14 | 17 | element_text, |
15 | 18 | geom_line, |
16 | 19 | geom_point, |
|
22 | 25 | ) |
23 | 26 |
|
24 | 27 |
|
25 | | -# Data: Daily stock prices over one year |
| 28 | +THEME = os.getenv("ANYPLOT_THEME", "light") |
| 29 | +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" |
| 30 | +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" |
| 31 | +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
| 32 | +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
| 33 | +BRAND = "#009E73" |
| 34 | + |
| 35 | +# Data: Bitcoin prices over one year with explicit trend and volatility |
26 | 36 | np.random.seed(42) |
27 | | -dates = pd.date_range(start="2024-01-01", periods=252, freq="B") # Business days |
28 | | -price = 100.0 |
| 37 | +dates = pd.date_range(start="2023-01-01", periods=365, freq="D") |
| 38 | +price = 16500.0 |
29 | 39 | prices = [] |
30 | | -for _ in range(252): |
31 | | - price = price * (1 + np.random.randn() * 0.015) |
| 40 | +for i in range(365): |
| 41 | + # Trend component: upward over the year, with mid-year dip |
| 42 | + trend = 20000 + 15000 * np.sin(i / 365 * np.pi * 2) + i * 5 |
| 43 | + # Volatility: crypto is more volatile than stocks |
| 44 | + volatility = price * (1 + np.random.randn() * 0.035) |
| 45 | + # Mix trend and volatility |
| 46 | + price = 0.7 * trend + 0.3 * volatility |
32 | 47 | prices.append(price) |
33 | 48 |
|
34 | 49 | df = pd.DataFrame({"date": dates, "price": prices}) |
35 | 50 |
|
36 | 51 | # Plot |
37 | 52 | plot = ( |
38 | 53 | ggplot(df, aes(x="date", y="price")) |
39 | | - + geom_line(color="#306998", size=1.5, alpha=0.9) |
40 | | - + geom_point(color="#306998", size=0.8, alpha=0.5) |
41 | | - + scale_x_datetime(breaks=breaks_date(7), labels=label_date("%b %Y")) |
42 | | - + labs(title="line-timeseries · plotnine · pyplots.ai", x="Date", y="Stock Price ($)") |
| 54 | + + geom_line(color=BRAND, size=1.5, alpha=0.9) |
| 55 | + + geom_point(color=BRAND, size=0.8, alpha=0.5) |
| 56 | + + scale_x_datetime(breaks=breaks_date(30), labels=label_date("%b")) |
| 57 | + + labs(title="line-timeseries · plotnine · anyplot.ai", x="Date", y="Bitcoin Price (USD)") |
43 | 58 | + theme_minimal() |
44 | 59 | + theme( |
45 | 60 | figure_size=(16, 9), |
46 | | - text=element_text(size=14), |
47 | | - axis_title=element_text(size=20), |
48 | | - axis_text=element_text(size=16), |
| 61 | + plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), |
| 62 | + panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG), |
| 63 | + panel_grid_major=element_line(color=INK, size=0.3, alpha=0.10), |
| 64 | + panel_grid_minor=element_line(color=INK, size=0.2, alpha=0.05), |
| 65 | + panel_border=element_rect(color=INK_SOFT, fill=None), |
| 66 | + text=element_text(size=14, color=INK), |
| 67 | + axis_title=element_text(size=20, color=INK), |
| 68 | + axis_text=element_text(size=16, color=INK_SOFT), |
49 | 69 | axis_text_x=element_text(angle=45, hjust=1), |
50 | | - plot_title=element_text(size=24), |
51 | | - panel_grid_major=element_line(color="#cccccc", size=0.5, alpha=0.3), |
52 | | - panel_grid_minor=element_line(color="#dddddd", size=0.3, alpha=0.2), |
| 70 | + plot_title=element_text(size=24, color=INK), |
53 | 71 | ) |
54 | 72 | ) |
55 | 73 |
|
56 | 74 | # Save |
57 | | -plot.save("plot.png", dpi=300) |
| 75 | +plot.save(f"plot-{THEME}.png", dpi=300) |
0 commit comments