An area chart showing quantitative data over a continuous axis with the area below the line filled. It emphasizes the magnitude of values over time by filling the space between the line and axis, creating visual weight that helps readers understand volume and trends. Particularly effective for showing cumulative totals, resource consumption, or any data where the "amount" is as important as the trend.

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