Nivel 1 · Añade nombres de producto a las líneas de pedido
¿Es nuevo para ti? Lee primero el concepto: Qué le hace un merge a tu número de filas
0 de 3
La solicitud

De Angela Rivera, Directora de Atención al Cliente
Tu objetivo
Asigna a result un DataFrame con una fila por cada línea de pedido de los pedidos 1001 a 1010 (ambos incluidos): columnas order_item_id, order_id, name, category, quantity (name y category vienen de products, unidas por product_id), ordenado por order_item_id ascendente, con el índice reiniciado.
- Usa el DataFrame
productspendiente - Usa el DataFrame
order_itemspendiente - Muestra exactamente
order_item_idorder_idnamecategoryquantitypendiente
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 Angela, 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 |
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 |
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 |
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é las tablas están separadas
order_items guarda un product_id en cada línea en lugar del nombre, la categoría y el precio del
producto. Es a propósito: los detalles del producto viven en un solo sitio, products, así que
renombrar un producto significa cambiar una fila, no 30.000. El coste es que tienes que unir las
tablas de nuevo (hacer un join) cuando necesitas ambas.
merge
order_items.merge(products, on="product_id")
Para cada línea de pedido, pandas busca la fila de producto con el mismo product_id y pone sus
columnas una al lado de otra. La columna por la que emparejas es la clave. Si la clave se llama
distinto en las dos tablas, usa left_on= y right_on=. Por ejemplo, el manager_id de cada
empleado apunta al employee_id de otro empleado, así que esto pone a cada empleado junto a los
datos de su jefe:
employees.merge(employees, left_on="manager_id", right_on="employee_id", suffixes=("", "_manager"))
Eso da 59 filas, no 60: el CEO no tiene jefe, así que el merge inner deja fuera esa fila.
El argumento how= decide qué pasa con las filas sin pareja:
| how | conserva |
|---|---|
"inner" (por defecto) |
solo las filas con pareja en ambas tablas |
"left" |
todas las filas de la tabla izquierda; NaN donde la derecha no tiene pareja |
"right" |
todas las filas de la tabla derecha |
"outer" |
todo de ambas |
Aquí cada línea de pedido tiene un producto válido, así que inner y left dan el mismo resultado.
Escribe how= de forma explícita de todos modos; le dice al lector que lo pensaste.
Nombres de columna repetidos
Ambas tablas tienen una columna unit_price, y significan cosas distintas: el precio pagado en la
línea frente al precio de lista de hoy. pandas conserva las dos y añade suffixes, unit_price_x y
unit_price_y. Esos nombres son fáciles de confundir, así que pon los tuyos:
order_items.merge(products, on="product_id", suffixes=("_paid", "_list"))
O selecciona solo las columnas que necesitas de la tabla derecha antes de unir, lo que además mantiene el resultado estrecho:
order_items.merge(products[["product_id", "name", "category"]], on="product_id")
Comprueba el número de filas
El hábito más útil con los merges: comparar el número de filas antes y después.
len(order_items) # lines before
len(order_items.merge(products, on="product_id")) # should be the same
Cada línea tiene exactamente un producto, así que el número no debe cambiar. Si creció, la tabla derecha tenía claves duplicadas y algunas líneas se copiaron. Si se redujo, algunas líneas no tenían pareja y un join inner las descartó. Verás ambos problemas más adelante en este capítulo.
pandas puede comprobarlo por ti. validate="many_to_one" dice “muchas líneas pueden compartir un
producto, pero cada producto aparece una vez en products”, y lanza un error si no es así:
order_items.merge(products, on="product_id", how="inner", validate="many_to_one")
Otras opciones son "one_to_one" y "one_to_many". Añadir validate no cuesta nada y convierte un
error silencioso en uno ruidoso.
Errores comunes
- Hacer merge sin
on=. pandas entonces une por todas las columnas con el mismo nombre en ambas tablas, aquíproduct_idyunit_price, y la mayoría de las líneas no encuentran pareja porque los precios cambiaron. - Usar
unit_price_xmás tarde sin recordar de qué tabla venía. - No comprobar el número de filas después de un merge.
¡Linterna encendida!
Practicaste: mergeinner joinonsuffixesrow count check
- Resuelto
- Sin pistas
- Al primer intento
