lección 3
Día 2 (mañana) — Antes de calcular, limpiar (y definir tú qué es renovar)
Con la lista de suciedad de ayer, hoy limpias con criterio propio: fechas en tres formatos (incluido el mes en inglés), importes con euro, plan y sede en varias grafías, edades imposibles, y la fecha de baja vacía convertida en una bandera de activo. Y tomas la decisión de peso de la semana: qué significa exactamente «renovar».
⏱ 50 min
### La cocina antes del plato
Un cocinero no empieza a cocinar echando las verduras a la sartén tal como llegan del mercado. Primero las lava, las pela, las corta al mismo tamaño y las coloca en cuencos: el mise en place, lo llaman en francés, «poner en su sitio». Sin ese paso previo, el plato sale desigual: unos trozos crudos, otros quemados, tierra en la ensalada. Limpiar datos es exactamente eso. Ayer levantaste el capó y anotaste todo lo que venía sucio; hoy lo pones en su sitio, para que cuando mañana empieces a calcular tasas de renovación, los ingredientes estén limpios y cortados iguales. La diferencia entre un análisis que aguanta y uno que se cae casi nunca está en el cálculo final —eso es una división—, está en si los datos que entran en esa división están limpios. Y hoy, además, tomas dos decisiones que no son de limpieza sino de criterio, y que deciden el caso: qué significa una fecha de baja vacía, y qué significa «renovar».
La forma de trabajar de hoy es distinta a la de tus primeros encargos. Entonces te daban el mapeo hecho: «convierte estas cuatro grafías en esta categoría». Ahora Nuria te ha soltado la mano: sabes que hay que normalizar el plan, así que lo normalizas; sabes que hay que parsear las fechas, así que decides cómo; sabes que las edades imposibles hay que apartarlas, así que pones tú el umbral. El código llega a cachos y con pistas, pero el criterio es tuyo. Eso es lo que se espera de un analista que ya no es junior: no que sepa la sintaxis —eso lo tienes—, sino que sepa qué hay que hacer y por qué, y lo haga sin que se lo dicten.
### Las fechas, y el mes en inglés
Empecemos por lo que más columnas afecta: las fechas. Vienen en tres formatos mezclados en la misma columna: «2024-03-12» (el formato ISO, año-mes-día), «12/03/2024» (día/mes/año, el europeo) y «12 Mar 2024» (con el mes en inglés abreviado). La herramienta que parsea fechas en Pandas, `pd.to_datetime`, puede con los tres si le dices dos cosas: que el formato es mixto (`format='mixed'`, es decir, «no asumas uno solo, míralos uno a uno») y que cuando la fecha sea ambigua asuma el día primero (`dayfirst=True`, para que «12/03» sea 12 de marzo y no 3 de diciembre). Añades `errors='coerce'` para que, si alguna fecha no parsea, en vez de romper el programa la convierta en un nulo especial de fecha (NaT, «not a time») que luego puedes contar. Cuando lo hagas verás que las fechas de las suscripciones parsean todas, cero NaT: la clave es que el mes viene en inglés, que la herramienta entiende, y no en español, que no entendería.
### Los importes, el plan y la sede
Los importes —el precio de la suscripción, lo cobrado en cada pago, la cuota base de la sede— vienen como texto: «39,00 €», «468,00 €». Para convertirlos en número hay que quitar el símbolo del euro, quitar los espacios, cambiar la coma decimal por punto (porque la herramienta entiende el punto como decimal, no la coma) y entonces convertir a decimal. Cuidado con un detalle: si hubiera separador de miles con punto («1.200,00 €»), habría que quitar ese punto antes de cambiar la coma, o te saldría un número roto. Cuando limpies los importes verás que el medio ronda los 74 €, pero que hay un máximo de 9.999 € y un mínimo de 0 €: dos valores imposibles, outliers que alguien metió por error o para probar, y que habrá que apartar del cálculo del LTV para que no lo desvíen.
El plan es la columna más importante de todas, porque el encargo entero se apoya en distinguir anual de mensual. Ayer viste sus ocho grafías. Normalizarlas es mapear cada una a su categoría limpia: «mensual», «Mensual», «MENSUAL» y «mes» pasan a «mensual»; «anual», «Anual», «ANUAL» y «año» pasan a «anual». La forma robusta es pasar todo a minúsculas y quitar espacios primero, y luego mapear; así, si mañana aparece una grafía nueva con otra combinación de mayúsculas, la pillas igual. La sede se normaliza igual, pero apuntando a las seis ciudades canónicas de la tabla de sedes: «MAD», «Madrid» y «madrid» se convierten todas en «Madrid». Y recuerda el aviso de ayer: mientras la sede en los check-ins siga como texto sucio, el cruce con la tabla de sedes por ciudad no cuadra. Normalizar categorías no es cosmético: es lo que hace que los cruces funcionen.
### La decisión de peso (1): la fecha de baja vacía
Aquí dejamos la limpieza mecánica y entramos en criterio. Ayer contaste que 7.322 de las 10.957 suscripciones tienen la fecha de baja vacía. La reacción de junior es tratarlas como datos que faltan: borrarlas, o rellenarlas con una fecha cualquiera. Sería un error grave. Álex lo avisó y lo repito porque es el eje del caso: una fecha de baja vacía no es un hueco, es información. Significa que esa suscripción no se ha dado de baja anticipadamente; sigue viva. Lo que hay que hacer no es borrar ni rellenar, sino convertir ese vacío en una señal explícita: crear una bandera —una columna nueva de sí/no— que diga «esta suscripción está activa». Convertir un vacío con significado en una columna con nombre es una de las cosas más valiosas que puede hacer un analista, porque deja escrito para siempre lo que antes era tradición oral en la cabeza de Álex.
El vacío con significado es una trampa que se cobra víctimas. Si tratas la fecha de baja vacía como un nulo a eliminar, pierdes a los 4.370 socios que siguen de alta —justo los que interesan para saber quién se queda— y tu tasa de renovación se calcula solo sobre los que ya se fueron, que es un sinsentido. Antes de borrar cualquier fila por tener un nulo, pregúntate siempre: ¿este vacío es un dato que falta, o un dato que significa algo? En las fechas de baja, casi siempre significa algo.
### La decisión de peso (2): qué es «renovar»
La segunda decisión es la que sostiene todo el análisis de la semana, y es tuya: definir qué significa renovar. Ya sabes que no hay una columna «renovó»; hay que deducirlo. Y no es tan obvio como parece, porque el anual y el mensual ni siquiera vencen igual: el anual dura doce meses, el mensual uno. Necesitas una definición que valga para los dos. La razonable, y la que vas a usar toda la semana, es esta: una suscripción está vencida si su fecha de fin ya ha pasado (a la fecha de extracción de los datos, el 30 de junio de 2024). Y una suscripción vencida renueva si el mismo socio arranca otra suscripción distinta que empieza en los treinta días siguientes a ese fin. Treinta días de margen para no penalizar al socio que renovó con un hueco de una semana por despiste, pero sin contar como renovación una alta seis meses después, que ya es un socio nuevo.
Fíjate en por qué esta definición es tan importante y por qué la decides tú y no viene dada. Si la definieras mal —por ejemplo, contando como churn (fuga) a quien renovó con dos semanas de hueco, o contando como renovación una nueva alta medio año después—, el análisis entero saldría torcido y no lo notarías, porque la cifra tendría buena pinta igual. Una mala definición no da error: da un número plausible y equivocado, que es lo más peligroso. Por eso los analistas escriben la definición antes de calcular y la dejan al lado del resultado: «renovación = suscripción vencida que encadena otra en 30 días». Esta semana no vas a implementar todavía la derivación —eso es mañana, en SQL, con un encadenamiento de las suscripciones del socio—, pero la decisión se toma hoy, porque de ella cuelga todo lo demás.
Cierro con las manchas menores que también hay que atender hoy, porque en conjunto ensucian el análisis. Las edades imposibles: hay socios con edad 0, 8 o 150, valores que alguien metió mal; no se borran los socios (siguen siendo socios válidos para casi todo), pero se apartan del cálculo de la edad media poniendo un rango razonable, por ejemplo de 14 a 100 años. El estado de las reservas viene con grafías inconsistentes e incluso con una tilde («asistió», «asistio», «Asistio»), que hay que unificar —y aquí tienes que acordarte de la tilde, porque «asistió» y «asistio» son la misma cosa escrita de dos formas—. Y el tipo de clase, el método de pago y el estado de los pagos vienen igual de sucios y se normalizan de la misma manera. Nada de esto es difícil; todo es necesario. Cuando acabes hoy, tendrás los ingredientes lavados y cortados, y mañana empiezas a cocinar el LTV y la renovación.
### Las fechas, el tipo más traicionero de todos
De las tres familias de suciedad, las fechas merecen un cuidado extra porque son el tipo que más formas tiene de engañarte en silencio. La primera trampa es la ambigüedad del día y el mes: «03/04/2024» ¿es 3 de abril o 4 de marzo? Depende del país que escribió el dato, y si aciertas o fallas, no da error: simplemente registras la fecha equivocada y todos tus cálculos de «cuánto tardó» salen mal por unos días. Por eso hay que decirle a la herramienta que el día va primero (`dayfirst=True`), que es la convención española. La segunda trampa es el idioma del mes, que ya conoces: «12 Mar 2024» solo parsea porque «Mar» es marzo en inglés. La tercera, más sutil, es que una fecha mal parseada a veces no falla: se convierte en una fecha plausible pero equivocada, y se cuela en tus datos sin levantar sospechas. Las fechas son el campo donde más análisis se tuercen por un detalle que nadie miró.
Hay una razón por la que merece la pena convertir las fechas de texto a fecha de verdad en cuanto puedes, en lugar de dejarlas como texto: una vez son fechas, la máquina las entiende como puntos en el tiempo y puedes operar con ellas —restar dos para saber los días que pasan, ordenar cronológicamente, filtrar «los check-ins de las tres primeras semanas»—. Mientras sean texto, «2024-03-12» es solo una cadena de caracteres, y «2024-03-02» le parece «mayor» o «menor» según el orden alfabético, no cronológico, lo cual es una fuente de errores absurdos. Todo el análisis de la asistencia temprana —contar los check-ins entre la fecha de alta y 21 días después— depende de que las fechas sean fechas de verdad, porque necesitas restar y comparar en el tiempo. Convertir bien las fechas no es un preliminar aburrido: es lo que habilita el corazón del caso.
Comprueba siempre que tus fechas parseadas tienen sentido antes de fiarte de ellas: mira la más antigua y la más reciente. Si al parsear la fecha de alta te sale una fecha en el año 2050 o en 1970, algo ha ido mal en el formato y lo has convertido en una fecha absurda sin que salte ningún error. Un rango de fechas que abarca desde 2023 hasta mediados de 2024 tiene sentido para dieciocho meses de datos; uno que llega al año 2050 grita que hay un formato mal interpretado. Este chequeo de dos segundos —mirar el mínimo y el máximo de una columna de fechas recién parseada— caza los desastres de parseo antes de que contaminen todos los cálculos de tiempo que vienen después.
### Un hueco tiene tres razones, y cada una se trata distinto
Cuando encuentres un valor vacío en una columna, resiste el impulso de tratarlo siempre igual —borrar la fila, o rellenar con un cero, o con la media—. Un hueco puede tener tres razones muy distintas, y confundirlas es de los errores que más silenciosamente estropean un análisis. Primera razón: el dato falta de verdad, se perdió o no se capturó. El número de fotos de un anuncio que se subió sin fotos, la edad de un socio que no la dio. Ahí el hueco es una ausencia real, y hay que decidir qué hacer (a veces rellenar con un valor razonable, a veces excluir del cálculo). Segunda razón: el hueco significa algo, es información disfrazada de ausencia. La fecha de baja vacía que significa «sigue de alta». Ahí no se rellena ni se borra: se convierte en una bandera explícita. Tercera razón: el hueco no aplica, la pregunta no tenía sentido para esa fila —el motivo de baja de quien no se ha dado de baja—.
La consecuencia práctica es que, ante cada columna con huecos, hay que hacerse la pregunta antes de actuar: ¿por qué está vacío esto? Y la respuesta casi nunca está en el dato: está en entender el negocio. Que la fecha de baja vacía signifique «de alta» no lo deduces mirando la columna, lo entiendes sabiendo cómo funciona una suscripción. Por eso limpiar bien exige conocer el dominio, no solo la sintaxis de Pandas: la misma operación técnica (rellenar un nulo) puede ser correcta o desastrosa según lo que ese nulo signifique. Rellenar con cero el número de fotos que faltan puede ser razonable; rellenar con una fecha la baja que está vacía inventa una baja que no ocurrió y te carga a la mitad de los socios activos. La técnica es idéntica; el criterio, opuesto. Y el criterio viene de entender qué representa el dato.
### Las tres familias de la limpieza
Toda la suciedad que vas a arreglar hoy, por variada que parezca, cae en tres familias, y reconocerlas te da un método en vez de un caos de arreglos sueltos. La primera familia es la de los tipos mal leídos: cosas que deberían ser números o fechas y llegan como texto porque traen algo pegado (el euro, la coma, el formato de fecha raro). Se arreglan convirtiendo: limpiar los caracteres sobrantes y transformar al tipo correcto. La segunda familia es la de las categorías inconsistentes: la misma cosa escrita de muchas formas (el plan en ocho grafías, la sede en veinticinco). Se arreglan normalizando: colapsar todas las variantes en un valor canónico. Y la tercera es la de los valores problemáticos: outliers imposibles, duplicados, nulos. Se arreglan con criterio: apartar, deduplicar o interpretar según lo que signifiquen. Casi cualquier mancha que encuentres en tu carrera es una de estas tres.
Ver la limpieza como tres familias, y no como una lista infinita de problemas, te ordena el trabajo y te da una checklist mental para cualquier fichero nuevo: ¿hay tipos mal leídos? ¿hay categorías inconsistentes? ¿hay valores problemáticos? Recorres las tres y no se te escapa nada. Y hay un orden natural entre ellas: normalmente conviene arreglar primero los tipos (para poder operar con los datos), luego las categorías (para poder agrupar), y dejar los valores problemáticos —outliers, nulos— para el final, cuando ya ves los datos limpios y puedes juzgar mejor qué es error y qué es señal. Este orden no es sagrado, pero tener un orden te evita el ir y venir caótico de tocar aquí y allá sin plan. Un limpiador con método es más rápido y comete menos errores que uno que va apagando fuegos.
### Limpiar debe ser reproducible, no artesanal
Hay una tentación peligrosa cuando encuentras un dato raro: arreglarlo a mano. Ves que un socio tiene la edad 150, y te dan ganas de abrir el fichero, buscar esa fila y corregirla. No lo hagas nunca. La limpieza tiene que ser código —un conjunto de pasos escritos que transforman el fichero sucio en uno limpio— y no toques manuales, por una razón de peso: el mes que viene llegará una exportación nueva, con los mismos problemas, y si limpiaste a mano tendrás que volver a hacer todo el trabajo de memoria, cometiendo errores distintos cada vez. Si limpiaste con código, vuelves a pasar el mismo código y listo. Un arreglo a mano sirve una vez; un paso de limpieza escrito sirve siempre. Esta es, por cierto, una de las fronteras donde la hoja de cálculo se queda corta frente a Pandas o SQL: en la hoja tocas celdas, y eso no se puede repetir; en código escribes transformaciones, y eso se repite infinitas veces igual.
Ligada a esta idea hay una propiedad que conviene buscar: la idempotencia, una palabra técnica para algo sencillo. Un proceso es idempotente si aplicarlo dos veces da el mismo resultado que aplicarlo una. Tu limpieza debería serlo: si pasas el código de limpieza sobre datos ya limpios, no debería estropear nada. Normalizar «anual» (que ya está limpio) debe dejarlo en «anual», no romperlo. Convertir a fecha algo que ya es fecha no debería fallar. Buscar la idempotencia te protege de un error clásico: ejecutar la limpieza dos veces por accidente y acabar con datos doblemente transformados —importes divididos dos veces, fechas desplazadas—. Escribir la limpieza pensando «¿qué pasa si esto corre dos veces?» es una disciplina que separa el código que aguanta del que un día, en producción, hace algo raro que nadie entiende.
Consejo de senior: nunca edites el fichero de datos crudo a mano, ni siquiera para un arreglo pequeño. El crudo es sagrado: es la fuente, y debe quedar intacto para poder rehacer la limpieza si te equivocas o si cambias de criterio. Toda transformación va en código, sobre una copia, dejando el original sin tocar. El día que borres o edites el crudo y luego necesites volver a él, entenderás por qué esta regla no es manía: es la red de seguridad que te deja equivocarte sin consecuencias irreversibles.
### Basura entra, basura sale: el coste silencioso del dato sucio
Hay una frase vieja en el mundo de los datos, de los tiempos de las primeras computadoras: «basura entra, basura sale» (en inglés, «garbage in, garbage out»). Significa que ningún cálculo, por sofisticado que sea, arregla unos datos malos: si metes basura, sacas basura, solo que con la apariencia de un resultado. Es la razón por la que la limpieza no es un paso menor antes del análisis «de verdad»: es parte del análisis, y a menudo la parte donde se decide si el resultado vale o no. Un modelo carísimo alimentado con datos sucios da peores respuestas que una cuenta sencilla sobre datos limpios. En este oficio, la calidad de la salida está limitada por la calidad de la entrada, siempre.
Lo traicionero del dato sucio es que casi nunca da error: da un número. Si sumas los precios sin convertir el texto «39,00 €» a número, la mayoría de las herramientas o bien fallan (y al menos te enteras) o bien hacen algo raro que no esperabas. Pero el caso peligroso es el más sutil: si no unificas las ocho grafías del plan y agrupas tal cual, no salta ningún error; simplemente tienes ocho grupos en vez de dos, y tu «renovación del anual» se calcula solo sobre las filas que ponían exactamente «anual», ignorando «Anual», «ANUAL» y «año». El número que sale es plausible, tiene sus decimales, y está mal. Nadie te avisa. Por eso limpiar antes de calcular no es ser puntilloso: es la única forma de que el número en el que vas a basar una decisión de presupuesto sea el número de verdad.
### Outliers: el valor que grita y el que susurra
Un outlier —un valor atípico— es un dato que se sale muchísimo de lo normal, y hay que tratarlo con cuidado porque puede ser dos cosas muy distintas. Puede ser un error: la edad 150, el importe de 9.999 €, el pago de 0 €. Esos no son personas de 150 años ni cuotas de casi diez mil euros; son fallos de captura, y hay que apartarlos del cálculo que ensucian. O puede ser un dato real y valioso: un socio que viene 25 veces en tres semanas es un outlier de asistencia, pero es real y es justo el tipo de socio que más renueva, así que ni se te ocurra borrarlo. La destreza está en distinguir el outlier que es error del que es señal, y para eso hay que conocer el negocio: sabes que 150 años es imposible, pero que 25 visitas es un fanático del gimnasio, no un fallo.
El outlier que grita es fácil: el 150, el 9.999, saltan a la vista en cuanto miras el máximo y el mínimo de una columna. El que susurra es más peligroso: un importe de 0 € se esconde entre los valores bajos y no llama la atención, pero un pago de cero no es un pago, y si lo cuentas en el LTV lo tiras hacia abajo sin que lo notes. Por eso, al limpiar una columna numérica, no basta con mirar la media: hay que mirar los extremos (el mínimo y el máximo) y a menudo la distribución completa, porque los outliers que susurran viven en los bordes. La costumbre de mirar mínimo y máximo de cada columna numérica antes de usarla es de las que más disgustos ahorra: es un vistazo de dos segundos que caza el 0 y el 9.999 antes de que contaminen una media.
Y una decisión de criterio que se repite: cuando encuentras un outlier que es error, ¿borras la fila entera o solo apartas ese valor del cálculo afectado? Casi siempre, lo segundo. Un socio con la edad mal puesta sigue siendo un socio válido para contar altas, renovación o pagos; solo su edad está mal, así que lo apartas del cálculo de la edad media y lo dejas en todo lo demás. Borrar la fila entera por un campo malo es tirar información buena junto con la mala. Limpiar con bisturí —apartar solo lo que está mal, del cálculo que afecta— en vez de con hacha —borrar la fila— es lo que distingue una limpieza cuidadosa de una que se lleva por delante datos que valían.
Consejo de senior: antes de usar cualquier columna numérica en un cálculo, mira su mínimo, su máximo y su media de un vistazo (un `.describe()` los da todos). Si el máximo o el mínimo no tienen sentido para el negocio —una edad de 150, un importe de 0—, tienes outliers que apartar antes de promediar. Este chequeo de dos segundos evita el clásico «la edad media me sale rarísima» que luego resulta ser un puñado de 150 tirando de la media. Mirar los extremos es más rápido que explicar después por qué el promedio estaba contaminado.
Consejo de senior: normaliza siempre pasando primero a minúsculas y quitando espacios, y solo después mapea. Escribir el mapeo con todas las mayúsculas posibles («Anual», «ANUAL», «anual»...) es frágil: el día que aparezca «AnuAl» se te escapa. En cambio, si primero haces .str.strip().str.lower(), todas esas variantes colapsan en «anual» y tu mapeo solo necesita una entrada por categoría. Menos código y más robusto: la marca de un analista que ha limpiado datos suficientes como para saber que siempre aparece una grafía nueva.
Consejo de senior: cuando conviertas un vacío con significado en una bandera, ponle un nombre que diga la verdad («activa», «sigue_de_alta») y no un nombre técnico («fecha_baja_nula»). Esa columna la van a leer otras personas y tu yo futuro, y el nombre es la mitad de la documentación que este proyecto no tiene. Un buen nombre de columna evita media reunión de «¿y esto qué significa?».
Regístrate para guardar tu progreso.