Monthly revenue per country, counting paid orders only
df has columns country, order_ts, amount, status. Compute monthly revenue per country, summing amount for status == 'paid' rows only — in a single groupby, without pre-filtering the frame.
import pandas as pd
def monthly_paid_revenue(df: pd.DataFrame) -> pd.DataFrame:
# your code here
Write the implementation.
Mask the unpaid amounts to zero, then group once. Build paid = df['amount'].where(df['status'].eq('paid'), 0), derive the month from order_ts, and sum: df.assign(paid=paid, m=df['order_ts'].dt.to_period('M')).groupby(['country','m'])['paid'].sum(). The where keeps every row so one pass covers all months.
- ✗Filtering paid rows so months with no paid orders vanish from the output
- ✗Forgetting to derive a month period from order_ts before grouping
- ✗Counting rows instead of summing the amount column
- →How would you keep months with zero paid revenue in the result?
- →Why prefer where-masking over filtering rows before the groupby?
Turn the condition into a masked column, then do one grouped sum. where replaces unpaid amounts with 0 but keeps every row, so no month is silently dropped.
import pandas as pd
def monthly_paid_revenue(df: pd.DataFrame) -> pd.DataFrame:
paid = df['amount'].where(df['status'].eq('paid'), 0)
m = df['order_ts'].dt.to_period('M')
return (df.assign(paid=paid, m=m)
.groupby(['country', 'm'])['paid']
.sum()
.reset_index(name='revenue'))
Pre-filtering with df[df.status == 'paid'] gives the same numbers but drops any country-month that had zero paid orders — masking keeps those rows at 0.