Time Series Interview Questions for Data Science

Time series interviews test whether you respect time: no peeking at the future, honest baselines, and metrics that do not mislead. Seven questions answered on four years of real hourly electricity use: baselines, autocorrelation, what a stationarity test misses, shuffled cross-validation, a leaky feature and MAPE.

GloryTecks Team

Training & Placement Faculty

6 May 2026 8 min read

Last updated: 8 October 2026

Share:

Time series questions look like ordinary machine learning questions until you notice the one rule that changes everything: the future must not leak into the past. Interviewers check whether you respect that rule in your baselines, your validation, your features and your metrics. These time series interview questions are answered on four years of real electricity use, so every claim comes with a number.

The data is the UCI household power set: one reading a minute from a house in Sceaux, near Paris, from December 2006 to November 2010 (UCI: household power consumption), averaged here to 34,589 hourly values in kilowatts. The last six months are held back as a test period.

python
import numpy as np
import pandas as pd
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import KFold, TimeSeriesSplit
from statsmodels.tsa.stattools import acf, adfuller

raw = pd.read_csv("household_power_consumption.txt", sep=";", na_values="?", usecols=["Date", "Time", "Global_active_power"])
raw.index = pd.to_datetime(raw["Date"] + " " + raw["Time"], format="%d/%m/%Y %H:%M:%S")
hourly = raw["Global_active_power"].resample("h").mean()          # kW, one value per hour
print(f"T1 {len(hourly):,} hours, {hourly.isna().sum()} with no readings at all; filled by time interpolation")
y = hourly.interpolate("time")

test = y["2010-05-01":]                                          # last six months as the test period
print(f"\nT2 baselines on {len(test):,} test hours (MAE, kW)")
for name, lag in (("last hour", 1), ("same hour yesterday", 24), ("same hour last week", 168), ("training mean", None)):
    guess = y[:"2010-04-30"].mean() if lag is None else y.shift(lag)[test.index]
    print(f"   {name:<22} {np.abs(test - guess).mean():.3f}")

r = acf(y, nlags=168)
print(f"\nT3 autocorrelation: lag 1 {r[1]:.2f}, lag 12 {r[12]:.2f}, lag 24 {r[24]:.2f}, lag 168 {r[168]:.2f}")

daily = y.resample("D").mean()
by_month = daily.groupby(daily.index.month).mean()
print(f"\nT4 ADF test on daily means: p = {adfuller(daily, result_object=False)[1]:.4f}, "
      f"yet the mean is {by_month[12]:.2f} kW in December and {by_month[8]:.2f} kW in August")

X = pd.DataFrame({"hour": y.index.hour, "weekday": y.index.dayofweek, "month": y.index.month,
                  "lag24": y.shift(24), "lag168": y.shift(168)}, index=y.index).dropna()
target = y[X.index]
model = HistGradientBoostingRegressor(random_state=0)

def cv_mae(splitter):
    errors = []
    for tr, te in splitter.split(X):
        fit = model.fit(X.iloc[tr], target.iloc[tr])
        errors.append(np.abs(fit.predict(X.iloc[te]) - target.iloc[te]).mean())
    return np.array(errors)

shuffled = cv_mae(KFold(5, shuffle=True, random_state=0))
ordered = cv_mae(TimeSeriesSplit(5))
print(f"\nT5 the same model, 5 folds: shuffled KFold MAE {shuffled.mean():.3f} | TimeSeriesSplit MAE {ordered.mean():.3f}")
print(f"   TimeSeriesSplit fold by fold: {np.round(ordered, 3)}")

features = X.assign(trailing6=y.shift(1).rolling(6).mean(), centred6=y.rolling(6, center=True).mean()).dropna()
tr, te = features.index < "2010-05-01", features.index >= "2010-05-01"
for name, cols in (("trailing 6-hour mean (past only)", ["trailing6"]), ("centred 6-hour mean (sees the future)", ["centred6"])):
    use = list(X.columns) + cols
    fit = model.fit(features.loc[tr, use], y[features.index[tr]])
    print(f"\nT6 {name}: test MAE {np.abs(fit.predict(features.loc[te, use]) - y[features.index[te]]).mean():.3f}" if "trailing" in name
          else f"   {name}: test MAE {np.abs(fit.predict(features.loc[te, use]) - y[features.index[te]]).mean():.3f}")

print("\nT7 MAE and MAPE can disagree")
for name, guess in (("training mean", y[:"2010-04-30"].mean()), ("training median", y[:"2010-04-30"].median())):
    print(f"   {name:<16} MAE {np.abs(test - guess).mean():.3f} | MAPE {(np.abs(test - guess) / test).mean():.1%}")
error = test - y.shift(24)[test.index]
ape = np.abs(error) / test
print(f"   'same hour yesterday': over-forecasts are {(error < 0).mean():.0%} of hours but {ape[error < 0].sum() / ape.sum():.0%} of total MAPE")
text
T1 34,589 hours, 421 with no readings at all; filled by time interpolation

T2 baselines on 5,038 test hours (MAE, kW)
   last hour              0.374
   same hour yesterday    0.496
   same hour last week    0.554
   training mean          0.615

T3 autocorrelation: lag 1 0.72, lag 12 0.24, lag 24 0.44, lag 168 0.45

T4 ADF test on daily means: p = 0.0045, yet the mean is 1.50 kW in December and 0.59 kW in August

T5 the same model, 5 folds: shuffled KFold MAE 0.485 | TimeSeriesSplit MAE 0.519
   TimeSeriesSplit fold by fold: [0.713 0.475 0.499 0.486 0.422]

T6 trailing 6-hour mean (past only): test MAE 0.385
   centred 6-hour mean (sees the future): test MAE 0.261

T7 MAE and MAPE can disagree
   training mean    MAE 0.615 | MAPE 113.5%
   training median  MAE 0.554 | MAPE 78.8%
   'same hour yesterday': over-forecasts are 51% of hours but 73% of total MAPE

T1. What do you do about gaps?

Find them before modelling. 421 hours had no readings at all. Here they were filled by interpolating over time, a reasonable choice for short outages in a smooth series. Say what you did and why; for long gaps, or targets like sales where a gap may mean "zero", interpolation could invent data.

T2. What baseline would you compare a forecasting model against?

The naive and seasonal naive forecasts: the last value, or the value at the same point in the previous season (FPP3: simple methods). On the test period, "last hour" scored an MAE of 0.374 kW, "same hour yesterday" 0.496, "same hour last week" 0.554, and the training mean 0.615. Any model must beat these to be worth its complexity.

The follow-up to raise yourself: "last hour" is only available if you forecast one hour ahead. For a day-ahead forecast, the fair baseline is "same hour yesterday". The horizon decides which baseline is legitimate.

T3. What does autocorrelation tell you?

How strongly the series resembles itself at a given lag. Correlation was 0.72 at one hour, fell to 0.24 at twelve hours, and rose again to 0.44 at 24 hours and 0.45 at 168 hours, one week. The peaks at 24 and 168 show daily and weekly cycles, which suggests lag-24 and lag-168 features and seasonal baselines.

T4. Is the series stationary, and does it matter?

Many classical models assume stationarity: constant mean and variance over time. The augmented Dickey-Fuller test on daily means gave p = 0.0045, rejecting a unit root. Yet average use was 1.50 kW in December and 0.59 kW in August. Both are true. ADF tests for one kind of non-stationarity, a unit root, and says little about a regular yearly cycle. Unit root tests rest on different assumptions and can disagree (FPP3: stationarity). Plot the series and the seasonal means instead of trusting one p-value.

T5. Why not use ordinary k-fold cross-validation?

Because shuffled folds let the model train on hours that come after the hours it is tested on. The same gradient-boosting model scored 0.485 with shuffled 5-fold cross-validation and 0.519 with TimeSeriesSplit, which always trains on the past and tests on the next block (scikit-learn: TimeSeriesSplit). The shuffled score is the optimistic one.

Be fair about it: the time-ordered folds also train on less data. The first fold trained on only the earliest sixth of the series and scored 0.713, while later folds scored between 0.42 and 0.50. Report the folds, not just the mean, because they show how error changes as history grows.

T6. How can a feature leak the future?

A centred rolling mean is the classic case. A six-hour average centred on each hour includes the next three hours. With it, test MAE dropped to 0.261, against 0.385 with a trailing six-hour average that uses only past hours. The centred version is not a better model; it is a model that could not exist in production, because at forecast time those future hours are unknown. Any result that looks too good deserves this check: for every feature, could I have computed it at the moment of forecasting?

T7. Why can MAPE mislead?

Two reasons showed up here. First, MAPE can disagree with MAE about which forecast is better: the training median beat the training mean by a small margin on MAE, 0.554 against 0.615, but by a wide one on MAPE, 78.8% against 113.5%. Second, it punishes over-forecasts much harder than under-forecasts. For "same hour yesterday", over-forecasts were 51% of hours but 73% of the total MAPE, because overshooting a small actual value gives a huge percentage, while an under-forecast can never exceed 100%. Hyndman and Athanasopoulos note exactly this heavier penalty on negative errors (FPP3: forecast accuracy). Optimising MAPE pushes forecasts low, which matters if under-forecasting is the expensive mistake.

How to answer time series questions

  • State the forecast horizon first; it decides the baselines and the features.
  • Validate forward in time, and show the folds.
  • Audit every feature for information from after the forecast time.
  • Pick the metric from the cost of errors, not from habit.

The modelling basics are covered in time series forecasting: a beginner-friendly introduction, validation more generally in cross-validation in machine learning, and the wider interview round in data science interview questions and answers. For the statistics side, see statistics interview questions.

What are common time series interview questions?

How to handle missing timestamps, which baselines to use, autocorrelation and seasonality, stationarity and differencing, how to validate a forecasting model, how features can leak future information, and which error metric to choose.

Why is random cross-validation wrong for time series?

Shuffled folds train on observations that come after the ones being tested, so the model effectively sees the future and the score is optimistic. Use time-ordered splits such as an expanding window instead.

What is a seasonal naive forecast?

A forecast that repeats the value from the same point in the previous season, such as the same hour yesterday or the same month last year. It is a strong baseline for seasonal data.

When should I avoid MAPE?

When actual values can be zero or close to zero, when the scale has no natural zero, and when over- and under-forecasts should be penalised equally, because MAPE punishes over-forecasts more.

Forecasting and time series analysis are part of the Data Science course.

Sources

GloryTecks Team

Training & Placement Faculty

The GloryTecks faculty team mentors learners across Data Science, AI and Data Engineering, with a focus on real-time projects and placement readiness in Hyderabad.

Want to master Interview Questions?

Join GloryTecks’ expert-led Data Science training in Hyderabad with real-time projects and 100% placement support.

Explore course