Saltar al contenido

lección 2

Día 1 (tarde) — Primer contacto con los datos

Siete exportaciones en la carpeta compartida y ninguna tan limpia como parece. Cárgalas con Pandas, mira qué hay en cada una y entiende por qué en un F2P todo cuelga del jugador y su canal. Explorar antes de calcular.

55 min

### Siete iconos de CSV y una tentación

Abres la carpeta compartida y ahí están: siete ficheros CSV con nombres de tabla. usuarios, sesiones, partidas, compras, ingresos_ads, gasto_ua, productos_iap. La tentación, con el Slack de Bruno pidiendo el CPI «cuanto antes 🙏», es abrir la hoja de gasto, dividir y contestarle en cinco minutos. Resístela. Ya sabes por el encuadre de esta mañana que instalaciones y CPI son el principio, no el final, y que un número sin saber de qué cohorte sale no vale. Antes de calcular nada hay que saber qué hay en cada caja: cuántas filas, qué columnas, de qué tipo, y cuánta suciedad esconden. Esa media hora de aparente lentitud es lo que evita horas de recalcular sobre datos que no eran lo que creías.

La herramienta para esto es Pandas, la librería de Python para trabajar con tablas. Cargas un CSV y te devuelve un DataFrame: una tabla en memoria sobre la que puedes preguntar su forma, sus tipos y sus huecos con una línea. Es lo mismo que abrir el fichero en una hoja de cálculo y mirar por encima, pero programado, repetible y sin que se te cuelgue con cientos de miles de filas. Vamos a hacer justo eso: el reconocimiento del terreno.

### ¿Y por qué no una hoja de cálculo?

Es una pregunta honesta y la respuesta no es «porque el código es más profesional». Una hoja de cálculo es una herramienta de primera, y buena parte de las decisiones bien tomadas del mundo se han tomado sobre una. Podrías abrir estos siete CSV en Excel o en Google Sheets, mirarlos por encima, hacer una tabla dinámica y sacar unas primeras cuentas. Para muchas preguntas, esa sería la respuesta correcta y la más rápida. No hay ningún desprecio en usar una hoja: quien te diga que un analista «de verdad» no toca hojas de cálculo no ha trabajado en una empresa real. La hoja es donde media compañía vive, y saber moverte en ella es parte del oficio.

Dicho eso, este encargo tiene tres características que hacen que la hoja se quede corta, y conviene reconocerlas porque son las mismas tres que empujan a cualquiera de la hoja al código. La primera es el volumen: sesiones tiene más de cuarenta mil filas y partidas más de sesenta mil; una hoja se arrastra, se cuelga o directamente no las abre enteras, y una tabla dinámica sobre ese tamaño tarda una eternidad. La segunda es la repetición: este análisis de captación no se hace una vez, se hará cada mes; si lo montas a mano en una hoja, cada mes repites el clic-clic-clic y cada mes hay un clic que se te olvida. Y la tercera, la más peligrosa: la hoja se copia, y en cuanto hay dos copias hay dos versiones del mismo número. Bruno tendrá su hoja con su CPI, Finanzas la suya con otro, y nadie sabrá cuál manda.

Ni la hoja es de segunda ni el código es superior: cada uno tiene su terreno, y este encargo cae en el del código

Así que la regla no es «hoja mala, código bueno», sino saber en qué terreno estás. Para un vistazo rápido a catorce filas, la hoja. Para un análisis que cruza cuatro fuentes, pesa decenas de miles de filas, se repetirá cada mes y tiene que dar un número que sea el mismo para toda la empresa, el código. Este encargo cumple las cuatro condiciones del lado derecho, y por eso lo haces en Pandas y en SQL. Pero guárdate el respeto por la hoja: la vas a seguir usando toda tu carrera, y muchas veces será la respuesta correcta.

Consejo de senior: desconfía tanto del que desprecia la hoja de cálculo como del que lo mete todo en ella. El primero pierde horas programando lo que se resolvía en cinco minutos con una tabla dinámica; el segundo monta un castillo de fórmulas frágiles que nadie más entiende y que se rompe al mes. El buen analista elige la herramienta por el problema, no por la moda, y sabe explicar por qué. «Lo hice en una hoja porque era un vistazo puntual» es una respuesta perfectamente profesional.

### El modelo de datos: por qué todo cuelga del jugador y su canal

Antes de abrir los ficheros conviene ver cómo encajan entre sí, porque el modelo de datos de un F2P tiene una lógica muy clara una vez la ves. En el centro está el jugador (la tabla usuarios), y cada jugador trae pegado el dato que lo vale todo: su canal de captación, de dónde vino. Alrededor cuelgan las cosas que hace: sus sesiones (cada vez que abre el juego), sus partidas (cada nivel que juega), sus compras (si es de la minoría que paga) y sus ingresos por anuncios (los vídeos que ve). Y fuera del jugador, aparte, está el gasto de publicidad, que no es de ningún jugador concreto sino del canal entero.

El jugador (usuarios) en el centro; todo cuelga de él por user_id, salvo el gasto de publicidad, que se cruza por canal

Fíjate en la línea discontinua: gasto_ua no tiene user_id. Es la única tabla que no se cruza por jugador sino por canal, porque el gasto de publicidad viene de la red de anuncios agregado, no jugador a jugador. Ese cruce por canal es el que te dará el CPI (dividir gasto entre instalaciones de cada canal) y, más adelante, el ROAS. Y es también el que esconde una trampa: para que el cruce funcione, el nombre del canal tiene que estar escrito igual en las dos tablas. Ya lo verás.

Consejo de senior: dibuja este mapa tú mismo en una servilleta antes de escribir código, aunque el equipo ya lo tenga. Identificar cuál es la tabla central (aquí, el jugador) y qué cuelga de ella por qué clave es lo que te permite saber, ante cualquier pregunta, qué tablas hay que cruzar. Quien no tiene el mapa en la cabeza cruza a ciegas y acaba con cifras que «casi cuadran».

Ese mapa esconde una distinción que vas a reconocer en cualquier empresa a la que vayas: hay dos tipos de tabla. Las tablas de hechos guardan cosas que pasan, con fecha: una sesión, una partida, una compra, un anuncio visto. Crecen sin parar, tienen una fila por cada acontecimiento, y son de las que sumas y cuentas. Y las tablas de dimensión describen cosas que son: quién es un jugador (usuarios), qué es un producto (productos_iap). Cambian poco, tienen una fila por cosa, y son las que aportan los atributos por los que quieres agrupar (el canal, el país, el tipo de producto). El patrón de casi todo análisis es el mismo: coges una tabla de hechos y le pegas los atributos de una de dimensión para poder agrupar por algo que el hecho no traía.

Aquí lo ves clarísimo. compras es una tabla de hechos: cada fila es una transacción con su fecha y su importe, pero no sabe de qué canal vino el jugador. usuarios es la dimensión que lo sabe. Para responder «¿cuánto ingresó cada canal?» no te queda otra que pegar el canal de usuarios a cada compra, cruzando por user_id. Sin ese cruce, la tabla de hechos no puede contestar una pregunta por canal, porque el canal no vive en ella. Reconocer qué tabla es hecho y cuál es dimensión te dice, ante cualquier pregunta, qué tienes que cruzar con qué.

Consejo de senior: ante una pregunta nueva, identifica primero qué estás contando (el hecho: compras, sesiones, partidas) y por qué atributo quieres partirlo (la dimensión: canal, país, plataforma). La respuesta casi siempre es «cuenta el hecho, agrupa por el atributo de la dimensión, cruzando por la clave que los une». Ese esqueleto —hecho, dimensión, clave— resuelve el 80% de las preguntas de negocio que te van a llegar, en este sector y en cualquier otro.

### El primer vistazo: cuatro preguntas a cada fichero

Explorar un fichero por primera vez es hacerle cuatro preguntas, siempre las mismas, en este orden. Cada una tiene su método en Pandas y cada una te dice algo distinto.

  1. 01.¿Qué tamaño tiene? → .shape te da (filas, columnas). Te sitúa: no es lo mismo una tabla de 14 filas que una de 60.000.
  2. 02.¿Qué pinta tienen los datos? → .head() te enseña las primeras filas. Ver el dato real vale más que imaginarlo.
  3. 03.¿De qué tipo cree Pandas que es cada columna? → .info() o .dtypes. Una columna que sale como texto (object) donde esperabas un número esconde suciedad.
  4. 04.¿Cuántos huecos hay? → .isnull().sum() cuenta los nulos por columna. Un hueco no siempre es un error: a veces significa algo.

Con esas cuatro preguntas repetidas sobre las siete tablas tendrás, en media hora, un mapa completo de con qué trabajas y qué tendrás que limpiar mañana. No vas a arreglar nada hoy: hoy solo observas y anotas. Como dice Marta por Slack: «hoy entérate de qué hay, mañana lo limpias».

Consejo de senior: resiste la tentación de arreglar los problemas según los encuentras durante la exploración. Es como en el reconocimiento de un terreno: primero recorres el mapa entero y anotas dónde están las minas, y solo después decides por dónde pasar. Si te pones a limpiar la primera columna sucia que ves, pierdes la visión de conjunto y acabas tomando decisiones de limpieza sin saber todavía qué te vas a encontrar en las otras seis tablas. Explorar y limpiar son dos fases, y mezclarlas te hace peor en las dos.

El primer vistazo, siempre las mismas cuatro preguntas: tamaño, pinta, tipos y huecos
1import pandas as pd
2
3usuarios = pd.read_csv('datos/usuarios.csv')
4
5print(usuarios.shape) # (filas, columnas)
6print(usuarios.dtypes) # tipo de cada columna
7print(usuarios.isnull().sum()) # nulos por columna

El patrón de exploración que vas a repetir: cargar y preguntar la forma, los tipos y los nulos.

### Mira el dato real: no te fíes de lo que imaginas que hay

De las cuatro preguntas, la segunda —ver las primeras filas con .head()— parece la más tonta y es la que más disgustos ahorra. Cuando abres un fichero que se llama compras, tu cabeza ya se ha imaginado lo que hay dentro: un importe numérico, una fecha, un identificador. Y casi nunca es lo que imaginabas. El importe está escrito como texto con el euro pegado, la fecha viene en tres formatos, hay una columna de moneda que no esperabas con algún «MXN» dentro. Mirar el dato real, con tus ojos, en cinco filas de ejemplo, te dice en un segundo lo que una hora de suposiciones no te habría dicho. El analista novato calcula sobre lo que cree que hay; el veterano mira primero lo que hay.

Y al mirar los tamaños de las siete tablas te vas a topar con la firma inconfundible de un F2P: una desproporción brutal entre lo que la gente hace y lo que la gente paga. Habrá millones —o decenas de miles— de sesiones y partidas, y en cambio un puñado ridículo de compras. Ocho mil jugadores, decenas de miles de aperturas del juego, y solo unos pocos cientos de transacciones de pago. Esa asimetría no es un error del volcado: es el negocio. Te está diciendo, antes de calcular nada, que aquí el dinero viene de una minoría diminuta y que la inmensa mayoría juega gratis. Un negocio donde todos comprasen tendría las tablas equilibradas; que estén tan descompensadas es la huella de que casi nadie paga.

Consejo de senior: dedica siempre treinta segundos a que los tamaños de las tablas te «cuenten» el negocio antes de tocar una fórmula. Muchas compras y pocos jugadores es una tienda; muchísimos jugadores y poquísimas compras es un F2P; muchos eventos y pocos usuarios es un producto que se usa a diario. La forma de los datos delata el modelo de negocio, y leerla de un vistazo te ahorra malentendidos que costarían horas más adelante.

### La primera cosa que no cuadra: una instalación no es un jugador

Cuando cargues las tablas verás una cosa que conviene tener clara desde ya, porque es el error número uno al contar en un F2P. La tabla usuarios tiene una fila por jugador. La tabla sesiones tiene una fila por cada vez que un jugador abrió el juego, así que un mismo jugador aparece muchísimas veces. Y partidas tiene una fila por cada nivel jugado, todavía más. Cada tabla mira el mundo a un nivel de detalle distinto —en la jerga, tiene una granularidad distinta—, y contar filas de la tabla equivocada infla la respuesta.

La analogía que mejor lo fija es el tique del supermercado. Piensa en las compras de un sábado: hay clientes (los que pasan por caja), hay tiques (cada vez que uno paga) y hay líneas de tique (cada producto que aparece en el papelito). Un mismo cliente puede volver tres veces el mismo día, así que tiene tres tiques; y cada tique tiene diez o quince líneas. Si el gerente pregunta «¿cuánta gente ha comprado hoy?» y tú cuentas líneas de tique, le contestas «cuatro mil» cuando la respuesta eran trescientos clientes. No has calculado mal una división: has contado la cosa equivocada. En PlayLoop, usuarios son los clientes, sesiones son los tiques y partidas son las líneas. Confundir el nivel es responder «cuántos clientes» contando líneas.

Tres tablas, tres granularidades: contar filas de sesiones o partidas no cuenta jugadores

Cuando alguien te pregunte «¿cuántos jugadores activos hay?», la respuesta NO es el número de filas de sesiones. Ese número cuenta aperturas del juego, y un jugador abre el juego muchas veces. Para contar jugadores hay que contar user_id distintos: en Pandas, sesiones["user_id"].nunique(). Confundir filas con jugadores es el error que hincha una cifra al doble o al triple sin que nadie lo note.

### Huecos que significan algo

La cuarta pregunta, la de los nulos, tiene más miga de la que parece. Cuando cuentes los huecos de la tabla usuarios verás que la columna version_app tiene bastantes vacíos. La reacción de un junior novato es borrarlos, pensando que son un error. Pero para eso primero hay que entender por qué faltan. En este caso, son instalaciones antiguas de una época en la que el juego no registraba todavía la versión de la app. El hueco no es un error de datos: es un dato en sí mismo (nos dice «este jugador es viejo»). Borrar esas filas sería tirar jugadores reales por un campo secundario que está vacío por un motivo legítimo.

Esta es una distinción que vas a usar toda tu carrera: un nulo puede ser un error (falta un dato que debería estar) o puede tener significado (el vacío te está contando algo). No hay una regla automática; hay que pensar qué representa cada columna. Un booster_usados nulo probablemente significa «cero boosters», no «dato perdido». Una version_app nula significa «instalación anterior al registro de versión». Un importe de compra nulo sí sería sospechoso. Cada nulo se interroga antes de tocarlo.

Consejo de senior: antes de borrar una sola fila por tener un nulo, pregúntate «¿qué representaría que esto esté vacío?». Si el vacío tiene una explicación razonable de negocio, casi nunca se borra: se marca, se rellena con un valor con sentido, o se deja y se decide en cada cálculo si estorba. Borrar por defecto es la forma más silenciosa de perder datos buenos.

Un apunte sobre gasto_ua antes de cerrar, porque es una fricción que verás en cualquier empresa: no todas las tablas vienen al mismo nivel de detalle. Las de actividad están por jugador y por evento; el gasto de publicidad llega agregado por canal y por día, porque así es como lo reportan las redes. Esa diferencia de grano no es un defecto, es la realidad de juntar datos de fuentes distintas, y obliga a un cuidado extra al cruzar: no puedes pegar un gasto de canal a un jugador concreto, solo repartirlo o compararlo a nivel de canal. Reconocer a qué nivel viene cada tabla es lo que evita cruces imposibles antes de intentarlos.

Con el mapa del modelo en la cabeza, el patrón de las cuatro preguntas y el ojo puesto en la granularidad y en los nulos, ya puedes abrir las siete cajas. Empieza por saber el tamaño de cada una: te sorprenderá lo distinto que es el volumen de lo que la gente hace (millones de sesiones) frente a lo que paga (un puñado de compras). Esa desproporción es la firma de un F2P.

Regístrate para guardar tu progreso.