La solicitud

De Robert Kim, Director de Operaciones
Tu objetivo
Cuenta los pedidos (todos los estados) por año y canal, y convierte los recuentos en la cuota de cada canal sobre los pedidos de ese año (las filas suman 1), redondeada a 3. Asigna a result un DataFrame con las columnas year (2023, 2024, 2025), app, marketplace, web, ordenado por year. Dibújalo como un gráfico de barras apiladas.
- Usa el DataFrame
orderspendiente - Muestra exactamente
yearappmarketplacewebpendiente - 3 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 Robert, 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
De qué está hecho un total
“¿Cuánto del total viene de cada parte?” es una pregunta de composición, y el gráfico para ella es una barra apilada: una barra por periodo, dividida en segmentos. Cuando los totales difieren mucho entre periodos pero te importa la mezcla, apila cuotas, de modo que cada barra mide el 100 % y solo se mueven los segmentos.
Recuentos, luego cuotas
pd.crosstab cuenta filas para cada par de valores:
year = orders["order_date"].dt.year.rename("year")
counts = pd.crosstab(year, orders["channel"])
# app marketplace web
# 2023 819 464 1888
# 2024 1366 601 2079
# 2025 2135 702 1946
Para obtener cuotas dentro de un año, divide cada fila entre el total de esa fila. sum(axis=1)
suma a lo largo de las columnas, dando un total por año, y div(..., axis=0) divide fila a fila:
shares = counts.div(counts.sum(axis=1), axis=0).round(3)
# app marketplace web
# 2023 0.258 0.146 0.595
# 2025 0.446 0.147 0.407
Barras apiladas y agrupadas en pandas
ax = shares.plot(kind="bar", stacked=True, rot=0) # stacked: composition
ax = counts.plot(kind="bar", rot=0) # grouped: compare channels side by side
Las barras agrupadas responden a “¿cuál es mayor?” dentro de cada año. Las barras apiladas
responden a “¿qué tamaño tiene el todo, y de qué está hecho?”. rot=0 mantiene rectas las etiquetas de los años.
En matplotlib puro, una pila se construye a mano: cada segmento empieza donde terminó el anterior, que es lo que hace bottom=:
fig, ax = plt.subplots()
bottom = np.zeros(len(shares))
for channel in shares.columns:
ax.bar(shares.index.astype(str), shares[channel], bottom=bottom, label=channel)
bottom += shares[channel].values
ax.legend()
Leer el cambio
En 2023 la web tenía el 59,5 % de los pedidos y la app el 25,8 %. En 2025 la app tenía el 44,6 % y la web el 40,7 %: la app adelantó a la web en número de pedidos. El marketplace apenas se movió, del 14,6 % al 14,7 %. Solo el segmento inferior de una pila se puede comparar exactamente, porque los demás flotan, así que pon abajo el segmento del que trata tu historia. Con solo tres partes de un total, un gráfico circular por año también funcionaría, pero tres gráficos circulares lado a lado son más difíciles de comparar que tres barras.
Errores comunes
- Dividir por los totales de columna (
counts / counts.sum()) en lugar de por los totales de fila. - Apilar recuentos en bruto cuando la pregunta es sobre la mezcla: los totales crecientes ocultan el cambio.
- Demasiados segmentos. Pasadas cinco o seis, agrupa los pequeños en “otros”.
- Olvidar la leyenda, o dejarla encima de las barras.
bbox_to_anchor=(1, 1)la mueve a la derecha del gráfico, donde no tapa nada.
¡Linterna encendida!
Practicaste: stacked bargrouped barsharescrosstabcomposition
- Resuelto
- Sin pistas
- Al primer intento
