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
Last updated: 8 October 2026
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.
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")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 MAPET1. 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?
Why is random cross-validation wrong for time series?
What is a seasonal naive forecast?
When should I avoid MAPE?
Forecasting and time series analysis are part of the Data Science course.
Sources
- Some simple forecasting methods (Forecasting: Principles and Practice, 3rd ed.) — Rob J Hyndman and George Athanasopoulos
- Evaluating point forecast accuracy (Forecasting: Principles and Practice, 3rd ed.) — Rob J Hyndman and George Athanasopoulos
- Stationarity and differencing (Forecasting: Principles and Practice, 3rd ed.) — Rob J Hyndman and George Athanasopoulos
- TimeSeriesSplit (scikit-learn documentation) — scikit-learn
- Individual Household Electric Power Consumption (UCI Machine Learning Repository) — UCI Machine Learning Repository
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.
Related articles
SQL Interview Questions: Top 50 with Answers
Fifty SQL interview questions with answers checked on PostgreSQL, DuckDB and SQLite against one small practice schema: evaluation order, NULL logic, joins and fan-out, window functions, dates, and performance, including where the three engines disagree.
Python Interview Questions for Data Roles
The plain-Python coding tasks data-analyst and data-engineer interviews use, without pandas: counting, deduplicating, grouping, streaming large files, flattening JSON, joining, and the bugs interviewers plant. Each has a worked solution and the follow-up questions to expect.
Data Science Interview Questions and Answers 2026
A data science interview is several interviews in one: statistics, machine learning, coding, product sense and a take-home. This guide maps each round with model answers, then works a churn take-home on real telecom data, including the checks that separate a strong submission from a high score.