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
df["lag1"] = df["sales_inr"].shift(1).df["lag12"] = df["sales_inr"].shift(12).df["t"] = range(len(df)).- Drop rows with NaN lags.
- Fit
LinearRegressionon train rows only;predicton 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.
Ravindra Bagale's Tip – मराठी
Lag = “मागचा number column”. LinearRegression = साधी line. Time series = features + प्रामाणिक time split.
Ravindra Bagale's Tip – हिंदी
Lag = “पिछला number column”. LinearRegression = सादी line. Time series = features + ईमानदार time split।