El módulo 10 terminó con una advertencia: al abrir Papyrus al mundo, la web empezó a generar datos. Cada venta que Marta registra, cada búsqueda que Júlia teclea, cada visita a una ficha de libro deja rastro. Y con el rastro llegaron las preguntas de Ana: ¿qué títulos se consultan mucho pero se compran poco?, ¿qué día de la semana vende más?, ¿cuánto stock conviene pedir de cara a Sant Jordi? Ninguna de esas preguntas se responde programando la tienda: se responden entendiendo sus números. Ese oficio se llama ciencia de datos, y este módulo te da sus tres herramientas fundamentales — NumPy, pandas y Matplotlib — más una primera mirada honesta al aprendizaje automático. Esta lección prepara el terreno: qué es (y qué no es) la ciencia de datos, cómo se trabaja, qué piezas forman el ecosistema y con qué dataset vamos a responder las preguntas de Ana.

Contenido

  1. Qué es la ciencia de datos (y qué no es)
  2. El flujo de trabajo: de la pregunta a la conclusión
  3. Los roles del oficio: analista, científico e ingeniero de datos
  4. El ecosistema PyData: qué pieza hace qué
  5. Jupyter Notebook: el entorno habitual del análisis
  6. El dataset del módulo: ventas_2026.csv
  7. Lo que ya sabes hacer: statistics y sus límites

Qué es la ciencia de datos (y qué no es)

La ciencia de datos es la disciplina de extraer conocimiento útil de los datos para responder preguntas y tomar decisiones. Combina tres ingredientes que, por separado, ya conoces o intuyes:

  • Programación — para leer, transformar y automatizar. Es lo que llevas 10 módulos haciendo.
  • Estadística — para resumir, comparar y no engañarse con el azar.
  • Conocimiento del negocio — Ana sabe que Sant Jordi (23 de abril) es su pico anual; ningún algoritmo lo sabe si nadie se lo cuenta.

Igual de importante es lo que no es:

Mito Realidad
"Es hacer gráficos bonitos" El gráfico es el final; el 80% del trabajo es conseguir y limpiar datos
"Es inteligencia artificial" El ML es una herramienta más (la veremos en 11-05); la mayoría de preguntas se responden contando y agrupando bien
"Necesitas big data" Papyrus tiene cientos de filas, no millones, y aun así hay decisiones valiosas que tomar
"Es magia predictiva" Un modelo solo proyecta patrones del pasado; si el futuro cambia (una pandemia, una moda), el modelo no lo ve venir

El flujo de trabajo: de la pregunta a la conclusión

Todo análisis serio recorre el mismo camino, y conviene tenerlo delante antes de escribir una línea de código. Con las preguntas de Papyrus como ejemplo:

flowchart LR
    A["1. Pregunta<br>¿Cuánto stock pedir<br>para Sant Jordi?"] --> B["2. Datos<br>ventas_2026.csv<br>logs de la web (M10)"]
    B --> C["3. Limpieza<br>filas corruptas,<br>duplicados, huecos"]
    C --> D["4. Exploración<br>agrupar, resumir,<br>visualizar"]
    D --> E["5. Conclusión o modelo<br>'pide ~220 unidades,<br>El Quijote el que más'"]
    E -.->|nuevas preguntas| A

Fíjate en la flecha de vuelta: explorar los datos casi siempre genera preguntas nuevas ("¿por qué Fausto se consulta tanto y se vende tan poco?"), y el ciclo vuelve a empezar. No es una cadena de montaje: es un bucle.

El reparto del módulo sobre este flujo: la limpieza y exploración son territorio de pandas (11-03), la visualización de Matplotlib (11-04), el modelo de scikit-learn (11-05), y NumPy (11-02) es el motor numérico que sostiene a todos.

Los roles del oficio

"Ciencia de datos" es un paraguas. En una empresa real el trabajo se reparte en (al menos) tres perfiles; en Papyrus los tres son Ana con distintos sombreros:

Rol Pregunta típica En Papyrus Herramientas estrella
Analista de datos ¿Qué pasó y por qué? "¿Qué día vendemos más?" pandas, SQL, Matplotlib
Científico de datos ¿Qué pasará? ¿Qué decisión tomo? "¿Cuántas unidades pedir en abril?" pandas, scikit-learn, estadística
Ingeniero de datos ¿Cómo llegan los datos limpios y a tiempo? El script que consolida ventas de tienda y web cada noche Python, pipelines (¡tus generadores de M8!), bases de datos

Este módulo te da la base de los dos primeros roles; del tercero ya tienes más de lo que crees: leer CSV (M6), pipelines con generadores (M8) y una web que produce datos (M10) es ingeniería de datos a pequeña escala.

El ecosistema PyData

Todas estas piezas se instalan con pip en tu entorno virtual de M1 (pip install numpy pandas matplotlib scikit-learn). Cada una tiene un papel claro:

Módulo Rol en el flujo Lección
NumPy Arrays numéricos rápidos; el motor que todos los demás usan por debajo 11-02
pandas Tablas (DataFrames): cargar, limpiar, agrupar, unir — el csv.DictReader de M6 con esteroides 11-03
Matplotlib Gráficos: convertir números en historias que Ana entienda de un vistazo 11-04
scikit-learn Aprendizaje automático: modelos que aprenden patrones del histórico 11-05
Jupyter El entorno interactivo donde todo lo anterior se explora cómodamente aquí mismo

La dependencia entre ellas no es casual: pandas está construido sobre NumPy, Matplotlib dibuja arrays de NumPy, y scikit-learn espera arrays de NumPy o DataFrames de pandas como entrada. Por eso el módulo empieza por NumPy aunque en el día a día escribas sobre todo pandas.

Jupyter Notebook, brevemente

El análisis de datos es conversacional: pruebas algo, miras el resultado, ajustas, repites. Los notebooks están hechos para eso: documentos vivos con celdas de código que se ejecutan una a una, intercaladas con texto y gráficos que quedan guardados junto al código.

pip install notebook
jupyter notebook   # abre el navegador en http://localhost:8888

Dentro, cada celda se ejecuta con Shift+Enter y su resultado aparece debajo — la última expresión de la celda se muestra sola, sin print(). ¿Cuándo usar cada formato?

Situación Notebook (.ipynb) Script (.py)
Explorar datos, probar hipótesis Ideal Incómodo (relanzar todo cada vez)
Informe con código, texto y gráficos Ideal No aplica
Código de producción (la web de M10, el paquete papyrus) Mala idea Ideal
Tests (M9), control de versiones limpio Difícil de testear y de diffear Ideal
Ejecutar cada noche automatizado Posible pero forzado Ideal

Todo el código de este módulo funciona igual en un script .py — si prefieres seguir con tu editor de siempre, adelante. El notebook es una comodidad, no un requisito. La única diferencia práctica: en un script, para ver un DataFrame tendrás que envolverlo en print().

El dataset del módulo: ventas_2026.csv

En M6 creaste datos/ventas.csv (columnas fecha,titulo,importe). Desde M10, además, la web registra sus propias ventas. Ana ha consolidado ambos orígenes — el trabajo de ingeniero de datos de la tabla anterior — en un único fichero que usaremos todo el módulo: datos/ventas_2026.csv, con las ventas de enero a junio de 2026.

Columna Tipo Significado
fecha fecha yyyy-mm-dd Día de la venta
titulo texto Uno de los 4 títulos del catálogo
unidades entero Ejemplares vendidos en esa operación
importe decimal Total cobrado (si el cliente es socio, aplica la tarifa de socio de M3)
canal texto tienda (caja física) o web (la tienda de M10)

Así empieza el fichero (que tiene 487 filas en total):

fecha,titulo,unidades,importe,canal
2026-01-02,La Odisea,1,12.50,tienda
2026-01-02,Hamlet,2,19.90,web
2026-01-03,El Quijote,1,15.71,tienda
2026-01-03,Fausto,1,21.00,web
2026-01-05,El Quijote,2,31.80,tienda
...
2026-04-23,El Quijote,3,47.70,tienda
2026-04-23,La Odisea,2,25.00,web
...

Dos detalles que ya puedes leer con lo aprendido: la fila del 3 de enero cobra 15.71 por El Quijote — la tarifa de socio que calculaste en M3 (15.90 con IVA del 4 % y descuento de socio del 5 %: 15.90 * 1.04 * 0.95 ≈ 15.71) — y las filas del 23 de abril se acumulan sospechosamente: es Sant Jordi.

Lo que ya sabes hacer: statistics y sus límites

Antes de instalar nada nuevo, seamos justos con la biblioteca estándar. Con csv.DictReader (M6) y el módulo statistics (M3) ya puedes responder preguntas sencillas:

import csv
import statistics
from collections import Counter
from pathlib import Path

importes = []
titulos = []
with open(Path("datos") / "ventas_2026.csv", encoding="utf-8", newline="") as f:
    for fila in csv.DictReader(f):
        importes.append(float(fila["importe"]))
        titulos.append(fila["titulo"])

print(f"Ventas registradas: {len(importes)}")
print(f"Importe medio:   {statistics.mean(importes):.2f} €")
print(f"Importe mediano: {statistics.median(importes):.2f} €")
print(f"Título más frecuente: {Counter(titulos).most_common(1)}")
Ventas registradas: 487
Importe medio:   15.03 €
Importe mediano: 12.50 €
Título más frecuente: [('El Quijote', 168)]

Ya hay una lección estadística aquí: la media (15.03 €) es mayor que la mediana (12.50 €). Unas pocas ventas grandes (packs de Fausto a 21 € o el aluvión de Sant Jordi) tiran de la media hacia arriba; la mediana — el valor central — resiste mejor esos extremos. Cuando alguien te dé "el promedio", pregunta siempre cuál de los dos es.

Ahora los límites. Intenta responder "¿qué día de la semana vende más?" con la stdlib:

from datetime import date

por_dia = Counter()
with open(Path("datos") / "ventas_2026.csv", encoding="utf-8", newline="") as f:
    for fila in csv.DictReader(f):
        dia = date.fromisoformat(fila["fecha"]).weekday()   # 0=lunes ... 6=domingo
        por_dia[dia] += int(fila["unidades"])
print(por_dia)

Funciona — y en 11-03 comprobaremos que da sábado como ganador. Pero fíjate en el coste: conversión de tipos a mano en cada fila, un Counter por cada pregunta, y si ahora quieres "unidades por día de la semana y por canal, solo de socios, ordenado" el código crece en bucles anidados. Y todo es texto: "12.50" no se puede sumar hasta que tú lo conviertas, fila a fila. La ciencia de datos hace estas preguntas por docenas; necesitas herramientas donde cada pregunta cueste una línea, no un bucle. Eso son NumPy y pandas.

Errores Comunes y Consejos

  • Saltarse la pregunta e ir directo al código. El error número uno. "Analizar los datos" no es un objetivo; "decidir cuántas unidades pedir para Sant Jordi" sí. Escribe la pregunta antes de abrir el editor.
  • Instalar las librerías fuera del entorno virtual. Los pip install de este módulo van dentro del venv del proyecto (M1). Si import pandas falla con ModuleNotFoundError, casi seguro que el entorno no está activado.
  • Confundir media y mediana. Con datos asimétricos (y las ventas casi siempre lo son) cuentan historias distintas. Reporta ambas, o al menos sé consciente de cuál usas y por qué.
  • Fiarse de datos que no has mirado. Antes de calcular nada, abre el CSV y lee 20 filas. Fechas imposibles, importes negativos o títulos mal escritos se detectan antes con los ojos que con código.
  • Ejecutar celdas de notebook en desorden. El estado vive en memoria: si ejecutas la celda 5 antes que la 3, los resultados pueden ser incoherentes. Ante la duda: Kernel → Restart & Run All.

Ejercicios

  1. Clasifica estas tareas de Papyrus según el rol (analista, científico o ingeniero de datos) que mejor encaja: (a) un script nocturno que vuelca las ventas de la web de Django al CSV consolidado; (b) un informe mensual de unidades vendidas por título; (c) estimar cuántos ejemplares de El Quijote se venderán el próximo Sant Jordi.
  2. Con csv.DictReader y statistics, calcula el importe medio de las ventas de ventas_2026.csv solo del canal web y compáralo con el del canal tienda. ¿Qué hipótesis se te ocurre para explicar la diferencia?
  3. Sin escribir código: para la pregunta "¿qué títulos se consultan en la web pero no se compran?", ¿qué datos necesitas además de ventas_2026.csv? ¿En qué paso del flujo de trabajo estás al darte cuenta de que te falta información?

Soluciones

  1. (a) Ingeniero de datos: mueve y consolida datos, no responde preguntas. (b) Analista: describe qué pasó. (c) Científico de datos: predice y apoya una decisión. En Papyrus las tres tareas las hace la misma persona; los roles describen el tipo de trabajo, no un carné.
  2. import csv, statistics
    from pathlib import Path
    
    web, tienda = [], []
    with open(Path("datos") / "ventas_2026.csv", encoding="utf-8", newline="") as f:
        for fila in csv.DictReader(f):
            destino = web if fila["canal"] == "web" else tienda
            destino.append(float(fila["importe"]))
    
    print(f"web:    {statistics.mean(web):.2f} € en {len(web)} ventas")
    print(f"tienda: {statistics.mean(tienda):.2f} € en {len(tienda)} ventas")
    
    Hipótesis razonables (¡a verificar en 11-03, no a dar por ciertas!): en tienda se compran más unidades por operación (Marta recomienda en persona), o en la web pesan más los títulos baratos. Formular hipótesis comprobables es exactamente el paso 4 del flujo.
  3. Necesitas las visitas a las fichas de libro — están en los logs de la web de M10 (cada request a /libro/<titulo> deja rastro), no en el CSV de ventas. Te das cuenta en el paso 2 (datos): la pregunta compara dos magnitudes (consultas y compras) y solo tienes una. Volver de la exploración a la búsqueda de datos es el bucle del diagrama funcionando.

Conclusión

Ya tienes el mapa: la ciencia de datos es responder preguntas con datos siguiendo el ciclo pregunta → datos → limpieza → exploración → conclusión; el ecosistema PyData reparte el trabajo entre NumPy (números), pandas (tablas), Matplotlib (gráficos) y scikit-learn (modelos); Jupyter es la mesa de trabajo habitual aunque todo funcione en scripts; y ventas_2026.csv — 487 ventas de enero a junio, con Sant Jordi latiendo el 23 de abril — es el material sobre el que responderemos las preguntas de Ana. También viste el límite: statistics y Counter llegan hasta donde llegan, y cada pregunta nueva cuesta otro bucle con conversiones a mano. La raíz del problema es que las listas de Python no saben de matemáticas: sumar dos listas las concatena, no suma sus números. La próxima lección presenta la estructura que sí sabe: el array de NumPy, donde importes * 1.04 hace en una línea — y mil veces más rápido — lo que hasta ahora exigía un bucle.

Curso de Programación en Python

Módulo 1: Introducción a Python

Módulo 2: Estructuras de Control

Módulo 3: Funciones y Módulos

Módulo 4: Estructuras de Datos

Módulo 5: Programación Orientada a Objetos

Módulo 6: Manejo de Archivos

Módulo 7: Manejo de Errores y Excepciones

Módulo 8: Temas Avanzados

Módulo 9: Pruebas y Depuración

Módulo 10: Desarrollo Web con Python

Módulo 11: Ciencia de Datos con Python

Módulo 12: Proyecto Final

© Copyright 2026. Todos los derechos reservados