La solicitud

De Laura Bennett, Directora de Finanzas
Tu objetivo
Paso 1 de 3. Verifica los meses. Para los pedidos hechos del 1 de septiembre al 31 de diciembre de 2025, asigna a result un DataFrame con las columnas month, orders (todos los pedidos), completed, cancelled, refunded y pending (pedidos con cada estado), ordenado por month, con índice por defecto.
- Usa el DataFrame
orderspendiente - Muestra exactamente
monthorderscompletedcancelledrefundedpendingpendiente - 4 filas, ordenadas como se pidependiente
Paso 2 de 3. Construye la tabla de KPI para 2024-11, 2025-10 y 2025-11. Asigna a result un DataFrame con las columnas month, net_revenue (redondeado a 2), orders (pedidos completados distintos con una línea contada), avg_order_value (ingresos / pedidos, redondeado a 2), buyers (clientes distintos que pidieron), new_buyers (compradores cuyo primer pedido completado, de siempre, cae en ese mes), returning_buyers (buyers - new_buyers), refunds (refund_amount de returns, por el mes de returned_on, redondeado a 2) y web_conversion_pct (sesiones convertidas * 100 / todas las sesiones de ese mes, por started_at, redondeado a 2). Ordena por month, con índice por defecto.
- Usa el DataFrame
order_itemspendiente - Usa el DataFrame
returnspendiente - Muestra exactamente
monthnet_revenueordersavg_order_valuebuyersnew_buyersreturning_buyersrefundsweb_conversion_pctpendiente
Paso 3 de 3. Explica la brecha año contra año. Para los pedidos completados (líneas con quantity > 0) de 2024-11 y 2025-11, suma el ingreso neto de cada pedido y luego etiquétalo como size_band 'large' si ese total es 5000 o más, y 'regular' en caso contrario. Asigna a result un DataFrame con las columnas month, size_band, orders, net_revenue (redondeado a 2) y avg_order_value (redondeado a 2), ordenado por month y luego size_band, con índice por defecto.
- Usa el DataFrame
order_itemspendiente - Muestra exactamente
monthsize_bandordersnet_revenueavg_order_valuependiente - 4 filas, ordenadas como se pidependiente
Este caso se desbloquea cuando terminas cualquiera de estos:
La solicitud y la lección ya se pueden leer. Resuelve todos los niveles de uno de esos capítulos, en la ruta que prefieras, y este caso se abre.
Paso 1 · tu código
Cargando el editor…
Solución de referencia
| 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 revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Paso 2 · tu código
Cargando el editor…
Solución de referencia
| order_item_id | order_id | product_id | quantity | unit_price |
|---|---|---|---|---|
| 1 | 1001 | 121 | 9 | 31.99 |
| 2 | 1001 | 154 | 3 | 11.99 |
| 3 | 1002 | 154 | 4 | 11.99 |
| 4 | 1002 | 194 | 1 | 149.00 |
Mote revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Paso 3 · tu código
Cargando el editor…
Solución de referencia
| order_item_id | order_id | product_id | quantity | unit_price |
|---|---|---|---|---|
| 1 | 1001 | 121 | 9 | 31.99 |
| 2 | 1001 | 154 | 3 | 11.99 |
| 3 | 1002 | 154 | 4 | 11.99 |
| 4 | 1002 | 194 | 1 | 149.00 |
Mote revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Lo que recibe Laura, y por qué
DataFrames
Cargados como DataFrames de pandas, junto con pd y np.
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 |
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 |
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 |
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 |
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 |
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 |
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
Qué estás verificando y por qué
Un mes está listo para informarse solo cuando sus pedidos se han asentado. Los pedidos llegan como pending y pasan a
completed, cancelled o refunded en los días siguientes. Una tabulación cruzada de mes
contra estado muestra dónde están los pedidos abiertos:
counts = pd.crosstab(o["month"], o["status"])
Noviembre tiene 2 pedidos pendientes de 715; diciembre tiene 94 de 777. Esa es la evidencia detrás de informar de noviembre.
Una tabla por fuente
Los KPI vienen de tres tablas con tres granularidades: líneas de pedido, devoluciones y sesiones web. El patrón
seguro es llevar cada una a una fila por mes, indexada por mes, y luego aplicar join:
sales = lines.groupby("month").agg(revenue=("revenue", "sum"), orders=("order_id", "nunique"), ...)
refunds = returns.groupby(returns["returned_on"].dt.strftime("%Y-%m"))["refund_amount"].sum()
kpi = sales.join(refunds.rename("refunds")).join(web)
Los compradores nuevos necesitan un paso más. “Nuevo” significa que el primer pedido completado del cliente cae en el
mes. transform("min") pone la fecha del primer pedido de cada cliente en cada una de sus líneas, y
.where() conserva el customer_id solo en las líneas de ese primer mes, así que nunique() del resultado
cuenta los compradores nuevos.
Cómo leer el resultado
| month | net_revenue | orders | avg_order_value | buyers | web_conversion_pct |
|---|---|---|---|---|---|
| 2024-11 | 319,297.22 | 564 | 566.13 | 357 | 3.50 |
| 2025-10 | 174,599.43 | 333 | 524.32 | 261 | 2.33 |
| 2025-11 | 292,364.40 | 651 | 449.10 | 442 | 4.45 |
Frente a octubre todo sube, como cada noviembre. Frente al año pasado, el volumen creció y los ingresos cayeron, así que la pregunta pasa a ser el valor medio del pedido. El paso 3 la responde: siete pedidos voluminosos el noviembre pasado, uno este noviembre.
Explicar el cambio
El paso 3 trabaja a nivel de pedido, porque el tamaño de un pedido solo se conoce una vez que sus líneas se
han sumado. Agrupa las líneas por mes y pedido, etiqueta cada pedido con np.where y luego agrupa los
pedidos por mes y banda. El resultado divide cada noviembre en unos pocos pedidos grandes y muchos regulares,
que es el desglose que convierte “los ingresos cayeron” en una razón sobre la que la dirección puede actuar.
Trampas
groupbysobre una Series calculada (returns["returned_on"].dt.strftime(...)) funciona sin añadir antes una columna; el resultado queda indexado por las etiquetas de mes.- Sumar
buyersentre meses cuenta dos veces a las personas que compraron en ambos. .loc[["2024-11", ...]]lanza unKeyErrorsi falta un mes en una fuente;joinconserva los meses de ventas y deja NaN donde otra fuente no tiene ninguno.
¡Linterna encendida!
Practicaste: data validationgroupbynamed aggregationcrosstabkpi definitionmomyoy
- Resuelto
- Sin pistas
- Al primer intento
