1. Faro

Nivel 9 · Desafío final: el informe de canales para la junta

La solicitud

De Laura Bennett, Directora de Finanzas

“Para el dossier de la junta necesito los ingresos completados por canal de venta de 2023 a 2025 con el crecimiento de 2025, y luego una cuadrícula de 2025 de pedidos por mes y canal, con enero primero. La junta preguntará dos cosas: qué canal lideró en enero y qué mes fue el más ocupado.”

Tu objetivo

Paso 1 de 4. Asigna a result un DataFrame con las columnas channel, 2023, 2024, 2025: la suma de los ingresos de línea completados por canal y año de order_date, redondeada a 2. Una fila por canal, ordenada de la A a la Z.

  • Usa el DataFrame orderspendiente
  • Usa el DataFrame order_itemspendiente
  • Muestra exactamente channel 2023 2024 2025pendiente

Paso 1 · tu código

Python

Cargando el editor…

    ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
    Vista previa de orders
    order_idcustomer_idorder_datestatuschannel
    10011252023-01-01 20:51:19completedweb
    10021562023-01-02 07:58:46completedweb
    1003222023-01-02 10:25:27completedmarketplace
    1004482023-01-02 11:21:51completedmarketplace

    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

    Python

    Cargando el editor…

      ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
      Vista previa de orders
      order_idcustomer_idorder_datestatuschannel
      10011252023-01-01 20:51:19completedweb
      10021562023-01-02 07:58:46completedweb
      1003222023-01-02 10:25:27completedmarketplace
      1004482023-01-02 11:21:51completedmarketplace

      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

      Python

      Cargando el editor…

        ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
        Vista previa de orders
        order_idcustomer_idorder_datestatuschannel
        10011252023-01-01 20:51:19completedweb
        10021562023-01-02 07:58:46completedweb
        1003222023-01-02 10:25:27completedmarketplace
        1004482023-01-02 11:21:51completedmarketplace

        Mote revisa tu resultado

        Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.

        Paso 4 · tu código

        Python

        Cargando el editor…

          ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
          Vista previa de orders
          order_idcustomer_idorder_datestatuschannel
          10011252023-01-01 20:51:19completedweb
          10021562023-01-02 07:58:46completedweb
          1003222023-01-02 10:25:27completedmarketplace
          1004482023-01-02 11:21:51completedmarketplace

          Mote revisa tu resultado

          Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.

          DataFrames

          Cargados como DataFrames de pandas, junto con pd y np.

          orders12,000 filas · 7 columnas
          • order_idinteger
          • customer_idinteger
          • order_datetimestamp
          • statusvarchar
          • channelvarchar
          • shipping_feedecimal
          • coupon_codevarchar
          Primeras 5 filas de orders
          order_idcustomer_idorder_datestatuschannelshipping_feecoupon_code
          10011252023-01-01 20:51:19completedweb0.00NaN
          10021562023-01-02 07:58:46completedweb0.00NaN
          1003222023-01-02 10:25:27completedmarketplace4.99WELCOME10
          1004482023-01-02 11:21:51completedmarketplace4.99WELCOME10
          1005822023-01-02 11:43:36completedweb0.00WELCOME10
          order_items30,338 filas · 6 columnas
          • order_item_idinteger
          • order_idinteger
          • product_idinteger
          • quantityinteger
          • unit_pricedecimal
          • discount_pctdecimal
          Primeras 5 filas de order_items
          order_item_idorder_idproduct_idquantityunit_pricediscount_pct
          11001121931.990.00
          21001154311.990.00
          31002154411.990.00
          410021941149.000.00
          51002193219.990.00
          customers2,018 filas · 9 columnas
          • customer_idinteger
          • first_namevarchar
          • last_namevarchar
          • emailvarchar
          • cityvarchar
          • statevarchar
          • signup_datedate
          • segmentvarchar
          • referral_sourcevarchar
          Primeras 5 filas de customers
          customer_idfirst_namelast_nameemailcitystatesignup_datesegmentreferral_source
          1OwenHudsonowen.hudson@icloud.comSan FranciscoCA2022-06-02consumersearch
          2DouglasMendozadmendoza69@gmail.comAtlantaGA2022-06-02consumerNaN
          3HenryBrookshbrooks@lakesidecafe.comLos AngelesCA2022-06-04businessNaN
          4BrianGrahambgraham@bluecedarhomes.comSeattleWA2022-06-06businesspinterest
          5KyleJimenezkjimenez27@yahoo.comIndianapolisIN2022-06-07consumerNaN
          products120 filas · 8 columnas
          • product_idinteger
          • namevarchar
          • categoryvarchar
          • subcategoryvarchar
          • unit_pricedecimal
          • unit_costdecimal
          • launched_ondate
          • is_activeboolean
          Primeras 5 filas de products
          product_idnamecategorysubcategoryunit_priceunit_costlaunched_onis_active
          101Vale Velvet LoveseatFurnitureSofas1659.00NaN2023-09-11true
          102Alder Oak Coffee TableFurnitureTables919.00503.502024-05-16true
          103Orchard Rattan Dining ChairFurnitureChairs789.00429.872023-05-27true
          104Upland Oak BookcaseFurnitureStorage429.00214.702022-12-20true
          105Avery Leather Bed FrameFurnitureBeds449.00232.702021-08-31true
          returns1,673 filas · 5 columnas
          • return_idinteger
          • order_item_idinteger
          • returned_ondate
          • reasonvarchar
          • refund_amountdecimal
          Primeras 5 filas de returns
          return_idorder_item_idreturned_onreasonrefund_amount
          1142023-01-10damaged83.69
          2422023-01-10wrong_item19.99
          31052023-01-14wrong_item10.99
          4242023-01-16changed_mind26.99
          51262023-01-16late20.99
          employees60 filas · 8 columnas
          • employee_idinteger
          • first_namevarchar
          • last_namevarchar
          • departmentvarchar
          • titlevarchar
          • manager_idinteger
          • hire_datedate
          • salaryinteger
          Primeras 5 filas de employees
          employee_idfirst_namelast_namedepartmenttitlemanager_idhire_datesalary
          1CatherineHaleExecutiveChief Executive OfficerNaN2016-03-01285000
          2RobertKimExecutiveChief Operating Officer12017-01-09235000
          3MeganCollinsSalesHead of Sales12018-04-16172000
          4ChloeGutierrezSalesAccount Executive32020-01-2172000
          5FrankBellSalesAccount Executive32023-05-2173000
          web_sessions40,000 filas · 7 columnas
          • session_idinteger
          • customer_idinteger
          • started_attimestamp
          • devicevarchar
          • sourcevarchar
          • pages_viewedinteger
          • convertedboolean
          Primeras 5 filas de web_sessions
          session_idcustomer_idstarted_atdevicesourcepages_viewedconverted
          1NaN2023-01-01 23:02:24mobilepaid1false
          2182023-01-01 15:07:49desktoppaid1false
          3NaN2023-01-01 16:55:46desktopdirect7false
          4NaN2023-01-01 12:43:28mobileorganic3false
          5NaN2023-01-01 13:06:21mobilesocial2false
          marketing_spend3,276 filas · 3 columnas
          • spend_datedate
          • channelvarchar
          • amountdecimal
          Primeras 5 filas de marketing_spend
          spend_datechannelamount
          2023-01-01paid492.99
          2023-01-01email37.38
          2023-01-01social200.53
          2023-01-02paid709.13
          2023-01-02email64.13

          La lección

          Dos cuadrículas, una reunión

          Este desafío usa las herramientas de cuadrícula del capítulo en una petición real de la junta. Los datos empiezan largos: una fila por línea de pedido o por pedido. La junta lee cuadrículas, y hace preguntas sobre ellas.

          Cada paso se ejecuta sobre una copia nueva de las tablas, así que cada uno construye de nuevo lo que necesita:

          items = order_items.merge(orders[["order_id", "order_date", "status", "channel"]], on="order_id")
          items = items[items["status"] == "completed"].copy()
          items["revenue"] = items["quantity"] * items["unit_price"] * (1 - items["discount_pct"] / 100)
          items["year"] = items["order_date"].dt.year

          Crecimiento en forma ancha

          Con el canal en el lateral y el año arriba, los ingresos completados suman 1,600,511.41 en 2023, 1,993,605.32 en 2024 y 2,300,170.84 en 2025. Cada año es una columna, así que el crecimiento es aritmética de columnas, calculada para todos los canales a la vez:

          grid["growth_2025"] = grid[2025] / grid[2024] - 1

          Las etiquetas vinieron de dt.year, así que son enteros. Calcula el crecimiento sobre los totales sin redondear, y redondea después. Ordenada por crecimiento, la historia es clara: app creció un 53,1 % y se convirtió en el canal más grande, marketplace creció un 13,3 %, web cayó un 7,2 %.

          Meses en orden de calendario

          dt.month_name() convierte una fecha en “January”, “February”, etc., que es lo que quiere ver un lector. La pega: pandas ordena el texto alfabéticamente, así que un pivot sobre nombres de mes sale April, August, December, February… Dos soluciones:

          months = ["January", "February", "March", "April", "May", "June", "July",
                    "August", "September", "October", "November", "December"]
          grid.reindex(months)                     # rows in the order of the list

          o conserva el número del mes (dt.month) junto al nombre, ordena por el número y luego pon el nombre como índice. reindex es más corto cuando ya tienes la lista; además añade una fila de NaN para cualquier mes que falte, lo que hace visibles los huecos en lugar de descartarlos en silencio.

          Leer la cuadrícula: idxmax y sum(axis=1)

          Dos métodos cortos responden a la mayoría de las preguntas de “¿cuál?”:

          • .idxmax() sobre una Series devuelve la etiqueta de su valor mayor (.max() devuelve el valor). grid.loc["January"].idxmax() es el canal que más vendió en enero.
          • grid.sum(axis=1) suma a lo largo de cada fila (un total por mes); grid.sum() suma por cada columna (un total por canal). Encadena .idxmax() para nombrar el mayor.
          grid.idxmax(axis=1)        # the leading channel in every month

          En 2025 app lideró nueve meses, pero web lideró enero, junio y agosto. Un titular como “app lidera todos los meses” sería incorrecto, y estas dos líneas son cómo lo compruebas.

          Errores comunes

          • Valorar las líneas con products["unit_price"] en lugar del precio de la línea de pedido.
          • Escribir grid["2025"] para una etiqueta de columna entera.
          • Dejar los meses en orden alfabético.
          • Usar .max() cuando la pregunta pide cuál mes o canal: eso es .idxmax().
          • Sumar con axis=0 cuando quieres un total por fila.

          Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.