Saltar al contenido

Indice / Practicas / EJ-6.10

EJ-6.10 · Sesionizar eventos por hueco de 30 minutos

Practica de: 6.6 Series de tiempoDificultad: A

600 eventos sueltos se convierten en 128 sesiones. La palabra «sesión» no existe en los datos: hay que inventarla a partir de los huecos, y decidir cuán grande tiene que ser un hueco para que corte.

Qué hay que hacer

A partir de eventos_usuarios.json, producir sesiones_usuarios.csv: una fila por sesión, con cuándo empezó y terminó, cuántos eventos tuvo, cuántas páginas distintas y cuánto se compró.

ELI5Explicado facil

Tenés el registro de cada vez que alguien tocó algo en la web. Nadie anotó «acá empieza una visita».

Pero si ves cuatro clics a las 8:07, 8:24, 8:35 y 8:45, y el siguiente recién a las 11:44, es evidente que fueron dos visitas. Lo que las separa es el hueco - y cuánto tiene que durar el hueco lo decidís vos, no los datos.

Archivos

El orden es parte del algoritmo

El archivo viene en el orden en que se registraron los eventos, no en el orden de cada usuario. Y diff() compara con la fila anterior de la tabla.

Sin ordenar por (usuario, fecha) salen 206 cortes en vez de 88, y aparecen 292 diferencias negativas: el evento «anterior» resultó ser posterior. Los dos programas corren, los dos devuelven un número plausible, y no hay forma de saber cuál está bien mirando el resultado.

El assert que lo atrapa es una línea: ninguna duración puede ser negativa.

La cuenta que tiene que cerrar

88 cortes + 40 usuarios = 128 sesiones. Cada usuario arranca con la sesión 1 aunque nunca haya tenido un hueco; cada corte agrega una. Si tu archivo tiene 88 filas, te olvidaste del + 1.

Cómo saber si te salió

python comparar.py mi_salida.csv sesiones_usuarios.csv

Antes de arrancar, mirá los datos

eventos_usuarios.json (entrada) · 3603 filas, se muestran 5
{
"origen": "web-analytics"vacio
"eventos": [
{
"usuario": "u10"vacio
"fecha": "2026-08-24T15:11:00"vacio

El contrato de salida

sesiones_usuarios.csv · 128 filas

ColumnaTipoQue lleva
usuariotextoEl identificador del usuario
sesionenteroNumero de sesion DENTRO de ese usuario, empezando en 1
iniciotextoPrimer evento de la sesion, AAAA-MM-DD HH:MM:SS
fintextoUltimo evento de la sesion, mismo formato
eventosenteroCuantos eventos tiene la sesion
minutosdecimalDuracion: fin menos inicio, en minutos, con 1 decimal
paginasenteroPaginas distintas visitadas en la sesion
comprasenteroEventos de tipo compra
importedecimalSuma de importe, redondeada a 2 decimales. 0.00 si no hubo compras

Orden de las filas: usuario ASC y, dentro, sesion ASC. El par es unico. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
3 eventos con la fecha invalida (vacia, 2026-08-32, 24/08/2026 10:00)3 de 600descartar descartar antes de sesionizar. Una fecha que no se puede ordenar rompe el calculo de huecosfuera de sesiones_usuarios.csv
1 evento con el usuario vacio1 de 600descartar: descartar: no se le puede atribuir a nadiefuera de sesiones_usuarios.csv
82 eventos sin pagina y 520 sin importeson campos opcionales segun el tipo de eventoNO NO se descartan ni se imputan. nunique ignora los ausentes y sum los trata como 0sesiones_usuarios.csv
el archivo NO viene ordenado por usuario y fechalas 600 filasordenar ordenar por (usuario, fecha) ANTES de calcular los huecos. Sin eso salen 206 cortes en vez de 88sesiones_usuarios.csv
Orden de comprobacion

Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:

  1. descartar los eventos sin usuario
  2. descartar los eventos con fecha invalida
  3. ordenar por usuario y fecha, con kind='stable'
  4. calcular el hueco con groupby('usuario')['fecha'].diff()
  5. marcar los cortes y numerar con cumsum() + 1
  6. agrupar por (usuario, sesion)

El orden va antes del diff porque diff compara con la fila anterior de la TABLA, no con el evento anterior del usuario. Y los invalidos se descartan antes de ordenar: una fecha NaT no tiene lugar en ningun orden y contaminaria los huecos de su usuario.

Conteos clave

Si estos numeros no te dan, algo se desvio antes de que llegues a comparar los archivos.

eventos en el archivo600
eventos validos596
usuarios con eventos validos40
cortes (huecos de mas de 30 minutos)88
sesiones_usuarios.csv128
compras en total81
por motivo

Invariantes

Comprobaciones que tu resultado tiene que cumplir. Corrilas vos mismo antes de comparar los archivos:

len(sesiones) == 128
88 + 40 == 128
int(sesiones['eventos'].sum()) == 596
sesiones['usuario'].nunique() == 40
sesiones.duplicated(subset=['usuario', 'sesion']).sum() == 0
sesiones.groupby('usuario')['sesion'].min().eq(1).all()
(sesiones['minutos'] >= 0).all()
(sesiones['paginas'] <= sesiones['eventos']).all()
int(sesiones['compras'].sum()) == 81
PISTASSi te trabas, abri esto
  • Las sesiones son cortes MAS usuarios: cada usuario arranca con la sesion 1 aunque nunca haya tenido un hueco. 88 + 40 = 128.
  • Sin ordenar por (usuario, fecha) salen 206 cortes. Los dos programas corren y los dos dan un numero plausible.
  • Un assert de que ninguna duracion es negativa atrapa el error de orden solo.
  • cumsum() sobre la mascara de cortes es lo que convierte los cortes en numeros de sesion. Vale la pena mirarlo una vez con atencion.

Así tiene que quedar

sesiones_usuarios.csv (objetivo) · 128 filas, se muestran 5
usuariosesioniniciofineventosminutospaginascomprasimporte
u0112026-08-24 10:22:002026-08-24 10:38:00216.002370.37
u0122026-08-24 11:48:002026-08-24 12:12:00724.031477.81
u0132026-08-24 13:39:002026-08-24 13:54:00215.011476.81
u0142026-08-24 15:36:002026-08-24 16:09:00633.0400.0
u0212026-08-24 09:03:002026-08-24 09:36:00633.0300.0
Cuatro eventos se descartan antes de empezar

Tres tienen la fecha inválida - una vacía, un 2026-08-32 que no existe, y una escrita 24/08/2026 10:00 - y uno no tiene usuario.

Van afuera antes de ordenar. Una fecha NaT no tiene lugar en ningún orden, y si se cuela, contamina los huecos de su usuario: el evento anterior y el siguiente quedan separados por una diferencia que no significa nada.

El umbral es una decisión declarada

30 minutos es la convención de la industria para analítica web, y por eso es el que usa el contrato. Con 15 minutos saldrían más sesiones y más cortas; con una hora, menos y más largas. Ninguno es «el correcto»: lo que importa es que esté escrito, para que dos informes del mismo mes se puedan comparar.

Y el borde también: más de 30 minutos corta; exactamente 30, no.