{"spec_id":"area-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\narea-basic: Basic Area Chart\nLibrary: letsplot 4.10.1 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-05-28\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\nfrom lets_plot.export import ggsave\n\n\nLetsPlot.setup_html()\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\nBRAND = \"#009E73\"\nDIP_COLOR = \"#AE3030\"\n\n# Data — daily website visitors over January\nnp.random.seed(42)\ndays = pd.date_range(start=\"2024-01-01\", periods=30, freq=\"D\")\nbase_visitors = 5000\ntrend = np.linspace(0, 2000, 30)\nweekly_pattern = 1000 * np.sin(np.arange(30) * 2 * np.pi / 7)\nnoise = np.random.randn(30) * 300\nvisitors = base_visitors + trend + weekly_pattern + noise\nvisitors = np.clip(visitors, 2000, None).astype(int)\n\ndf = pd.DataFrame({\"date\": days, \"visitors\": visitors})\n\npeak_idx = int(df[\"visitors\"].idxmax())\ndip_idx = int(df[\"visitors\"].idxmin())\ndip_val = df.loc[dip_idx, \"visitors\"]\npeak_val = df.loc[peak_idx, \"visitors\"]\ngrowth_pct = (df[\"visitors\"].iloc[-5:].mean() / df[\"visitors\"].iloc[:5].mean() - 1) * 100\n\nsubtitle = f\"+{growth_pct:.0f}% average growth over January — weekly cycles with steady upward trend\"\n\nann_peak = df.iloc[[peak_idx]].copy()\nann_dip = df.iloc[[dip_idx]].copy()\n\ny_min = max(int(dip_val * 0.82), 0)\ny_max = int(peak_val * 1.06)\n\nanyplot_chrome = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG),\n    panel_grid_major_y=element_line(color=INK_SOFT, size=0.15),\n    panel_grid_major_x=element_blank(),\n    panel_grid_minor=element_blank(),\n    axis_title=element_text(color=INK, size=12),\n    axis_text=element_text(color=INK_SOFT, size=10),\n    axis_line=element_line(color=INK_SOFT),\n    plot_title=element_text(color=INK, size=16),\n    plot_subtitle=element_text(color=INK_SOFT, size=10),\n    plot_margin=[40, 60, 20, 20],\n)\n\nplot = (\n    ggplot(df, aes(x=\"date\", y=\"visitors\"))\n    + geom_area(fill=BRAND, alpha=0.15)\n    + geom_area(\n        fill=BRAND,\n        alpha=0.35,\n        tooltips=layer_tooltips()\n        .line(\"@visitors visitors\")\n        .format(\"date\", \"%b %d, %Y\")\n        .line(\"@date\"),\n    )\n    + geom_line(color=BRAND, size=1.0)\n    + geom_smooth(\n        color=INK_SOFT, size=0.8, se=False, method=\"loess\", linetype=\"dashed\"\n    )\n    + geom_point(\n        data=ann_peak,\n        mapping=aes(x=\"date\", y=\"visitors\"),\n        size=5,\n        color=BRAND,\n        fill=PAGE_BG,\n        shape=21,\n        stroke=2.0,\n    )\n    + geom_point(\n        data=ann_dip,\n        mapping=aes(x=\"date\", y=\"visitors\"),\n        size=5,\n        color=DIP_COLOR,\n        fill=PAGE_BG,\n        shape=21,\n        stroke=2.0,\n    )\n    + geom_text(\n        data=ann_peak,\n        mapping=aes(x=\"date\", y=\"visitors\", label=\"visitors\"),\n        nudge_y=-500,\n        size=4,\n        color=BRAND,\n        hjust=1,\n        label_format=\"▲ {,d} peak\",\n    )\n    + geom_text(\n        data=ann_dip,\n        mapping=aes(x=\"date\", y=\"visitors\", label=\"visitors\"),\n        nudge_y=-400,\n        size=4,\n        color=DIP_COLOR,\n        label_format=\"▼ {,d} dip\",\n    )\n    + scale_x_datetime(format=\"%b %d\")\n    + scale_y_continuous(limits=[y_min, y_max])\n    + labs(\n        x=\"Date\", y=\"Daily Visitors\", title=\"area-basic · python · letsplot · anyplot.ai\", subtitle=subtitle\n    )\n    + ggsize(800, 450)\n    + theme_minimal()\n    + anyplot_chrome\n)\n\nggsave(plot, filename=f\"plot-{THEME}.png\", path=\".\", scale=4)\nggsave(plot, filename=f\"plot-{THEME}.html\", path=\".\")\n"}