Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 70 additions & 30 deletions plots/acf-pacf/implementations/python/plotnine.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
""" pyplots.ai
""" anyplot.ai
acf-pacf: Autocorrelation and Partial Autocorrelation (ACF/PACF) Plot
Library: plotnine 0.15.3 | Python 3.14.3
Quality: 90/100 | Created: 2026-03-14
Library: plotnine 0.15.5 | Python 3.13.13
Quality: 91/100 | Updated: 2026-06-10
"""

import os
import sys

import numpy as np
import pandas as pd
from plotnine import (


# Work around naming conflict with plotnine.py script and plotnine package
script_dir = os.path.dirname(os.path.abspath(__file__))
if script_dir in sys.path:
sys.path.remove(script_dir)
if "" in sys.path:
sys.path.remove("")
if "." in sys.path:
sys.path.remove(".")

from plotnine import ( # noqa: E402
aes,
element_blank,
element_line,
Expand All @@ -16,18 +30,32 @@
geom_hline,
geom_point,
geom_segment,
geom_vline,
ggplot,
guides,
labs,
scale_color_manual,
scale_x_continuous,
scale_y_continuous,
theme,
theme_minimal,
)
from statsmodels.tsa.stattools import acf, pacf


# Data - Simulated monthly temperature with seasonality and AR(1) component
# Theme tokens — Imprint palette, theme-adaptive chrome
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"
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"

# Imprint palette positions used
BRAND = "#009E73" # position 1 — significant lags (brand green, first series)
ALARM = "#AE3030" # position 5 — confidence bounds (semantic: alert/threshold)

# Data — simulated monthly temperature with seasonality and AR(1) component
np.random.seed(42)
n_obs = 240
time = np.arange(n_obs)
Expand All @@ -51,43 +79,55 @@

# Mark significance: lags outside confidence bounds
df["significant"] = np.where(np.abs(df["correlation"]) > confidence_bound, "Significant", "Non-significant")
# Lag 0 in ACF is always 1.0 by definition - not a meaningful significant lag
# Lag 0 in ACF is always 1.0 by definition not a meaningful significant lag
df.loc[(df["panel"] == "ACF") & (df["lag"] == 0), "significant"] = "Non-significant"

# Colors
PYTHON_BLUE = "#306998"
MUTED_SILVER = "#B0BEC5"
CONF_RED = "#C0392B"
# Seasonal lag markers restricted to ACF panel — period-12 structure at lags 12, 24, 36
seasonal_ann_df = pd.DataFrame(
{
"xintercept": [12, 24, 36],
"panel": pd.Categorical(["ACF", "ACF", "ACF"], categories=["ACF", "PACF"], ordered=True),
}
)

# Title — 41 chars, within 67-char baseline, no font scaling needed
title = "acf-pacf · python · plotnine · anyplot.ai"

# Plot with significance coloring for visual storytelling
# Plot — strip labels "ACF" / "PACF" serve as per-panel y-axis identifiers per spec
plot = (
ggplot(df, aes(x="lag", y="correlation", color="significant"))
+ geom_hline(yintercept=0, color="#9E9E9E", size=0.7)
+ geom_hline(yintercept=confidence_bound, linetype="dashed", color=CONF_RED, size=0.8, alpha=0.5)
+ geom_hline(yintercept=-confidence_bound, linetype="dashed", color=CONF_RED, size=0.8, alpha=0.5)
+ geom_segment(aes(x="lag", xend="lag", y=0, yend="correlation"), size=1.3)
+ geom_point(size=3.2)
+ scale_color_manual(values={"Significant": PYTHON_BLUE, "Non-significant": MUTED_SILVER})
+ geom_hline(yintercept=0, color=INK_SOFT, size=0.6, alpha=0.8)
+ geom_vline(
data=seasonal_ann_df, mapping=aes(xintercept="xintercept"), color=BRAND, alpha=0.14, size=0.8, linetype="dotted"
)
+ geom_hline(yintercept=confidence_bound, linetype="dashed", color=ALARM, size=0.7, alpha=0.65)
+ geom_hline(yintercept=-confidence_bound, linetype="dashed", color=ALARM, size=0.7, alpha=0.65)
+ geom_segment(aes(x="lag", xend="lag", y=0, yend="correlation"), size=1.2)
+ geom_point(size=3.0)
+ scale_color_manual(values={"Significant": BRAND, "Non-significant": INK_MUTED})
+ guides(color="none")
+ facet_wrap("~panel", ncol=1, scales="free_y")
+ scale_x_continuous(breaks=range(0, n_lags + 1, 6))
+ labs(x="Lag", y="Correlation", title="acf-pacf · plotnine · pyplots.ai")
+ scale_x_continuous(breaks=list(range(0, n_lags + 1, 6)))
+ scale_y_continuous(expand=(0.04, 0))
+ labs(x="Lag", y="", title=title)
+ theme_minimal()
+ theme(
figure_size=(16, 10),
text=element_text(size=14, color="#2C3E50"),
axis_title=element_text(size=20, face="bold"),
axis_text=element_text(size=16, color="#546E7A"),
plot_title=element_text(size=24, face="bold", color="#1A237E"),
strip_text=element_text(size=20, face="bold", color="#263238"),
strip_background=element_rect(fill="#F5F5F5", color="none"),
figure_size=(8, 4.5),
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
panel_background=element_rect(fill=PAGE_BG),
panel_grid_major_x=element_blank(),
panel_grid_minor_x=element_blank(),
panel_grid_major_y=element_line(color="#ECEFF1", size=0.4),
panel_grid_major_y=element_line(color=INK, size=0.2, alpha=0.12),
panel_grid_minor_y=element_blank(),
panel_spacing_y=0.15,
axis_title_x=element_text(color=INK, size=10),
axis_title_y=element_blank(),
axis_text=element_text(color=INK_SOFT, size=8),
plot_title=element_text(color=INK, size=12, face="bold"),
strip_background=element_rect(fill=PAGE_BG, color="none"),
strip_text=element_text(color=INK, size=10, face="bold"),
panel_spacing_y=0.08,
)
)

# Save
plot.save("plot.png", dpi=300, verbose=False)
# Save — canvas: 8×4.5 in × 400 dpi = 3200×1800 px
plot.save(f"plot-{THEME}.png", dpi=400, width=8, height=4.5, units="in", verbose=False)
Loading
Loading