Typorithm · medium

Daily grids and rolling-window meaning

pythonpandasnumerical-computingindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Daily grids and rolling-window meaning

0%

Concept and contract

Complete an observed calendar range before computing a daily rolling mean.

A rolling three-row mean is not necessarily a rolling three-day mean. Missing dates, duplicates and unsorted rows can make those interpretations diverge. First define what an absent day means. In this lesson, the supplied event-count feed is declared complete between its first and last observed dates, so an absent date means zero observed events in that interval. This assumption would be inappropriate for an incomplete measurement feed.

The worked function validates unique daily keys, completes the UTC daily grid, fills only the newly absent event-count days with zero and computes a three-day rolling mean. The first two windows remain unavailable because min_periods requires all three days.

Mechanism and worked example

Parse strict YYYY-MM-DD keys as UTC midnight instants and reject duplicate days or negative/non-integer counts.

Parse strict YYYY-MM-DD keys as UTC midnight instants and reject duplicate days or negative/non-integer counts. Sort by date, construct date_range from the endpoints and reindex the event Series onto that complete grid. Only then apply rolling(window=3, min_periods=3). Return formatted UTC days, nullable integer event counts and nullable floating means.

Trace counts three on November first and six on November third. The completed second day has zero events. The third day's mean is three, based on three, zero and six. A direct rolling calculation on the two original rows cannot express that daily population.

Complete worked example

python

import pandas as pd

def inspect_example(rows):
    if any(type(r.get("events")) is not int or r["events"] < 0 for r in rows):
        raise ValueError("nonnegative whole counts required")
    frame = pd.DataFrame(rows, columns=["day", "events"])
    dates = pd.to_datetime(frame["day"], format="%Y-%m-%d", utc=True, errors="raise")
    if dates.duplicated().any():
        raise ValueError("duplicate day")
    counts = pd.Series(pd.array(frame["events"], dtype="Int64"), index=dates).sort_index()
    if len(counts):
        counts = counts.reindex(pd.date_range(counts.index.min(), counts.index.max(), freq="D"), fill_value=0)
    mean = counts.rolling(window=3, min_periods=3).mean()
    return pd.DataFrame({"day": counts.index.strftime("%Y-%m-%d"), "events": counts.to_numpy(), "mean": mean.to_numpy()}).astype({"day": "string", "events": "Int64", "mean": "Float64"})
Reasoning
Parse strict YYYY-MM-DD keys as UTC midnight instants and reject duplicate days or negative/non-integer counts. Sort by date, construct date_range from the endpoints and reindex the event Series onto that complete grid. Only then apply rolling(window=3, min_periods=3). Return formatted UTC days, nullable integer event counts and nullable floating means. Trace counts three on November first and six on November third. The completed second day has zero events. The third day's mean is three, based on three, zero and six. A direct rolling calculation on the two original rows cannot express that daily population.
Open in local Python playground ↗

Focused decision: context is in the complete example

python

if len(counts):
    counts = counts.reindex(pd.date_range(counts.index.min(), counts.index.max(), freq="D"), fill_value=0)
mean = counts.rolling(window=3, min_periods=3).mean()
Focused decision
Type this short table decision after reading its complete context. The complete imports, table construction, validation, and result checks remain in the worked example. Typing records practice; only the downloadable computer lab executes Python.

Counterexamples and common mistakes

The controlled mistake reduces min_periods to one.

The controlled mistake reduces min_periods to one. It reports partially observed early windows as though they met the complete-window contract. Another mistake applies rolling before reindexing, turning a number of sparse observations into a misleading number of calendar days. A third fills missing measurement values without establishing whether the feed is complete, conflating absent reporting with observed zero events.

For irregular timestamps, time-offset windows such as rolling("3D") have their own endpoint and inclusion rules. They are useful, but not interchangeable with the completed daily-grid contract taught here. State the interval semantics rather than choosing syntax that merely returns a number.

Controlled mistake: inspect the failing table contract

python

import pandas as pd

def inspect_example(rows):
    if any(type(r.get("events")) is not int or r["events"] < 0 for r in rows):
        raise ValueError("nonnegative whole counts required")
    frame = pd.DataFrame(rows, columns=["day", "events"])
    dates = pd.to_datetime(frame["day"], format="%Y-%m-%d", utc=True, errors="raise")
    if dates.duplicated().any():
        raise ValueError("duplicate day")
    counts = pd.Series(pd.array(frame["events"], dtype="Int64"), index=dates).sort_index()
    if len(counts):
        counts = counts.reindex(pd.date_range(counts.index.min(), counts.index.max(), freq="D"), fill_value=0)
    mean = counts.rolling(window=3, min_periods=1).mean()
    return pd.DataFrame({"day": counts.index.strftime("%Y-%m-%d"), "events": counts.to_numpy(), "mean": mean.to_numpy()}).astype({"day": "string", "events": "Int64", "mean": "Float64"})
Reasoning
The controlled mistake reduces min_periods to one. It reports partially observed early windows as though they met the complete-window contract. Another mistake applies rolling before reindexing, turning a number of sparse observations into a misleading number of calendar days. A third fills missing measurement values without establishing whether the feed is complete, conflating absent reporting with observed zero events. For irregular timestamps, time-offset windows such as rolling("3D") have their own endpoint and inclusion rules. They are useful, but not interchangeable with the completed daily-grid contract taught here. State the interval semantics rather than choosing syntax that merely returns a number.
Open in local Python playground ↗

Independent practice

Change the complete rolling window from three days to two days.

Change the complete rolling window from three days to two days. Change both window and min_periods together, preserving the completed grid, zero-event assumption and sorted output. This is a small parameter edit that makes the observation requirement visible.

Predict counts three, zero and six on consecutive days: the first mean remains missing, the second is one-and-a-half and the third is three. The first row must not become a known mean just because the window length changed. Keep the explicit data-completeness assumption in your explanation; the code cannot discover that business fact from a missing date.

Step 1: Compute a complete two-day rolling mean on the same daily grid. Step 2: Retain the working imports, input validation and table schemas. Change the stated policy, run the supplied practice cases, then explain the newly accepted or rejected boundary.

Practice starter: solve before reading the solution

python

import pandas as pd

def inspect_example(rows):
    if any(type(r.get("events")) is not int or r["events"] < 0 for r in rows):
        raise ValueError("nonnegative whole counts required")
    frame = pd.DataFrame(rows, columns=["day", "events"])
    dates = pd.to_datetime(frame["day"], format="%Y-%m-%d", utc=True, errors="raise")
    if dates.duplicated().any():
        raise ValueError("duplicate day")
    counts = pd.Series(pd.array(frame["events"], dtype="Int64"), index=dates).sort_index()
    if len(counts):
        counts = counts.reindex(pd.date_range(counts.index.min(), counts.index.max(), freq="D"), fill_value=0)
    mean = counts.rolling(window=3, min_periods=3).mean()
    return pd.DataFrame({"day": counts.index.strftime("%Y-%m-%d"), "events": counts.to_numpy(), "mean": mean.to_numpy()}).astype({"day": "string", "events": "Int64", "mean": "Float64"})

# Independent task: Compute a complete two-day rolling mean on the same daily grid.
Reasoning
Compute a complete two-day rolling mean on the same daily grid.
Open in local Python playground ↗
  • Hint 1: Find the one field or branch that owns this policy.
  • Hint 2: Compare the first changed acceptance case with the retained baseline.

Solution, tests and trade-offs

The solution changes the two linked window parameters.

The solution changes the two linked window parameters. Acceptance tests sparse daily input, a single day, empty input, duplicated days and invalid counts. Exact missing early means distinguish complete-window behavior from a convenient partial-window calculation. The expected daily grid is listed independently in the fixtures.

Reindexing changes the reporting population by adding declared zero-event days within the interval. It does not add dates before the first or after the last supplied day. A production dashboard should expose its observed range and completeness evidence before presenting this mean as a broader market trend.

Practice solution and acceptance checks

python

import pandas as pd

def inspect_example(rows):
    if any(type(r.get("events")) is not int or r["events"] < 0 for r in rows):
        raise ValueError("nonnegative whole counts required")
    frame = pd.DataFrame(rows, columns=["day", "events"])
    dates = pd.to_datetime(frame["day"], format="%Y-%m-%d", utc=True, errors="raise")
    if dates.duplicated().any():
        raise ValueError("duplicate day")
    counts = pd.Series(pd.array(frame["events"], dtype="Int64"), index=dates).sort_index()
    if len(counts):
        counts = counts.reindex(pd.date_range(counts.index.min(), counts.index.max(), freq="D"), fill_value=0)
    mean = counts.rolling(window=2, min_periods=2).mean()
    return pd.DataFrame({"day": counts.index.strftime("%Y-%m-%d"), "events": counts.to_numpy(), "mean": mean.to_numpy()}).astype({"day": "string", "events": "Int64", "mean": "Float64"})
Reasoning
The solution changes the two linked window parameters. Acceptance tests sparse daily input, a single day, empty input, duplicated days and invalid counts. Exact missing early means distinguish complete-window behavior from a convenient partial-window calculation. The expected daily grid is listed independently in the fixtures. Reindexing changes the reporting population by adding declared zero-event days within the interval. It does not add dates before the first or after the last supplied day. A production dashboard should expose its observed range and completeness evidence before presenting this mean as a broader market trend.
Open in local Python playground ↗

Interview reasoning and next step

Explain why row windows, calendar windows and resampling are different operations.

Explain why row windows, calendar windows and resampling are different operations. State the missing-day policy and min_periods requirement in ordinary language, then calculate the small fixture manually. Describe what changes if the source has reporting gaps rather than a complete event feed. Discuss how window endpoints can affect comparisons across periods.

On the PC, type the completed-grid rolling expression and recall min_periods. In the app, identify which early means are still missing. Next, concatenate batches with an explicit schema and identity check so combined rows do not inherit accidental index collisions or unsupported columns.

Optional stretch — after the core task works: Add one independently reasoned boundary case and explain its expected value before running it.

Computer practice: https://applydjinn.com/typorithm/pandas-lab-20261106.zip. Install pinned dependencies in an isolated Python environment. Run verify.py, then change the working exercise baseline and run --practice pd-windows. The real pandas tables, exact schemas, unchanged inputs, CSV parser options and owned in-memory SQL reconciliation use owned fixtures only. No production database, feed, account or paid service is used. This lab executes Python; the PC typing trainer and native reading progress do not execute it.

Complete an observed calendar range before computing a daily rolling mean.