La solicitud

De Jordan Reyes, Director de Marketing
Tu objetivo
Conserva solo los pedidos que tienen coupon_code. Asigna coupon_code a una campaña con campaigns (dado) usando Series.map; los códigos que no están en el diccionario pasan a NaN, así que rellénalos con 'Unmapped'. Asigna a result un DataFrame con las columnas campaign y n_orders (pedidos por campaña), ordenado por n_orders descendente, con el índice reiniciado.
- Usa el DataFrame
orderspendiente - Muestra exactamente
campaignn_orderspendiente - 4 filas, ordenadas como se pidependiente
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 Jordan, 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 |
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 |
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
map: busca cada valor en un diccionario
Series.map(d) reemplaza cada valor por d[value]. Es la versión pandas de buscar un código en una
tabla de referencia:
campaigns = {"WELCOME10": "Onboarding", "SPRING15": "Seasonal", "SUMMER15": "Seasonal",
"BFCM25": "Holiday", "HOLIDAY20": "Holiday"}
orders["coupon_code"].map(campaigns).head()
El detalle importante es qué pasa con un valor que no es una clave. Un diccionario normal de Python
lanza KeyError ante una clave ausente; map no. Devuelve NaN en silencio. Los pedidos sin cupón
(NaN en coupon_code) también vuelven como NaN, ya que NaN tampoco es una clave.
Haz visibles los huecos
Harbor & Pine tiene seis códigos de cupón, pero la lista de Jordan tiene cinco. Falta FREESHIP, así que sus pedidos se asignan a NaN:
coupon_orders = orders[orders["coupon_code"].notna()].copy()
mapped = coupon_orders["coupon_code"].map(campaigns)
mapped.isna().sum() # 193, all FREESHIP
Si agrupas ahora, esos 193 pedidos desaparecen, porque groupby deja fuera las claves NaN por
defecto. Los totales sumarían 1.530 en lugar de los 1.723 pedidos que usaron cupón, y nadie sabría
por qué. fillna("Unmapped") convierte el hueco silencioso en una fila que Jordan puede ver y sobre
la que puede actuar.
Por eso filtramos primero a los pedidos con cupón. De lo contrario, los 10.277 pedidos sin ningún cupón también pasarían a NaN y luego a “Unmapped”, mezclando “sin cupón” con “un código que olvidé”.
El resultado
| campaña | n_orders |
|---|---|
| Onboarding | 587 |
| Holiday | 541 |
| Seasonal | 402 |
| Unmapped | 193 |
WELCOME10 por sí solo es el código más usado. Holiday combina BFCM25 (348 pedidos) y HOLIDAY20 (193). Cuando Jordan añada FREESHIP al diccionario, la fila Unmapped desaparecerá, que es exactamente cómo debe comportarse una tabla de consulta. Una conciliación rápida demuestra que no se perdió nada: 587
- 541 + 402 + 193 = 1.723, el número de pedidos con cualquier cupón.
Errores comunes
- Agrupar justo después de
map, de modo que los códigos sin asignar desaparecen de los totales. - Usar
.replace(campaigns)en su lugar: deja sin cambios los códigos desconocidos, así que FREESHIP parecería un nombre de campaña. - Asignar toda la tabla
orders, de modo que “sin cupón” y “cupón desconocido” acaban en el mismo grupo. - Esperar que
maplance un error ante una clave ausente, como hace una búsqueda normal en un diccionario.
¡Linterna encendida!
Practicaste: mapdictionariesnanfillnagroupby
- Resuelto
- Sin pistas
- Al primer intento
