La solicitud

De Priya Shah, Directora de Datos
Tu objetivo
Los pedidos registrados tienen status "completed" o "refunded". Para cada cliente, el trimestre 0 es el trimestre de su primer pedido registrado; el trimestre q es q trimestres después. Un cliente está activo en el trimestre q si tiene un pedido registrado en él. Asigna a result un DataFrame con una fila por cada q de 1 a 8 y las columnas quarter (q), cohorts (cuántos trimestres de cohorte han alcanzado q hasta 2025Q4), customers (clientes de esas cohortes) y retention_pct (clientes activos en el trimestre q × 100 / customers, redondeado a 1), ordenado por quarter, con índice por defecto.
- Usa el DataFrame
customerspendiente - Usa el DataFrame
orderspendiente - Muestra exactamente
quartercohortscustomersretention_pctpendiente
The lower line divides by every customer, including those whose quarter q has not happened yet.
Ver los números
| Quarters since first order | Cohorts that reached it | Every customer (biased) |
|---|---|---|
| 1 | 44.9% | 38.3% |
| 2 | 46% | 35.5% |
| 3 | 42.5% | 29.4% |
| 4 | 40.9% | 25.9% |
| 5 | 39.7% | 20.3% |
| 6 | 41% | 18.4% |
| 7 | 40.2% | 15.6% |
| 8 | 36.2% | 12% |
Tu código
Cargando el editor…
Solución de referencia
| customer_id | first_name | last_name | city | |
|---|---|---|---|---|
| 1 | Owen | Hudson | owen.hudson@icloud.com | San Francisco |
| 2 | Douglas | Mendoza | dmendoza69@gmail.com | Atlanta |
| 3 | Henry | Brooks | hbrooks@lakesidecafe.com | Los Angeles |
| 4 | Brian | Graham | bgraham@bluecedarhomes.com | Seattle |
Mote revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Lo que recibe Priya, y por qué
DataFrames
Cargados como DataFrames de pandas, junto con pd y np.
customers2,018 filas · 9 columnas
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 |
orders12,000 filas · 7 columnas
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 |
products120 filas · 8 columnas
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 filas · 6 columnas
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 filas · 5 columnas
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 filas · 8 columnas
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 filas · 7 columnas
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 filas · 3 columnas
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 |
La lección
De una tabla a una curva
Una tabla de cohortes tiene una fila por cohorte y una columna por periodo, que es demasiado para una diapositiva de junta. Una curva de retención la comprime en una sola línea: para cada número de trimestres desde el primer pedido, ¿qué proporción de clientes hizo un pedido en ese trimestre?
El trimestre 0 es el primer pedido en sí, así que siempre es 100% y se deja fuera. El trimestre 1 es el siguiente, el trimestre 2 el que sigue, y así sucesivamente. Un cliente cuenta como activo en un trimestre si tiene al menos un pedido registrado en él. No tiene que estar activo en todos los trimestres intermedios, por eso la curva puede subir del trimestre 1 al 2.
Los números de trimestre facilitan la aritmética
Numera los trimestres en orden, 2023Q1 = 0 hasta 2025Q4 = 11:
qi = (booked["order_date"].dt.year - 2023) * 4 + booked["order_date"].dt.quarter - 1
La cohorte de un cliente es su menor qi; la distancia de cada pedido a ella es una simple resta:
first = b.groupby("customer_id")["qi"].min().rename("c")
b = b.join(first, on="customer_id")
b["q"] = b["qi"] - b["c"]
Censura por la derecha: cuenta solo a quienes pudieron volver
La cohorte 2025Q4 aún no tiene trimestre 1. La cohorte 2025Q1 tiene los trimestres 1 a 3 y nada después. Si divides la actividad del trimestre 8 entre todos los clientes, esos clientes jóvenes quedan en el denominador sin posibilidad de estar en el numerador, y la curva se dobla hacia abajo por una razón que nada tiene que ver con que los clientes se vayan.
La solución: para el trimestre q, el denominador son solo los clientes cuya cohorte está al menos q trimestres antes del último trimestre de los datos:
fair = first[first + q <= last_q]
El gráfico muestra las dos versiones. La línea honesta se aplana cerca del 40%. La línea sesgada cae casi en línea recta, y cada punto de esa caída es el calendario que se acaba.
Agrupada, no promediada
Esta curva agrupa clientes: los clientes activos de todas las cohortes justas entre todos los clientes de ellas. Promediar en cambio la tasa de cada cohorte da a la cohorte 2023Q3 de 97 clientes el mismo peso que a la 2023Q4 de 181. Ambas son defendibles, pero di cuál usaste, porque no coincidirán.
Errores comunes
- Todos los clientes en el denominador. La curva se hunde porque se acabó el tiempo, no porque se fueran los clientes.
- Olvidar lo delgada que es la cola. El trimestre 8 descansa en cuatro cohortes. Muestra la base.
- Leer la primera cohorte como clientes nuevos. 2023Q1 incluye a personas que eran habituales antes de que empiecen los datos, y está en cada punto de la curva.
¡Linterna encendida!
Practicaste: retention curvecohortright censoringperiodpooled rate
- Resuelto
- Sin pistas
- Al primer intento
