Python · medium
Asked in Data Scientist interviews, in the Python round.
df['ma'] = df['x'].rolling(30).mean().
The one-liner is rolling(30).mean(), and the interview is about whether "30" means rows or days.
df = df.sort_values("date")
df["ma_30_rows"] = df["x"].rolling(30).mean() # last 30 rows
df["ma_30_days"] = (
df.set_index("date")["x"].rolling("30D").mean().to_numpy() # last 30 calendar days
)
rolling(30) is a row window: if a day is missing, it silently reaches further back in time. rolling("30D") on a datetime index is a time window and does the right thing on gaps, but requires the index to be sorted. If the frame has one row per entity per day, add groupby("entity_id") before the rolling so windows do not bleed across entities.
Two details interviewers ask about: min_periods (the first 29 rows are NaN by default; min_periods=1 gives a partial average instead), and center=True for a symmetric smoothing window rather than a trailing one. Say which the use case wants; a dashboard's "trailing 30-day" is the trailing one.