Why Delhi's Air Turns Toxic Every October — And Why That Isn't a Guess
Every year, around late October, Delhi's air quality index climbs from "moderate" to "severe" within a couple of weeks, stays brutal through November, and eases by January. Meteorologists, hospitals, and the Commission for Air Quality Management don't wait for it to happen — they plan for it in September, because the pattern repeats with eerie regularity: crop-residue burning in Punjab and Haryana after the paddy harvest, falling wind speeds as winter sets in, and a temperature inversion that traps pollutants near the ground. None of this is fortune-telling. It is time series analysis: using the structure hidden in a sequence of past measurements to say something disciplined about what comes next.
This is a fundamentally different problem from the machine learning you may have already met — classifying an email as spam, or predicting a house's price from its area and location. In those problems, each row of data (each email, each house) is treated as independent of the others; shuffling the rows before training changes nothing about what the model learns. A time series breaks that assumption on purpose. The order of the data is the information. Today's AQI depends on yesterday's wind and last week's crop-burning schedule; next month's electricity demand depends on this month's heatwave. Strip away the order, and you've thrown away the signal.
What a Time Series Actually Is
Formally, a time series is a sequence of observations indexed by time: y₁, y₂, y₃, …, yₙ, where the subscript t = 1, 2, …, n marks equally spaced time points — days, months, quarters. Because consecutive values are typically correlated with each other (a property called autocorrelation, which we'll compute exactly later), classical statistical tools built for independent samples — ordinary correlation between two unrelated variables, standard hypothesis tests — don't directly apply. Time series analysis is the toolkit built specifically to handle this dependence.
Most real time series can be thought of as a sum (or product) of a small number of underlying components:
- Trend (Tₜ): the long-run direction — sales climbing as a store gains customers, India's electricity demand rising as more households buy air conditioners.
- Seasonality (Sₜ): a pattern that repeats at a fixed, known period — AC sales peaking every summer, UPI transaction volumes dipping every year during the low-spending post-Diwali lull, ridership spiking every Monday morning. "Seasonal" doesn't have to mean the four seasons — it means "tied to the calendar or clock with a fixed period," whether that period is a day, a week, or a year.
- Cyclic component (Cₜ): a rise-and-fall pattern without a fixed period — a business cycle boom-bust that might take three years or seven, unlike seasonality's exact repeat.
- Residual / noise (εₜ): whatever is left after removing trend, seasonality, and cycle — the unpredictable part: a one-day discount sale, a sudden cricket-match-day traffic dip, ordinary randomness.
Combined additively, this gives the additive decomposition model:
yₜ = Tₜ + Sₜ + Cₜ + εₜ
(A multiplicative version, yₜ = Tₜ × Sₜ × Cₜ × εₜ, is used instead when the size of the seasonal swing grows along with the trend — festival-season e-commerce spikes get bigger in absolute rupee terms every year even if the percentage spike stays similar. For this chapter we'll work with the additive form, ignoring the cyclic term, since it's cleaner to compute by hand and captures the core idea.)
A Worked Decomposition: Two Years of AC Sales in Nagpur
Nagpur is one of India's hottest cities, and a small appliance store there sees air-conditioner sales climb steadily as the store's reputation grows, with a sharp seasonal jump every April–June before the monsoon breaks the heat. Here is two years (24 months) of illustrative sales data, constructed to show the mechanics cleanly:
Year 1 (Jan–Dec): 14, 18, 24, 38, 44, 40, 32, 32, 34, 38, 38, 44
Year 2 (Jan–Dec): 38, 42, 48, 62, 68, 64, 56, 56, 58, 62, 62, 68
Look at April–May in both years (values 38, 44 and 62, 68) against the surrounding months — a clear seasonal bump. But there's also a steady climb across the two years: December of Year 1 (44) is higher than December of Year 2's opening months. Two effects are tangled together, and decomposition is how we untangle them.
The key trick is the moving average. If the seasonal swings for a full 12-month cycle sum to exactly zero (which is how seasonal indices are conventionally defined — a "good month" is balanced by "bad months" elsewhere in the year), then averaging any 12 consecutive months makes the seasonal component vanish, leaving only the trend. Let's verify this by hand on the actual numbers.
Average of the first 12 months (t = 1 to 12): (14+18+24+38+44+40+32+32+34+38+38+44) ÷ 12 = 396 ÷ 12 = 33.
Now shift the 12-month window forward by one month (t = 2 to 13, i.e. Feb Year 1 through Jan Year 2): (18+24+38+44+40+32+32+34+38+38+44+38) ÷ 12 = 420 ÷ 12 = 35.
Notice the moving average rose from 33 to 35 — a clean, steady increase of 2 units as the window slides forward one month — even though the raw monthly figures jump around wildly (24 to 38 is a jump of 14 in a single month!). That smoothness is exactly the point: the moving average has filtered out the seasonal noise and revealed the underlying growth rate, which here is a genuine 2 units of trend growth per month.
Once you have this trend estimate at each point, you recover the seasonal component simply by subtracting: Sₜ = yₜ − Tₜ. For January of both years here, that difference works out to −8 in each case — the same seasonal dip, reliably, in both years, confirming January really is a weak month for this store independent of the overall growth trend. This subtract-and-average process, done properly across all twelve calendar months and both years, is exactly how statistical software (and CBSE's own Applied Mathematics statistics unit) defines a monthly seasonal index.
Seeing the Decomposition
The blue zig-zag is the raw data; the dashed red line is the underlying trend Tₜ = 20 + 2t we recovered above. Every April–June, the blue line jumps well above the dashed trend line — that gap is the seasonal component, Sₜ, visually. The whole discipline of decomposition is just: fit the smooth dashed line first, then read off the gaps.
Stationarity: The Property That Makes Forecasting Tractable
A time series is called stationary if its statistical properties — mean, variance, and how it correlates with its own past — don't change over time. A series with a rising trend, like our AC sales, is not stationary: its mean is different in month 1 than in month 24. This matters because most classical forecasting methods (including the AR and ARIMA models you'll meet in a full data-science course) are built on the mathematical assumption of stationarity — they model deviations around a constant, not a moving target.
The standard fix is differencing: instead of modelling yₜ directly, model the change Δyₜ = yₜ − yₜ₋₁. If the original series has a linear trend, differencing removes it almost completely, because the trend contributes an (almost) constant amount to every step.
Take a fresh, smaller example — the number of Ola/Uber rides booked each evening in one housing society over six consecutive weekdays: 40, 45, 47, 52, 58, 63. The first differences are:
45−40 = 5, 47−45 = 2, 52−47 = 5, 58−52 = 6, 63−58 = 5
The differenced series — 5, 2, 5, 6, 5 — hovers around a stable average of (5+2+5+6+5) ÷ 5 = 4.6, instead of climbing from 40 all the way to 63. That average, 4.6, is a direct estimate of "rides gained per weekday" — and later in this chapter, when we fit a formal trend line to the same six numbers, the least-squares slope comes out to 4.54, remarkably close. That's not a coincidence: differencing and trend-fitting are two different roads to the same underlying growth rate, and getting matching answers from both is a good way to sanity-check your own work.
Autocorrelation: Measuring "How Much Does Yesterday Predict Today?"
The single most important number in time series analysis is the autocorrelation coefficient at lag k, written rₖ. It measures how strongly a series correlates with a delayed copy of itself — exactly like an ordinary correlation coefficient, except instead of correlating two different variables, you correlate yₜ against yₜ₋ₖ. The formula, using ȳ for the series mean:
rₖ = [ Σₜ₌ₖ₊₁ⁿ (yₜ − ȳ)(yₜ₋ₖ − ȳ) ] ÷ [ Σₜ₌₁ⁿ (yₜ − ȳ)² ]
The denominator is just the total spread of the series around its mean (a fixed number once you know the data). The numerator pairs up each value with the value k steps earlier and multiplies their deviations from the mean — positive when both are above average or both below average together, negative when one is above and the other below.
Let's compute r₁ (lag-1 autocorrelation) for the ride-count series 40, 45, 47, 52, 58, 63 by hand. First, ȳ = (40+45+47+52+58+63) ÷ 6 = 305 ÷ 6 = 50.833. The deviations (yₜ − ȳ) are: −10.833, −5.833, −3.833, 1.167, 7.167, 12.167.
Denominator = sum of squared deviations = 10.833² + 5.833² + 3.833² + 1.167² + 7.167² + 12.167² ≈ 366.83.
Numerator = sum of consecutive products: (−5.833)(−10.833) + (−3.833)(−5.833) + (1.167)(−3.833) + (7.167)(1.167) + (12.167)(7.167) ≈ 63.19 + 22.36 − 4.47 + 8.37 + 87.20 ≈ 176.64.
r₁ ≈ 176.64 ÷ 366.83 ≈ 0.48.
A value of 0.48 is a moderately strong positive autocorrelation — today's ride count genuinely helps predict tomorrow's, which makes intuitive sense for a series that's steadily trending upward: two consecutive values sitting on the same rising slope will naturally sit on the same side of the mean together. Plotting rₖ against several values of k produces a correlogram, the standard diagnostic chart data scientists use to decide which forecasting model to reach for — a slow, gradual decay in rₖ (like you'd get here) signals a trend that needs differencing; a sharp cutoff after a few lags signals a different kind of underlying structure entirely. This is the exact diagnostic step that precedes fitting an ARIMA model, a topic you'll formalize if you continue toward a GATE-level data science foundation.
From Naive Guessing to a Real Forecasting Model
With decomposition and autocorrelation as diagnostic tools, we can now build forecasts in increasing order of sophistication, using the same six ride-count numbers throughout: 40, 45, 47, 52, 58, 63 (weeks 1–6), forecasting week 7.
1. Naive forecast: ŷₜ₊₁ = yₜ. Simply predict tomorrow will look like today. Forecast for week 7: ŷ₇ = y₆ = 63. Crude, but it's the baseline every real forecast must beat to justify its own complexity.
2. Moving-average forecast: ŷₜ₊₁ = average of the last k values. With k = 3: ŷ₇ = (y₄+y₅+y₆) ÷ 3 = (52+58+63) ÷ 3 = 173 ÷ 3 ≈ 57.67. It smooths out noise but, by construction, always lags behind a genuine trend, since it's built entirely from older, smaller numbers.
3. Linear trend regression: fit ŷₜ = a + bt by the method of least squares, minimizing the sum of squared errors Σ(yₜ − a − bt)². Rather than reach for calculus (that's a Class 12 tool), we can find a and b using pure algebra — the same simultaneous-equations skill you already have from Class 10. The condition that a and b minimize the squared error is captured by two "normal equations":
Σyₜ = na + bΣt (I)
Σtyₜ = aΣt + bΣt² (II)
These are just two linear equations in the two unknowns a and b — solvable by elimination. From (I): a = ȳ − bt̄. Substituting into (II) and using Σt = nt̄:
Σtyₜ = (ȳ − bt̄)(nt̄) + bΣt² ⟹ Σtyₜ − nt̄ȳ = b(Σt² − nt̄²)
⟹ b = (Σtyₜ − nt̄ȳ) ÷ (Σt² − nt̄²), and then a = ȳ − bt̄.
(A quick expansion check confirms Σtyₜ − nt̄ȳ is exactly equal to Σ(t−t̄)(y−ȳ), the more familiar "covariance-style" form of the same formula — both give identical numbers.)
Now apply it: t = 1..6, so Σt = 21, t̄ = 3.5, n = 6; Σy = 305, ȳ = 50.833; Σty = 1(40)+2(45)+3(47)+4(52)+5(58)+6(63) = 40+90+141+208+290+378 = 1147; Σt² = 1+4+9+16+25+36 = 91.
b = (1147 − 6×3.5×50.833) ÷ (91 − 6×3.5²) = (1147 − 1067.5) ÷ (91 − 73.5) = 79.5 ÷ 17.5 ≈ 4.543.
a = 50.833 − 4.543×3.5 ≈ 34.93.
So ŷₜ = 34.93 + 4.543t, and the week-7 forecast is ŷ₇ = 34.93 + 4.543×7 ≈ 66.73.
4. Simple exponential smoothing: a weighted average that favours recent observations without discarding older ones entirely, controlled by a smoothing constant α ∈ (0,1):
ŷₜ₊₁ = α·yₜ + (1−α)·ŷₜ
Each new forecast blends the latest actual value with the previous forecast; a bigger α reacts faster to recent changes but is noisier, a smaller α is smoother but slower to react. Starting with ŷ₁ = y₁ = 40 and α = 0.4:
rides = [40, 45, 47, 52, 58, 63] # rides booked, one housing society, weeks 1-6
def exponential_smoothing(series, alpha):
forecast = [float(series[0])] # y_hat_1 = y_1
for t in range(1, len(series)):
forecast.append(alpha * series[t-1] + (1 - alpha) * forecast[t-1])
forecast.append(alpha * series[-1] + (1 - alpha) * forecast[-1]) # week 7
return forecast
f = exponential_smoothing(rides, alpha=0.4)
print([round(x, 2) for x in f])
# [40.0, 40.0, 42.0, 44.0, 47.2, 51.52, 56.11]
Tracing this by hand confirms it: ŷ₂ = 0.4(40)+0.6(40) = 40, ŷ₃ = 0.4(45)+0.6(40) = 42, ŷ₄ = 0.4(47)+0.6(42) = 44, ŷ₅ = 0.4(52)+0.6(44) = 47.2, ŷ₆ = 0.4(58)+0.6(47.2) = 51.52, and finally ŷ₇ = 0.4(63)+0.6(51.52) = 56.112 ≈ 56.11 — the last entry printed, and the genuine one-step-ahead forecast for week 7.
Judging the Forecasts: MAE, RMSE, and MAPE
Suppose the actual week-7 ride count turns out to be 65. Three standard error measures compare a forecast ŷ against the actual y: Mean Absolute Error MAE = (1/n)Σ|yₜ−ŷₜ|, Root Mean Squared Error RMSE = √[(1/n)Σ(yₜ−ŷₜ)²] (which penalizes large errors more heavily than MAE, because squaring exaggerates big misses), and Mean Absolute Percentage Error MAPE = (100/n)Σ|(yₜ−ŷₜ)/yₜ|, which expresses the error as a percentage so you can compare accuracy across series measured in different units. With a single held-out point (n = 1), the absolute error and MAE coincide, letting us compare all four methods directly:
- Naive (ŷ = 63): |error| = 2.00, percentage error = 3.08%
- Moving average, k=3 (ŷ = 57.67): |error| = 7.33, percentage error = 11.28%
- Linear regression (ŷ = 66.73): |error| = 1.73, percentage error = 2.67%
- Exponential smoothing, α=0.4 (ŷ = 56.11): |error| = 8.89, percentage error = 13.68%
Regression wins here, and the reason is instructive, not accidental: this series has a strong, near-linear upward trend, and regression is the only method among the four built explicitly to extrapolate a trend forward. Moving averages and simple exponential smoothing both work by averaging in older, smaller numbers, so they systematically underforecast whenever there's a strong trend — a well-known limitation that motivates trend-adjusted extensions like Holt's method (double exponential smoothing), which adds a second smoothing equation just to track the trend's own rate of change. Naive forecasting, ironically, does reasonably well here too, precisely because the trend is so smooth that "tomorrow looks like today" isn't a bad approximation over a single step — a reminder that a fancier model isn't automatically a better one; you always test it against the naive baseline first.
Common Misconception: "I'll Just Shuffle the Data Before Splitting Train and Test"
In ordinary supervised learning, you split data into training and test sets randomly, because each row is independent — shuffling changes nothing about what's learnable. Applying that same instinct to time series is a serious, specific error. If you randomly shuffle a time series before splitting, some future time points end up in your training set while some past time points end up in your test set. Because consecutive observations are autocorrelated (as we measured directly with r₁ ≈ 0.48 above), a model effectively gets to "see the future" through a highly correlated neighbour sitting right next to a test point in training — producing an accuracy score that looks great on paper but is fiction, because in real deployment you will never have tomorrow's data available to help predict today.
The correct approach is a chronological split (also called walk-forward or out-of-time validation): train only on data up to some cutoff time, and test only on data strictly after it — exactly what we did above, training on weeks 1–6 and forecasting the genuinely unseen week 7. This mirrors the real forecasting task precisely: you only ever have the past to predict the future, never the reverse.
Where This Sits in Your Exams
Time series forecasting is an explicitly named topic within CBSE's Applied Mathematics (Code 241) statistics syllabus for Classes 11–12, and it's one of the practical "Data Science" applications covered under CBSE's Artificial Intelligence skill subject (Code 417) — expect board-level case-study questions asking you to compute a moving average, identify a trend, or interpret a seasonal pattern from a small dataset, much like the AC-sales example above. It is not a core JEE Main/Advanced or BITSAT topic, but the underlying mathematics you needed for every calculation here — solving simultaneous linear equations, summation notation, sequences and series, and basic statistics (mean, variance) — is squarely Class 10–11 board and competitive-exam material, and least-squares fitting is exactly the skill examined under "linear regression" in any Class 11 statistics unit. If you continue toward a GATE-foundation or data-science track later, the concepts introduced here by name but not fully derived — stationarity, the correlogram, AR/ARIMA models, Holt's trend-adjusted smoothing — are the direct next steps.
Summary
- A time series is an ordered sequence yₜ where order carries information; unlike ordinary ML data, consecutive points are correlated (autocorrelated), not independent.
- Real series decompose into trend (Tₜ), seasonality (Sₜ), and residual noise (εₜ): yₜ = Tₜ + Sₜ + εₜ. A moving average over one full seasonal cycle cancels the seasonal component (since it sums to zero) and reveals the trend.
- Stationarity — constant mean, variance, and autocorrelation structure over time — is required by classical forecasting models; differencing (yₜ − yₜ₋₁) is the standard way to convert a trending series into a roughly stationary one.
- The lag-k autocorrelation rₖ = [Σ(yₜ−ȳ)(yₜ₋ₖ−ȳ)] / [Σ(yₜ−ȳ)²] measures how strongly a series predicts itself k steps ahead; plotted across lags it forms a correlogram used to select forecasting models.
- Forecasting methods range from the naive forecast (ŷₜ₊₁ = yₜ), through moving averages and exponential smoothing (ŷₜ₊₁ = α yₜ + (1−α) ŷₜ), to least-squares linear trend regression, whose slope and intercept can be derived by solving two normal equations algebraically.
- MAE, RMSE, and MAPE quantify forecast accuracy; a method should always be checked against the naive baseline, and the best method depends on whether the series is dominated by trend, noise, or seasonality.
- Never randomly shuffle a time series before a train/test split — always split chronologically, training only on the past and testing only on the future.
Practice: Test Yourself
- A shop's monthly sales are 100, 108, 96, 104, 112, 100 (t = 1 to 6). Compute the first differences. Does the series look closer to stationary before or after differencing, and why?
Answer: Differences are 8, −12, 8, 8, −12, averaging around 0 with no upward or downward drift — this series has almost no trend to begin with (unlike the AC-sales or ride-count examples), so differencing mainly removes a small amount of noise structure rather than a trend. - Using the definition rₖ = [Σ(yₜ−ȳ)(yₜ₋ₖ−ȳ)] / [Σ(yₜ−ȳ)²], explain in one sentence why r₀ (lag zero) is always exactly 1 for any series.
Answer: At lag 0, the numerator becomes Σ(yₜ−ȳ)² — identical to the denominator — since you're correlating the series with itself with no shift at all, so the ratio is always 1. - For the Nagpur AC-sales trend Tₜ = 20 + 2t, what is the forecast for month t = 30 (month 6 of a hypothetical Year 3), ignoring seasonality?
Answer: T₃₀ = 20 + 2(30) = 80 units. - A colleague proposes randomly splitting five years of daily Mumbai rainfall data 80/20 into train and test sets to evaluate a monsoon-prediction model. What specific problem will this cause, and what should be done instead?
Answer: Random splitting lets days from the "test" period sit immediately next to highly autocorrelated days in the "training" period (consecutive monsoon days are extremely similar), leaking future information into training and producing an unrealistically optimistic accuracy score. A chronological split — train on earlier years, test on the most recent year — is the correct approach. - Given six weekly values with Σt = 21, Σy = 240, Σty = 980, Σt² = 91, n = 6, compute the least-squares trend slope b.
Answer: t̄ = 3.5, ȳ = 40. b = (Σty − nt̄ȳ) ÷ (Σt² − nt̄²) = (980 − 6×3.5×40) ÷ (91 − 6×12.25) = (980 − 840) ÷ (91 − 73.5) = 140 ÷ 17.5 = 8.
Think About It
Think about this: How would you explain time series analysis: predicting the future from the past to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.