Ravindra BagaleCourses & study guides मराठी Track your progress

65. How to Forecast Sales with Time Series in Python (pandas and sklearn)

65.5 Lag Features + LinearRegression with sklearn

Why. Regular linear regression on random shop rows is not enough for months. We turn “past months” into columns (lags), then fit LinearRegression.

What.

  • Lag 1 — sales last month.
  • Lag 12 — sales same month last year.
  • t — time index 0, 1, 2… (simple trend helper).
  • Model: sales ≈ a*lag1 + b*lag12 + c*t + intercept.

How.

Build lag table and fit

  1. df["lag1"] = df["sales_inr"].shift(1).
  2. df["lag12"] = df["sales_inr"].shift(12).
  3. df["t"] = range(len(df)).
  4. Drop rows with NaN lags.
  5. Fit LinearRegression on train rows only; predict on test rows.

Worked example A — Create lags.

import pandas as pd
import numpy as np

df = pd.read_csv("mauli_monthly_sales.csv", parse_dates=["month"]).sort_values("month")
df["lag1"] = df["sales_inr"].shift(1)
df["lag12"] = df["sales_inr"].shift(12)
df["t"] = np.arange(len(df))
print(df[["month", "sales_inr", "lag1", "lag12", "t"]].head(14).tail(3).to_string(index=False))

What it means. Early rows miss lag12 (need one year of history). After month 12, features are ready.

Worked example B — Fit and predict May–Oct 2026.

from sklearn.linear_model import LinearRegression
import pandas as pd
import numpy as np

df = pd.read_csv("mauli_monthly_sales.csv", parse_dates=["month"]).sort_values("month")
df["lag1"] = df["sales_inr"].shift(1)
df["lag12"] = df["sales_inr"].shift(12)
df["t"] = np.arange(len(df))
feat = df.dropna().reset_index(drop=True)
split = pd.Timestamp("2026-05-01")
tr = feat[feat["month"] < split]
te = feat[feat["month"] >= split]
model = LinearRegression().fit(tr[["lag1", "lag12", "t"]], tr["sales_inr"])
pred = model.predict(te[["lag1", "lag12", "t"]])
print("coef lag1, lag12, t:", [round(float(c), 4) for c in model.coef_])
print("intercept:", round(float(model.intercept_), 2))
print(list(zip(te["month"].dt.strftime("%Y-%m"), te["sales_inr"].astype(int), np.round(pred).astype(int))))

Output you should see.

coef lag1, lag12, t: [-0.0365, 1.1753, -1255.727]
intercept: 60912.34
[('2026-05', 674800, 664259), ('2026-06', 620700, 623235), ('2026-07', 602500, 606439), ('2026-08', 694700, 697050), ('2026-09', 799900, 807966), ('2026-10', 878700, 862580)]

What it means. Lag12 carries most of the seasonal story (coef ≈ 1.18). Predictions track actuals much closer than a flat naive line.

Worked example C — One-row story for a manager.

“For Oct 2026 we predicted ₹862,580 vs actual ₹878,700 — about 1.8% low — using last month, last year, and a time index.”

Ravindra Bagale's Tip

Lag = “past value as a column”. LinearRegression = a plain line. Time series work = good features + an honest time split.