Chapter 17 Dates and Basic Time-Series Operations
Dates require explicit types and ordering. String dates may sort incorrectly, and time-based calculations are unreliable when rows are unsorted or time zones are mixed.
17.1 Create and parse dates
import pandas as pd
daily_index = pd.date_range(start="2026-01-01", periods=4, freq="D")
assert daily_index[0] == pd.Timestamp("2026-01-01")
assert daily_index.freqstr == "D"Use an explicit format for known input formats:
17.2 Sort before calculating changes
diff() computes the change from the previous row in the current order. Sort
by entity and time before using it on panel data.
revenue = pd.DataFrame(
{
"date": pd.to_datetime(["2026-01-01", "2026-01-02", "2026-01-03"]),
"revenue": [100.0, 120.0, 90.0],
}
).sort_values("date")
revenue["daily_change"] = revenue["revenue"].diff()
revenue["growth_rate"] = revenue["revenue"].pct_change()
assert pd.isna(revenue.loc[0, "daily_change"])
assert revenue.loc[1, "daily_change"] == 20.0
assert round(revenue.loc[1, "growth_rate"], 2) == 0.20The first difference is missing because no prior observation exists. Decide whether to retain that missing value or define a domain-specific baseline; do not automatically replace it with zero.
17.3 Grouped differences
For multiple entities, calculate changes within each entity rather than across adjacent rows belonging to different groups.
panel = pd.DataFrame(
{
"customer_id": [1, 1, 2, 2],
"date": pd.to_datetime(["2026-01-01", "2026-02-01"] * 2),
"spend": [10, 15, 20, 18],
}
).sort_values(["customer_id", "date"])
panel["spend_change"] = panel.groupby("customer_id")["spend"].diff()
assert panel["spend_change"].tolist()[1] == 5
assert panel["spend_change"].tolist()[3] == -217.4 Resampling requires a time index
daily = pd.Series(
[10, 20, 30, 40],
index=pd.date_range("2026-01-01", periods=4, freq="D"),
)
two_day_totals = daily.resample("2D").sum()
assert two_day_totals.tolist() == [30, 70]Aggregation frequency changes the unit of analysis. State whether a result is a daily sum, monthly average, end-of-period value, or another defined measure.
17.5 Interview checklist
- Are values true datetimes or only strings?
- Are entity and time ordering explicit?
- Should differences be calculated within groups?
- What does the first missing difference mean?
- Does resampling use the correct aggregation and frequency?
- Could future information enter a feature through a centered or forward-looking window?