

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 6
click for more info
Not enough gems
Cost: 6 gems
1: Event Data
incomplete
2: Event Structure
incomplete
3: Event Counting
incomplete
4: Resample
incomplete
5: Resample Aggregations
incomplete
6: Active Users
incomplete
7: Time Patterns
incomplete
8: Funnel Metrics
incomplete
9: Conversion Rates
incomplete
10: Funnel Drop-Offs
incomplete
11: Ordered Funnels
incomplete
12: Cohorts
incomplete
13: Cohort Retention
incomplete
14: Rolling Metrics
incomplete
15: Growth Rates
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Click to play video
A cohort is a group of users who share a common starting point. Usually it's the day, week, or month they first had an event. Say we want to see how many users from each cohort are still active in later months. We can create a monthly cohort label with dt.to_period(), which converts each timestamp into a pandas Period value like 2024-01:
first_event = events.groupby("user_id")["timestamp"].min().dt.to_period("M")
first_event.name = "cohort"
Then merge it back into the events and calculate how many months have passed since each user's first event:
# Add cohort Series to the events DataFrame
events_c = events.merge(first_event.reset_index(), on="user_id")
# Calculate months since the user's first event
events_c["event_month"] = events_c["timestamp"].dt.to_period("M")
events_c["months_since"] = (
# Subtracting two Period objects returns the time difference
events_c["event_month"] - events_c["cohort"]
).apply(lambda x: x.n) # .n is the number of months in the difference
cohort_table = (
events_c.groupby(["cohort", "months_since"])["user_id"].nunique().unstack()
)
print(cohort_table)
Which prints something like this:
months_since 0 1 2
cohort
2024-01 3 2 2
2024-02 2 1 2
2024-03 1 1 NaN
Which means:
NaN.The unstack() function pivots months_since into columns, so each row is one cohort and each column is a month offset, and fill_value=0 shows 0 instead of NaN for months that never happened.
The retention grid above counts how many users stay active. SnackStack's product team wants the companion view: an engagement grid of how much activity each cohort generates: the total number of events a cohort fires in each month after first activity.
Fix the bug in the build_engagement_grid function so that it shows an engagement grid instead of a retention grid.