The request

From Jordan Reyes, Head of Marketing
Your goal
Count orders per day (all statuses, every calendar day). Set result to a DataFrame with columns order_date (the day), n_orders (orders that day) and avg_7d (mean of n_orders over that day and the 6 days before it, rounded to 2), for the days 2025-11-01 to 2025-12-31 only (61 rows), sorted by order_date ascending, index reset. The first rows of November must use the October days before them, not NaN.
- Use the
ordersDataFramenot done yet - Show exactly
order_daten_ordersavg_7dnot done yet - 61 rows, sorted as askednot done yet
Your code
Loading the editor…
Reference solution
| order_id | customer_id | order_date | status | channel |
|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace |
Mote checks your result
Press Run. Each row that matches the goal becomes a firefly in your lantern.
What Jordan gets, and why
DataFrames
Loaded for you as pandas DataFrames, plus pd and np.
orders12,000 rows · 7 columns
order_idintegercustomer_idintegerorder_datetimestampstatusvarcharchannelvarcharshipping_feedecimalcoupon_codevarchar
| order_id | customer_id | order_date | status | channel | shipping_fee | coupon_code |
|---|---|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web | 0.00 | NaN |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web | 0.00 | NaN |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace | 4.99 | WELCOME10 |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace | 4.99 | WELCOME10 |
| 1005 | 82 | 2023-01-02 11:43:36 | completed | web | 0.00 | WELCOME10 |
customers2,018 rows · 9 columns
customer_idintegerfirst_namevarcharlast_namevarcharemailvarcharcityvarcharstatevarcharsignup_datedatesegmentvarcharreferral_sourcevarchar
| customer_id | first_name | last_name | city | state | signup_date | segment | referral_source | |
|---|---|---|---|---|---|---|---|---|
| 1 | Owen | Hudson | owen.hudson@icloud.com | San Francisco | CA | 2022-06-02 | consumer | search |
| 2 | Douglas | Mendoza | dmendoza69@gmail.com | Atlanta | GA | 2022-06-02 | consumer | NaN |
| 3 | Henry | Brooks | hbrooks@lakesidecafe.com | Los Angeles | CA | 2022-06-04 | business | NaN |
| 4 | Brian | Graham | bgraham@bluecedarhomes.com | Seattle | WA | 2022-06-06 | business | |
| 5 | Kyle | Jimenez | kjimenez27@yahoo.com | Indianapolis | IN | 2022-06-07 | consumer | NaN |
products120 rows · 8 columns
product_idintegernamevarcharcategoryvarcharsubcategoryvarcharunit_pricedecimalunit_costdecimallaunched_ondateis_activeboolean
| product_id | name | category | subcategory | unit_price | unit_cost | launched_on | is_active |
|---|---|---|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 | NaN | 2023-09-11 | true |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 | 503.50 | 2024-05-16 | true |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 | 429.87 | 2023-05-27 | true |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.00 | 214.70 | 2022-12-20 | true |
| 105 | Avery Leather Bed Frame | Furniture | Beds | 449.00 | 232.70 | 2021-08-31 | true |
order_items30,338 rows · 6 columns
order_item_idintegerorder_idintegerproduct_idintegerquantityintegerunit_pricedecimaldiscount_pctdecimal
| order_item_id | order_id | product_id | quantity | unit_price | discount_pct |
|---|---|---|---|---|---|
| 1 | 1001 | 121 | 9 | 31.99 | 0.00 |
| 2 | 1001 | 154 | 3 | 11.99 | 0.00 |
| 3 | 1002 | 154 | 4 | 11.99 | 0.00 |
| 4 | 1002 | 194 | 1 | 149.00 | 0.00 |
| 5 | 1002 | 193 | 2 | 19.99 | 0.00 |
returns1,673 rows · 5 columns
return_idintegerorder_item_idintegerreturned_ondatereasonvarcharrefund_amountdecimal
| return_id | order_item_id | returned_on | reason | refund_amount |
|---|---|---|---|---|
| 1 | 14 | 2023-01-10 | damaged | 83.69 |
| 2 | 42 | 2023-01-10 | wrong_item | 19.99 |
| 3 | 105 | 2023-01-14 | wrong_item | 10.99 |
| 4 | 24 | 2023-01-16 | changed_mind | 26.99 |
| 5 | 126 | 2023-01-16 | late | 20.99 |
employees60 rows · 8 columns
employee_idintegerfirst_namevarcharlast_namevarchardepartmentvarchartitlevarcharmanager_idintegerhire_datedatesalaryinteger
| employee_id | first_name | last_name | department | title | manager_id | hire_date | salary |
|---|---|---|---|---|---|---|---|
| 1 | Catherine | Hale | Executive | Chief Executive Officer | NaN | 2016-03-01 | 285000 |
| 2 | Robert | Kim | Executive | Chief Operating Officer | 1 | 2017-01-09 | 235000 |
| 3 | Megan | Collins | Sales | Head of Sales | 1 | 2018-04-16 | 172000 |
| 4 | Chloe | Gutierrez | Sales | Account Executive | 3 | 2020-01-21 | 72000 |
| 5 | Frank | Bell | Sales | Account Executive | 3 | 2023-05-21 | 73000 |
web_sessions40,000 rows · 7 columns
session_idintegercustomer_idintegerstarted_attimestampdevicevarcharsourcevarcharpages_viewedintegerconvertedboolean
| session_id | customer_id | started_at | device | source | pages_viewed | converted |
|---|---|---|---|---|---|---|
| 1 | NaN | 2023-01-01 23:02:24 | mobile | paid | 1 | false |
| 2 | 18 | 2023-01-01 15:07:49 | desktop | paid | 1 | false |
| 3 | NaN | 2023-01-01 16:55:46 | desktop | direct | 7 | false |
| 4 | NaN | 2023-01-01 12:43:28 | mobile | organic | 3 | false |
| 5 | NaN | 2023-01-01 13:06:21 | mobile | social | 2 | false |
marketing_spend3,276 rows · 3 columns
spend_datedatechannelvarcharamountdecimal
| spend_date | channel | amount |
|---|---|---|
| 2023-01-01 | paid | 492.99 |
| 2023-01-01 | 37.38 | |
| 2023-01-01 | social | 200.53 |
| 2023-01-02 | paid | 709.13 |
| 2023-01-02 | 64.13 |
The lesson
Why smooth a daily series
Daily numbers are noisy. Harbor & Pine’s orders swing with the day of the week, with paydays and with promotions, so a daily chart looks like a seismograph. A moving average (also called a rolling average) replaces each day with the mean of a window of days ending on it. A 7-day window covers every weekday exactly once, so the weekly rhythm cancels out and the trend shows.
rolling(n)
rolling(7) slides a window of 7 rows along the series; the aggregation after it runs on every
window:
daily = orders.set_index("order_date").resample("D").size()
daily.head(8).tolist()
# [1, 8, 6, 4, 10, 9, 5, 8]
daily.rolling(7).mean().round(2).head(8).tolist()
# [nan, nan, nan, nan, nan, nan, 6.14, 7.14]
The 7th value, 6.14, is the mean of the first seven days (43 orders / 7). The first six values are
NaN because a full window of 7 rows doesn’t exist yet. If you’d rather get a value from the first
day on, pass min_periods: rolling(7, min_periods=1) averages whatever rows are available, so
the first three values become 1.0, 4.5 and 5.0. That’s convenient but misleading at the start of a
chart, which is why the default is strict.
.sum(), .max(), .median() and .std() work after rolling too. A rolling 7-day sum is
“orders in the last week”, another common dashboard number.
The window counts rows, not days. That’s why the daily series comes from resample("D"): it has
exactly one row per calendar day, zeros included, so 7 rows really are 7 days. On a series with
missing days you’d use a time-based window like rolling("7D") instead.
Window first, filter second
Jordan only wants November and December. If you filter first, the window has nothing to look back on:
daily.loc["2025-11-01":].rolling(7).mean().head(7) # six NaN, then 17.71
Compute the rolling mean on the full history and cut the date range at the very end. Then 1 November 2025 averages 26 October to 1 November: 14.29.
What the holiday season looks like
On Black Friday, 28 November 2025, orders jump from 24 to 56. The daily count spikes for four days (56, 51, 58, 67) and drops back to 24 on 2 December, but the 7-day average keeps climbing for a few days, because the spike is still inside the window. It peaks at 44.14 on 4 December, the last day whose week still contains the whole Black Friday weekend and Cyber Monday. A moving average always lags: it tells you the level of the last week, not of today.
Common mistakes
- Filtering the date range before rolling, which leaves NaN at the start of the period.
- Rolling over raw orders instead of a daily series: the window is 7 orders, not 7 days.
- Using
min_periods=1without saying so, which makes the first days look calmer than they were. - Reading the peak of a moving average as the peak day. It lags the real spike.
Lantern lit!
Practised: rollingmoving averageresample dailywindowmin periods
- Solved
- No hints
- First run
