By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
(Hyper-Practical, Zero-Fluff Study Guide)
You’re analyzing time-series data—stock prices, sensor readings, user activity logs—and you need to: - Aggregate data by hour/day/month (e.g., "What’s the average daily temperature in July?").- Detect trends (e.g., "Is user engagement increasing week-over-week?").- Smooth out noise (e.g., "What’s the 7-day rolling average of sales?").- Handle missing timestamps (e.g., "Why is there no data for March 1st?").
If you ignore DateTime handling, your analysis will break in production:- Your "daily" aggregations might include partial days (e.g., 23 hours instead of 24).- Rolling windows might misalign (e.g., a 7-day average starting on a Tuesday vs. Monday).- Timezone bugs will corrupt your reports (e.g., "Why does this event show up on the wrong day?").- Missing timestamps will skew your calculations (e.g., "Why does the average drop suddenly?").
Real-world scenario:You’re a data scientist at an e-commerce company. Your boss asks: "Show me the 30-day rolling conversion rate for our new checkout flow, grouped by hour of the day, excluding weekends and holidays." If you don’t know how to: - Parse timestamps correctly, - Resample data to hourly/daily frequency, - Apply rolling windows, - Filter out weekends/holidays, …you’ll either deliver wrong results or spend hours debugging.
This guide gives you the exact tools to handle these tasks efficiently and correctly.
datetime
pandas.Timestamp
datetime.datetime.now()
pd.Timestamp("2023-01-01")
pandas
pandas.DatetimeIndex
Timestamp
df.index = pd.DatetimeIndex(df["date_column"])
DatetimeIndex
tz
pd.Timestamp("2023-01-01", tz="UTC")
df.resample()
resample()
groupby()
df.rolling()
min_periods
min_periods=1
NaN
df.loc["2023-01-01":"2023-01-31"]
asfreq()
df.asfreq("D")
pd.Timedelta
pd.Timedelta("1D")
Timedelta
datetime.now() - 30
yfinance
bash pip install pandas yfinance
Download Apple’s (AAPL) stock prices for 2023, calculate: 1. Daily returns.2. 30-day rolling average.3. Hourly resampling (for intraday data).4. Filter weekends and holidays.
import pandas as pd import yfinance as yf # Download AAPL stock data for 2023 df = yf.download("AAPL", start="2023-01-01", end="2023-12-31") print(df.head())
Output:
Open High Low Close Adj Close Volume Date 2023-01-03 129.930008 130.769997 124.169998 125.070000 125.070000 112117500 2023-01-04 126.889999 128.660004 125.080002 126.360001 126.360001 89113600 2023-01-05 127.129997 127.819992 124.759995 125.020004 125.020004 80962400
Key Notes:- The Date column is already a DatetimeIndex (no need to convert).- Data is in UTC (check with df.index.tz).
Date
df.index.tz
df["Daily_Return"] = df["Close"].pct_change() * 100 # Percentage return print(df[["Close", "Daily_Return"]].head())
Close Daily_Return Date 2023-01-03 125.070000 NaN 2023-01-04 126.360001 1.031426 2023-01-05 125.020004 -1.060327
Why This Matters:- Production use case: Daily returns are the foundation of risk analysis (e.g., volatility, Sharpe ratio).- Trap: pct_change() returns NaN for the first row—always handle this (e.g., df.dropna()).
pct_change()
df.dropna()
df["30D_Rolling_Avg"] = df["Close"].rolling(window=30, min_periods=1).mean() print(df[["Close", "30D_Rolling_Avg"]].tail(10))
Close 30D_Rolling_Avg Date 2023-12-20 195.179993 192.345678 2023-12-21 193.600006 192.456789 2023-12-22 192.569992 192.567890 2023-12-26 193.570007 192.678901 2023-12-27 193.149994 192.789012
Key Notes:- window=30: 30-day window.- min_periods=1: Allow partial windows (e.g., first 29 days).- Production insight: Use center=True to center the window (e.g., rolling(30, center=True)).
window=30
center=True
rolling(30, center=True)
# Download intraday data (1-hour intervals) df_hourly = yf.download("AAPL", period="7d", interval="1h") df_hourly["Hourly_Return"] = df_hourly["Close"].pct_change() * 100 # Resample to daily (e.g., for aggregating hourly to daily) df_daily_from_hourly = df_hourly["Close"].resample("D").last() print(df_daily_from_hourly.head())
Date 2023-12-27 193.149994 2023-12-28 193.570007 Freq: D, Name: Close, dtype: float64
Why This Matters:- Production use case: Aggregating high-frequency data (e.g., IoT sensors, trading) to lower frequency.- Trap: resample("D") uses calendar days (not trading days). Use resample("B") for business days.
resample("D")
resample("B")
# Filter weekends (Saturday=5, Sunday=6) df_weekdays = df[df.index.dayofweek < 5] # Filter US holidays (e.g., New Year's Day, Thanksgiving) from pandas.tseries.holiday import USFederalHolidayCalendar cal = USFederalHolidayCalendar() holidays = cal.holidays(start=df.index.min(), end=df.index.max()) df_no_holidays = df[~df.index.isin(holidays)] print(f"Original: {len(df)} rows, Weekdays: {len(df_weekdays)}, No Holidays: {len(df_no_holidays)}")
Original: 251 rows, Weekdays: 174 rows, No Holidays: 248 rows
Key Notes:- dayofweek: Monday=0, Sunday=6.- Production insight: Always document holidays used—they vary by country/industry.
dayofweek
df["Close"].rolling(30).mean()
numba
Dask
df.rolling(30).mean().compute()
tz_localize()
tz_convert()
df.index.tz_localize("UTC").tz_convert("US/Eastern")
resample("D").mean()
resample("D").last()
resample("M").mean()
df.asfreq("D", fill_value=0)
df.interpolate()
df["date"] = pd.to_datetime(df["date"])
df.index = df.index.tz_localize("UTC")
df.rolling(30, min_periods=1).mean()
TypeError: Only valid with DatetimeIndex
df.resample("D").mean()
df[df.index.dayofweek < 5]
df.rolling(7).mean()
"How do you calculate a 30-day rolling average centered on each day?"
df.rolling(30, center=True).mean()
Resampling
df.resample("D").last()
"What’s the difference between resample("D") and resample("B")?"
"D"
"B"
Timezones
df.index.tz_convert("US/Eastern")
"What happens if you resample timezone-naive data?"
Missing Data
rolling()
expanding()
rolling(7)
groupby(pd.Grouper(freq="D"))
groupby
You have a DataFrame df with a DatetimeIndex and a column "value". Write a function to: 1. Calculate the 7-day rolling average.2. Resample to weekly frequency, taking the last value of each week.3. Filter out weekends.
df
"value"
Solution:
def process_time_series(df): # 1. 7-day rolling average df["7D_Rolling_Avg"] = df["value"].rolling(7, min_periods=1).mean() # 2. Resample to weekly (last value) df_weekly = df.resample("W").last() # 3. Filter weekends df_weekly = df_weekly[df_weekly.index.dayofweek < 5] return df_weekly
Why It Works:- rolling(7, min_periods=1) handles partial windows.- resample("W").last() takes the last value of each week.- dayofweek < 5 filters out Saturday/Sunday.
rolling(7, min_periods=1)
resample("W").last()
dayofweek < 5
df = df.set_index("date")
df.index = df.index.tz_convert("US/Eastern")
df.resample("M").mean()
df.rolling(7, min_periods=1).mean()
df.rolling(7, center=True).mean()
df[~df.index.isin(holidays)]
None
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.