

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 9
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
Growth rates show how quickly your numbers are changing over time. Pandas has built-in methods for both cumulative totals and percentage changes.
The cumsum() gives a running total:
events["date"] = events["timestamp"].dt.date
daily_signups = events[events["event_type"] == "signup"].groupby("date").size()
cumulative_signups = daily_signups.cumsum()
print(cumulative_signups)
Which prints something like:
date
2024-01-01 12
2024-01-02 25
2024-01-03 40
2024-01-04 54
2024-01-05 70
2024-01-06 88
dtype: int64
This shows total signups over time. It's useful for milestone tracking ("When did we hit 10,000 users?") and bragging on social media because the line can only go up.
The pct_change() method calculates the percentage change from one period to the next:
daily_users = events.groupby("date")["user_id"].nunique().asfreq("D", fill_value=0)
dod_growth = daily_users.pct_change()
print(dod_growth)
Which prints something like:
date
2024-01-01 NaN
2024-01-02 0.044643
2024-01-03 0.051282
2024-01-04 0.024390
2024-01-05 0.047619
2024-01-06 0.045455
2024-01-07 0.021739
2024-01-08 0.063830
2024-01-09 0.026667
Name: user_id, dtype: float64
A value of 0.044643 means 4.46% growth from the previous day. A value of -0.10 would mean a 10% decline.
Day-over-day growth is almost always noisy and hard to act on. I rarely report it directly. Week-over-week on a 7-day rolling average is much more stable and useful for decision-making.
Once daily_users is sorted with one value per calendar day, you can use pct_change(periods=7) to compare each day to the same day last week:
wow_growth = daily_users.pct_change(periods=7)
Which prints something like:
date
2024-01-01 NaN
2024-01-02 NaN
2024-01-03 NaN
2024-01-04 NaN
2024-01-05 NaN
2024-01-06 NaN
2024-01-07 NaN
2024-01-08 0.339286
2024-01-09 0.316239
2024-01-10 0.268293
2024-01-11 0.285714
2024-01-12 0.234848
2024-01-13 0.210145
2024-01-14 0.212766
2024-01-15 -0.280000
This naturally removes day-of-week effects. Tuesday gets compared to last Tuesday, not Monday.
Be careful with pct_change() when the base value is very small. Going from 2 users to 4 is a 100% increase, but it doesn't mean much.
Complete the calculate_growth_rate function. It accepts an events DataFrame with daily timestamp values and a user_id column. Return a per-day DataFrame with growth metrics.