Estadística en Python: Pandas, NumPy, SciPy (Parte I)

Recientemente SciPy anunció que lanzaba la versión 1.0 tras 16 años en desarrollo. Con motivo de este acontecimiento voy a realizar una serie de tutoriales sobre estadística en Python. Quiero hacer especial énfasis en la resolución de problemas estadísticos, con problemas reales que vamos a ir resolviendo. Usaremos Python 3, NumPy, Pandas, SciPy y Matplotlib entre otras.

¿Por qué Python para estadística?

Python se ha convertido en uno de los lenguajes más usados en la comunidad de data science. Se trata de un lenguaje cómodo para los matemáticos, sobre el que es fácil iterar y cuenta con unas librerías muy maduras.

Instalando el stack estadístico en Python

Yo voy a usar Python 3. Tanto si estamos en Windows, macOS o Linux podemos instalar NumPy, SciPy, Pandas y Matplotlib con este simple comando

¿Para qué sirve cada cosa?

NumPy sirve para realizar cálculos numéricos con matrices de forma sencilla y eficiente y tanto SciPy como Pandas la usan de forma interna. NumPy es la base del stack científico de Python.

SciPy es una colección de módulos dedicados a diversas áreas científicas. Nosotros usaremos principalmente el módulo stats.

Pandas es una librería que permite manipular grandes conjuntos de datos en tablas con facilidad. Además permite importar y exportar esos datos.

Matplotlib permite realizar gráficos y diagramas con facilidad, mostrarlos en pantalla o guardarlos a archivos.

Estadística descriptiva

Vamos a comenzar con la parte de la estadística que trata de darnos un resumen del conjunto de datos.

Para ello vamos a definir el concepto de variable estadística como la magnitud o cualidad de los individuos que queremos medir (estatura, calificaciones en el examen, dinero en la cuenta,…). Las variables pueden ser cualitativas o cuantitativas y dentro de las cuantitativas pueden ser continuas y discretas.

Fichero de ejemplo

En este post voy a usar este fichero para los ejemplos (guardalo como notas.csv).

Cargando datos

Para cargar datos y manipular los datos usamos Pandas. Pandas permite cargar datos de distintos formatos: CSV, JSON, HTML, HDF5, SQL, msgpack, Excel, …

Para estos ejemplos usaremos CSV, valores separados por comas:

df es un objeto de tipo DataFrame. Es la base de Pandas y como veremos, se trata de un tipo de dato muy flexible y muy fácil de usar. Si ahora hacemos print a df obtenemos algo así:

Tabla de frecuencias

Si tenemos una variable discreta o cualitativa una cosa habitual que se suele hacer es construir la tabla de frecuencias. Con ella sabemos cuantas veces se repite el valor de la variable. Para crear tablas de frecuencia usamos crosstab. En index indicamos la variable que queremos contar y en columns especificaos el nombre de la columna de salida. crosstab devuelve otro DataFrame independiente.

Ejemplo: ¿Cuántos alumnos han sacado un 5 en el examen?

Ejemplo: ¿Cuántos alumnos han aprobado (sacar 5 o más)?

En estos ejemplo usamos loc para devolver las filas que cumplan la condición descrita entre corchetes. En el último ejemplo como el resultado son varias filas, nos quedamos con la parte de las frecuencias y sumamos todo, para así obtener el resultado final.

Diagrama de sectores

Una forma sencilla de visualizar datos que ya han sido pasados por la tabla de frecuencias es el diagrama de sectores. Usando Matplotlib podemos generar gráficos en los que podemos personalizar todo, pero cuyo uso básico es extremadamente simple.

Gráfica generada por Matplotlib

Ejemplo: Haz un diagrama de sectores donde se vea claramente el porcentaje de aprobados frente al de suspensos

Destacar que aquí hemos usado np.array para crear un array de NumPy en vez de una lista nativa de Python.

Diagrama de barras

De forma similar es posible generar un diagrama de barras:

Ejemplo: Genere un diagrama de barras de las notas obtenidas por los alumnos en el examen

 

 

Fliuva, o como crear un servicio de analíticas

Ya hemos visto los motivos que tengo para diseñar un servicio de analíticas desde 0. Ahora veremos como lo he hecho.
Fliuva

No he tocado ningún CSS.

La base de datos

En un servicio de analíticas lo más importante son los datos, así que debemos de definir como almacenaremos la información. En principio Fliuva iba a estar centrado en analizar una única aplicación. Más tarde he pensado en un soporte multiaplicaciones pero no lo voy a desarrollar de momento. Usaría un espacio de nombres delante de todas las tablas y las peticiones GET.

Usuarios = Sesiones

En ciertos servicios de analíticas los usuarios y las sesiones son dos conceptos diferentes. En Fliuva sin embargo, y por razones de simplificar la estructura, ambos conceptos son idénticos y hablaremos de ellos como sesiones.

Tablas

Será necesario tener una tabla de eventos.

Events

  • CATEGORY: Categoría del evento
  • SUBCATEGORY: Subcategoría del evento
  • NAME: Nombre del evento
  • DESCRIPTION: Descripción del evento
  • DATA: Datos del evento
  • ID: Identificador
  • TIME: Hora en que se produjo
  • SESSION: Sesión a la que pertenece el evento

 

Y ya con esta tabla tendremos para almacenar muchos datos. Los campos CATEGORY, SUBCATEGORY, NAME, DESCRIPTION y DATA sirven unicamente para organizar eventos y subeventos en categorías. Los nombres de los campos son triviales. DESCRIPTION no guarda realmente la descripción sino que podemos definir otro subevento. Con 5 campos para categorizar eventos superamos a Google Analytics que tiene CATEGORY, ACTION, LABEL y VALUE. Además VALUE debe ser numérico mientras que en Fliuva todos son de tipo texto (en la práctica, cualquier cosa).

Código de seguimiento

¿Cómo introducir datos en la base de datos desde nuestra aplicación? Con una pequeña llamada GET a /collect. Yo la he definido en un fichero llamado collect.js

Y se llama muy fácilmente

Si estamos en HTML5, necesitaremos una librería de cliente para poder realizar las llamadas

Así, simplemente hay que llamar a sendEvent. Llamar a login no es necesario siempre que rellenes el valor de sessionStorage.__fliuvaSession correctamente.

Análisis de datos

Ahora debemos analizar los datos. Primero debemos obtener los valores a analizar. La llamada a /get devuelve un fichero JSON con la información completa. En un futuro lo ideal sería espeficicar intervalos de fechas.

Y en el cliente tratamos los datos. Aquí es donde debemos nosotros mismos crear las estadísticas según las métricas que hayamos definido. Yo solo voy a poner una métrica universal, usuarios por día.

Que se corresponde a este pequeño HTML

Visualizar cada sesión por separado es posible con la llamada a /session/NOMBRE_DE_SESION

Y para un rápido procesamiento he decidido usar Jade con JavaScript en el servidor. Y entonces session.jade queda

Juntando piezas

Por último, la aplicación se tiene que iniciar en algún lado. Server.js contiene el arranque

Y así en un pis pas hemos hecho una aplicación de seguimiento y analíticas en JavaScript. Ahora toca empezar a diseñar estadísticas con los datos que tenemos a nuestra disposición y por supuesto cuando tengamos los datos a obrar en consecuencia.

La información es poder

La información es poder. La frase suele atribuirse a Francis Bacon y creo que en estos tiempos cada vez se vuelve más cierta. Términos como Big Data, políticas de privacidad y similares son términos para hablar del gran poder que nos ofrece la información, si la sabemos interpretar y usar en consecuencia.

Obteniendo la información

Esto venía para explicar que finalmente y después de pensarlo un rato he decidido crear mi propio sistema de analíticas para Secta Sectarium. Las analíticas pueden ofrecerme valiosa información pero no encontré ningún servicio que me gustase. Muchos sistemas de analíticas están centrados en blogs (como Google Analytics o New Relic Browser) o en aplicaciones móviles (Google Analytics, Flurry). ¿Había algún servicio dedicado solo a juegos? Sí, GameAnalytics es específico pero no tiene API para HTML5 (y las APIs REST no se pueden llamar entre dominios en HTML5, CORS se llama la idea). Google Analytics se puede modificar lo suficiente para funcionar pero ya que tenía que trabajarmelo he preferido crear mi propia solución.

LaGenteSeInventaEstadisticas

Fliuva

Así que he decidido gastar una gear de OpenShift para una aplicación Node.js 0.12 y MySQL 5.5. Entre SQL y NoSQL he elegido SQL porque para introducir datos de eventos que luego, posteriormente, van a ser tratados, SQL da un mejor rendimiento y el esquema de tabla es más común. Las analíticas las podré ver desde la propia aplicación, que usa Vis.js para la visualización.

LaPersonaMasPoderosa

En próximas entradas veremos como se puede crear Fliuva y que métricas son más importantes.