1. Faro

Nivel 2 · Verifica y construye el embudo web en pandas

La solicitud

De Jordan Reyes, Director de Marketing

“Acordamos el plan: un embudo por dispositivo, de sesiones a interacción a conversión, y luego las mismas tasas por año. Antes de construirlo, dime para qué se puede confiar en los datos de sesiones. He oído que la mitad de nuestros visitantes son anónimos.”

Tu objetivo

Paso 1 de 3. Verifica los datos. Asigna a result un DataFrame de una fila con las columnas sessions (todas las filas), distinct_ids (session_id distintos), anonymous (customer_id es nulo), anonymous_converted (anónima y convertida), empty_sessions (pages_viewed < 1), converted_under_3_pages (convertidas con pages_viewed < 3) y converted (todas las sesiones convertidas).

  • Usa el DataFrame web_sessionspendiente
  • Muestra exactamente sessions distinct_ids anonymous anonymous_converted empty_sessions converted_under_3_pages convertedpendiente
  • 1 fila, ordenadas como se pidependiente

Paso 1 · tu código

Python

Cargando el editor…

    ResultadoVista previa de web_sessions · presiona Ejecutar para ver el tuyo
    Vista previa de web_sessions
    session_idcustomer_idstarted_atdevicesource
    1NaN2023-01-01 23:02:24mobilepaid
    2182023-01-01 15:07:49desktoppaid
    3NaN2023-01-01 16:55:46desktopdirect
    4NaN2023-01-01 12:43:28mobileorganic

    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 web_sessions · presiona Ejecutar para ver el tuyo
      Vista previa de web_sessions
      session_idcustomer_idstarted_atdevicesource
      1NaN2023-01-01 23:02:24mobilepaid
      2182023-01-01 15:07:49desktoppaid
      3NaN2023-01-01 16:55:46desktopdirect
      4NaN2023-01-01 12:43:28mobileorganic

      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 web_sessions · presiona Ejecutar para ver el tuyo
        Vista previa de web_sessions
        session_idcustomer_idstarted_atdevicesource
        1NaN2023-01-01 23:02:24mobilepaid
        2182023-01-01 15:07:49desktoppaid
        3NaN2023-01-01 16:55:46desktopdirect
        4NaN2023-01-01 12:43:28mobileorganic

        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.

        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
        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
        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
        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
        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

        Qué estás verificando y por qué

        web_sessions es una tabla de seguimiento: cada visita al sitio, su dispositivo y fuente, cuántas páginas vio y si terminó en una compra. Las tablas de seguimiento están llenas de huecos, así que antes de construir un embudo sobre una, averigua lo que puede y no puede mostrar. El paso 1 hace cuatro preguntas de una pasada:

        • ¿Se cuenta alguna sesión dos veces? Compara len(s) con s["session_id"].nunique().
        • ¿Hay sesiones vacías? Una visita con cero páginas es un fallo de seguimiento.
        • ¿Quién puede convertir? Cuenta las sesiones anónimas y cuántas de ellas convirtieron.
        • ¿Se sostiene la definición? Cuenta las conversiones con menos de tres páginas.

        Una condición sobre una columna da una Series booleana, y sumarla cuenta los valores True:

        anon = s["customer_id"].isna()
        (anon & s["converted"]).sum()   # 0

        El cero es el número más importante del caso. Más de la mitad de las sesiones nunca pueden mostrar una compra, porque las compras solo se registran contra una cuenta. Las tasas que construyas a continuación son tasas de compras registradas, y el embudo necesita una etapa para iniciar sesión. Envolver cada conteo en int() convierte los enteros de NumPy en números simples para el DataFrame de una fila.

        Un embudo es una cadena de columnas booleanas

        Un embudo sigue a las mismas sesiones a través de etapas que se estrechan: todas las sesiones, engaged (pages_viewed >= 3), engaged con sesión iniciada, converted. En pandas cada etapa es una columna booleana, y la agregación con nombre las suma por dispositivo en una sola llamada:

        result = s.groupby("device", as_index=False).agg(
            sessions=("session_id", "count"),
            engaged=("engaged", "sum"),
            known_engaged=("known_engaged", "sum"),
            converted=("converted", "sum"),
        )

        Las tasas dividen una etapa entre la anterior, para ver dónde abandona la gente: engaged_pct es el paso de navegación, close_pct es el paso de pago.

        Cómo leer el embudo

        device engaged_pct close_pct conversion_pct
        desktop 44.1 21.4 3.87
        mobile 44.1 12.9 2.41
        tablet 44.8 14.6 2.81

        El paso de navegación es el mismo en todos los dispositivos. El paso de pago es donde el móvil se queda atrás. Eso cambia el encargo al equipo móvil: las páginas de producto cumplen su función; la cesta, el inicio de sesión y el formulario de pago son donde hay que mirar.

        Por qué importa la vista por año

        El paso 3 repite la tasa de conversión por año, una columna por dispositivo. Un buen truco: multiplica un booleano por 100 y su media es un porcentaje. unstack() convierte entonces el nivel de dispositivo del índice en columnas. La proporción de tráfico móvil creció cada año, y el móvil convierte menos, así que la tasa global es un promedio ponderado cuyos pesos se siguen moviendo hacia la tasa baja. Todos los dispositivos mejoraron de 2023 a 2025, mientras la tasa global creció mucho menos. Si mantuvieras la mezcla de dispositivos de 2023 y aplicaras las tasas de 2025, la tasa global sería aproximadamente 3.24% en lugar de 3.08%. Divide siempre una tasa por sus segmentos antes de llamarla tendencia.

        Trampas

        • == None y == np.nan nunca coinciden; usa .isna() y .notna().
        • & tiene mayor precedencia que <, así que envuelve cada comparación entre paréntesis.
        • Dividir entre sessions para la tasa de cierre mezcla etapas: divide entre la etapa inmediatamente anterior.

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