La solicitud

De Laura Bennett, Directora de Finanzas
Tu objetivo
El starter se ejecuta pero rellena unit_cost ausente con 0. Corrígelo: calcula cost_ratio = unit_cost / unit_price, rellena los valores ausentes de cost_ratio con la mediana de cost_ratio de la categoría del producto (groupby + transform('median')), y asigna margin_pct = 1 - cost_ratio. Asigna a result un DataFrame con las columnas category, n_products (productos por categoría, se conservan los 120) y avg_margin (media de margin_pct, redondeada a 3), ordenado por avg_margin descendente y luego por category ascendente, con el índice reiniciado.
- Usa el DataFrame
productspendiente - Muestra exactamente
categoryn_productsavg_marginpendiente - 6 filas, ordenadas como se pidependiente
Tu código
Cargando el editor…
Solución de referencia
| product_id | name | category | subcategory | unit_price |
|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.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.
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 |
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 |
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
Por qué 0 es el relleno equivocado
Nueve productos no tienen unit_cost (NaN). Un coste ausente significa “no lo sabemos”, no
“gratis”. fillna(0) convierte “no lo sabemos” en “no cuesta nada”, y la fórmula del margen da
entonces a esos productos el 100 %. Cinco de los nueve son Furniture (el Vale Velvet Loveseat, el
Tidewater Teak Loveseat, el Weston Ash Bed Frame, el Alder Linen Sideboard y el Sable Oak Daybed), así
que la media de Furniture saltó al 65,8 % y a lo más alto de la lista. Laura conocía el negocio lo
bastante bien como para ver que eso era imposible. Esa es la mejor clase de comprobación.
Rellena con la mediana del grupo: transform
Laura pidió una estimación a partir de productos similares. Los costes varían enormemente en dólares, así que rellena la razón de coste (el coste como proporción del precio), que es comparable entre productos de una categoría:
products["cost_ratio"] = products["unit_cost"] / products["unit_price"]
products.groupby("category")["cost_ratio"].median()
# Furniture 0.476, Outdoor 0.445, Lighting 0.437, Decor 0.434, Kitchen 0.428, Textiles 0.416
agg o median() tras un groupby devuelve una fila por categoría. Para rellenar una columna
necesitas la mediana de la categoría en cada fila de producto, alineada con la tabla. Eso es lo que
hace transform: calcula por grupo y difunde la respuesta a cada fila del grupo, conservando el
índice original.
category_median = products.groupby("category")["cost_ratio"].transform("median")
products["cost_ratio"] = products["cost_ratio"].fillna(category_median)
fillna con una Series rellena cada hueco con el valor de la misma etiqueta de índice, así que cada
loveseat recibe la mediana de Furniture y cada parrilla la de Outdoor. La mediana ignora los NaN que está reemplazando.
El informe corregido
Kitchen lidera ahora con el 57,5 % y Furniture es la última con el 53,9 %, lo que coincide con lo que ve finanzas. Los 120 productos permanecen en el informe, 20 por categoría. Simplemente descartar los nueve también daría una clasificación sensata, pero con solo 15 productos de Furniture, y Laura pidió conservarlos.
Lighting (55,8 %) y Outdoor (55,7 %) están cerca. Antes de redondear están lo bastante separadas, pero el desempate por categoría en el orden mantiene fijo el orden pase lo que pase con los datos el mes que viene.
Errores comunes
fillna(0)en un coste, precio o salario. Cero es un valor real, no “desconocido”.- Usar
.agg("median")o.median()en lugar detransform, y luego intentar rellenar con una tabla de seis filas. - Rellenar con la mediana de toda la columna, que ignora cómo difieren las categorías.
- Rellenar
unit_costcon la mediana del coste en dólares de la categoría, lo que da al Alder Linen Sideboard de $259 el coste típico de un sofá o una cama mucho más caros.
¡Linterna encendida!
Practicaste: fillnatransformgroupbymediannandebugging
- Resuelto
- Sin pistas
- Al primer intento
