La solicitud

De Daniel Foster, Gerente de producto móvil
Tu objetivo
Paso 1 de 3. Verifica los datos. Para cada canal, cuenta todos los pedidos por estado. Asigna a result un DataFrame con las columnas channel, completed, cancelled, refunded, pending y pending_late (pedidos pendientes hechos el 2025-12-22 o después), ordenado por channel, con índice por defecto. Usa solo la tabla orders.
- Usa el DataFrame
orderspendiente - Muestra exactamente
channelcompletedcancelledrefundedpendingpending_latependiente - 3 filas, ordenadas como se pidependiente
Paso 2 de 3. Mide la mezcla. Usa pedidos completados y líneas con quantity > 0. Para cada año (el año de order_date, como columna year) y canal, calcula el número de pedidos y los ingresos netos. Asigna a result un DataFrame con las columnas year, channel, orders, order_share_pct (la participación del canal en los pedidos de ese año), revenue (redondeado a 2) y revenue_share_pct (su participación en los ingresos de ese año), con las participaciones redondeadas a 1, ordenado por year y luego channel, con índice por defecto.
- Usa el DataFrame
order_itemspendiente - Muestra exactamente
yearchannelordersorder_share_pctrevenuerevenue_share_pctpendiente - 9 filas, ordenadas como se pidependiente
Paso 3 de 3. Separa mezcla de crecimiento. Usa pedidos completados y líneas con quantity > 0. Para cada canal, asigna a result un DataFrame con las columnas channel, orders_2024 y orders_2025, orders_change_pct ((2025 - 2024) * 100 / 2024), aov_2025 (ingresos netos de 2025 por pedido) y shipping_2025 (el shipping_fee promedio de sus pedidos de 2025). Redondea el cambio a 1 y el dinero a 2, ordena por channel, con índice por defecto.
- Usa el DataFrame
orderspendiente - Usa el DataFrame
order_itemspendiente - Muestra exactamente
channelorders_2024orders_2025orders_change_pctaov_2025shipping_2025pendiente
Este caso se desbloquea cuando terminas cualquiera de estos:
- SQL · CASE, fechas y cadenas de texto
- Python · Columnas nuevas, groupby y agregación
- Excel · Tablas dinámicas
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_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.
Lo que recibe Daniel, 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 |
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 |
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
Qué estás verificando y por qué
Antes de medir participaciones, asegúrate de que las dos columnas en las que se apoya el análisis estén limpias: channel y
status. pd.crosstab cuenta cada combinación en una sola llamada:
pd.crosstab(orders["channel"], orders["status"])
Tres cosas que leer en el resultado:
- El número de filas. Una por valor de canal. Una cuarta fila como
Appsignificaría mayúsculas que corregir. - Pedidos pendientes. Daniel advirtió que diciembre no está asentado. La columna extra
pending_latemuestra cuántos de los pedidos pendientes son simplemente recientes. - Cancelaciones por canal. Si un canal canceló mucho más, usar los pedidos completados inclinaría la mezcla. Aquí todos están cerca del 6%.
Asignar una Series a una columna nueva la alinea por el índice, así que late.groupby("channel").size()
cae en las filas correctas aunque se calculó por separado.
Participaciones dentro de cada año
Una participación sobre el total necesita el total del grupo de cada fila a su lado. transform devuelve un resultado de la misma
longitud que la entrada, así que puede ir en una columna nueva:
g["orders"] * 100 / g.groupby("year")["orders"].transform("sum")
Las tres participaciones de cada año suman 100%. Agrega primero por año y canal, y luego divide.
¿Mezcla o crecimiento?
Una participación creciente tiene dos historias posibles. O la app creció mientras los demás se mantenían, o la
app se mantuvo mientras los demás caían. Normalmente es un poco de ambas, y solo los conteos las
distinguen. El paso 3 resume las líneas a pedidos y luego usa pivot_table para poner cada año en su propia
columna, la versión en pandas de COUNT(CASE WHEN year = 2024 ...).
Cómo leer el resultado
| channel | orders_2024 | orders_2025 | orders_change_pct | aov_2025 |
|---|---|---|---|---|
| app | 1239 | 1904 | 53.7 | 523.27 |
| marketplace | 543 | 630 | 16.0 | 515.01 |
| web | 1891 | 1761 | -6.9 | 557.03 |
La tienda creció en 2025 y el marketplace mantuvo el ritmo. La app creció mucho más rápido, y el sitio web se encogió. Los datos no pueden decir qué clientes se pasaron; un seguimiento a nivel de cliente mostraría cuántos compradores web de 2024 pidieron a través de la app en 2025.
Trampas
lines.groupby(...).size()cuenta líneas, no pedidos. Usanuniquesobre order_id o resume primero.- Una participación sin los conteos detrás puede ocultar un mercado que se encoge.
shipping_feees lo que el cliente pagó por la entrega, no la comisión que nos cobra el marketplace.
¡Linterna encendida!
Practicaste: data validationcrosstabgroupbytransformshare of totalyoymix vs growth
- Resuelto
- Sin pistas
- Al primer intento
