Aprendiendo de los datos-Análisis Exploratorio-Part 1

El título de la entrada se refiere hacer con los datos algunas gráficas, de las cuales uno puede ir analizando posibles relaciones o visualizando conexiones entre ciertas variables. Esto se llama “Análisis Exploratorio”.

Muchas de las técnicas de Machine Learning tienen su contra parte gráfica; es decir, existe algún recurso gráfico para visualizar el resultado del uso de los algoritmos.

En la entrada trato de mostrar ejemplos de las herramientas gráficas estándar, tanto con R project, como con Python. De cierto modo trato de ir de ejemplos gráficos sencillos a herramientas gráficas más sofisticadas, hasta quizás acercarme a mostrar algunos ejemplos de visualización de datos.

Esto último es quizás sumamente atractivo como campo de trabajo y herramienta para trasmitir descubrimientos o hacer amigable ciertas relaciones entre variables analizadas, ya que permite diseñar algunas gráficas interactivas. Lo malo es que en general las mejores herramientas de visualización; son herramientas web y requieren explicaciones totalmente distintas. Pero mi recomendación es visitar la página de D3 y hacer algunos de los ejemplos para darse una idea general. Ahora hay muchas herramientas de visualización de datos, pero al final ciertas gráficas son las básicas y suelen ser las más útiles.

Análisis Exploratorio

Como todo visionario, muchos años antes de que el poder de las computadoras estuvieran en nuestra sala, teléfono y en el día a día, Jhon W. Tukey auguró desde antes de 1977 en su libro “Exploratory Data Analysis”, la relevancia de dedicarse a la investigación de diseño de herramientas gráficas para visualizar relaciones estadísticas. De cierto modo, dejando como primera etapa hacer una análisis exploratorio entre las variables analizar y posteriormente hacer una análisis confirmatorio.

Así que la relevancia que tiene hacer un previo análisis gráfico es fundamental, pero no siempre es determinante. Con esto quiero decir que si bien una gráfica facilita la visualización de relaciones entre variables, esto no lo confirma. Por lo cual es bueno posteriormente hacer pasar nuestra hipótesis por alguna técnica estadística que respalde nuestro descubrimiento.

Existe un libro sobre la construcción de gráficas en español del Dr. Juan Carlos Correa de la Universidad de Medellín [2], el cual está disponible en la red de manera gratuita. De este libro tomo los principios de William Playfair sobre el análisis gráfico:

Principios.

  • Los métodos gráficos son un modo de simplificar lo tedioso y lo complejo.
  • Los hombres ocupados necesitan algún tipo de ayuda visual.
  • Un gráfico es más  accesible que una tabla.
  • El método gráfico es concordante con los ojos.
  • El método gráfico ayuda al cerebro, ya que permite entender y memorizar mejor.

Teniendo en cuenta que los anteriores principios fueron pensados en 1800, nos debería de hacer pensar en la relevancia que tienen el trasmitir conocimiento por métodos gráficos. Por eso no es sorpresa que siempre contar con algunas gráficas en nuestros reportes o aplicaciones facilita la visualización y entendimiento de los fenómenos o hechos estudiados.

Análisis Exploratorio con R

En R Project, desde su creación se contó con herramientas gráficas diversas y al pasar de los años se han agregado herramientas o librerías sumamente útiles, como lattice, ggplot y ggvis y ahora interfaces gráficas como Shiny.

En esta entrada hago 3 ejemplos, el primero usando las gráficas nativas o base de R, el segundo haciendo uso la librería lattice y el último haciendo uso de la librería ggplot. Y muestro como este último ejemplo se sirve para visualizar de manera interactiva las gráficas haciendo uso de la librería ggvis. Para gráficas de una sola variable hago uso de las nativas y ggplot, para ver relaciones entre varias variables hago uso de lattice y ggplot.

Para cada uno de los ejemplos indico como extraer los datos, el primer ejemplo fue motivado por un ejemplo compartido por el Dr. Yanchang Zhao y el segundo ejemplo fue motivado por Institute for Digital Research and Education de la universidad de California y la referencia [3,4].

 Ejemplo con librerías nativas en R.

Los datos ha usar son Iris, los cuales se encuentran por default en R, los gráficos que explico en breve son para explorar la información de una sola variable.

Boxplot

#Ejemplo
#Cargo los datos para todos los ejemplos
data(iris)
#Tamaño de los datos
dim(iris)
#Tipo de variables
str(iris)
#Conocer las variables
names(iris)

#Boxplot
range(iris$Sepal.Length)
boxplot(iris$Sepal.Length, main="Boxplot de la Longitud de Sepal-Datos Iris", ylab="Tamaño", col="2")

La gráfica anterior los beneficios que tienen es que es fácil de calcular en el sentido computacional, por otro lado de manera rápida uno puede detectar si la distribución de los datos es simétrica o no, puede notar varios detalles sobre los cuantiles y la mediana. Para más detalles pueden verse de manera fácil en wikipedia, si subestiman este sitio como referencia, están subestimando mucha información de calidad. En este ejemplo se hace notar que no es simétrica la distribución y no se detectan valores atípicos.

Boxplot

Jitter-Gráficas de Puntos

Esta gráfica es fácil e informativa, cuando se tienen una buena cantidad de datos se puede ver los puntos de aglomeración, lo cual permite identifica como se comporta la variable analizada. En el ejemplo no muestra claramente algún comportamiento apreciable.

#Ejemplo Jitter
#Se usan los mismo datos de boxplot

stripchart(iris$Sepal.Length, method='jitter',vertical=TRUE,pch=1, col="2", main="Gráfica de Puntos", ylab="Rango de Datos")

#Método 2
stripchart(iris$Sepal.Length, method='overplot',vertical=TRUE,pch=1, col="3", main="Gráfica de puntos", ylab="Rango de Datos")

Gr´ficas_puntosGraficas_puntos2

Histograma y Densidad

Las dos gráficas que más noto que se usan para describir propiedades de alguna variable son los histogramas y las gráficas de densidad. La primera tienen varios detalles que es recomendable revisar, no los comento a detalle, pero hacer variar la cantidad de clases afecta a la construcción del gráfico, por otro lado hacer cambios en considerar la estimación de la frecuencia o de la frecuencia relativa también cambio no de forma , sino de escala. Así que esos detalles se pueden revisar en información de ayudan con el comando help() en la consola de R.

La idea central de estos dos gráficos es presentar una estimación de la densidad de la variable analizada, por eso la forma del histograma y la gráfica de la densidad tienen forma similar.

#Histograma
#Pongo varios ejemplos de como ir agregando parámetros a la gráfica

#Gráfica 1
hist(iris$Sepal.Length)

#Gráfica 2
hist(iris$Sepal.Length,col="2",ylab="Frecuencia", xlab="Longitud del Sépalo", main="Histográma de la Longitud de Sépalo-Datos Iris")

#Gráfica 3
hist(iris$Sepal.Length,col="2",ylab="Frecuencia", xlab="Longitud del Sépalo", main="Histográma de la Longitud de Sépalo-Datos Iris", labels = TRUE)

#Gráfica 4
hist(iris$Sepal.Length,col="2",ylab="Frecuencia", xlab="Longitud del Sépalo", main="Histográma de la Longitud de Sépalo-Datos Iris", labels = TRUE,border="7", nclass=15)

#Gráfica 5-Considerando las frecuencias relativas
hist(iris$Sepal.Length,col="2",ylab="Frecuencia relativa", xlab="Longitud del Sépalo", main="Histográma de la Longitud de Sépalo-Datos Iris", labels = TRUE,border="7", nclass=15, probability = TRUE)
hist(iris$Sepal.Length,col="2",ylab="Frecuencia relativa", xlab="Longitud del Sépalo", main="Histográma de la Longitud de Sépalo-Datos Iris", labels = TRUE,border="7", probability = TRUE)

Hist_1Hist_3
Hist_2

La gráfica de densidad hace una estimación de la densidad, para ello existen  varias funciones ya que la densidad no necesariamente es gausiana o de forma de campana. Lo que determina la aproximación es el tipo de “kernel” que se emplea para estimarla, en general el kernel que se considera como default es gaussiano, pero puede ser modificado. Para ver detalles de las opciones se puede consultar en la información de ayuda en R, poniendo el comando help(density).

#Gráfica de Densidad
#Si se pide estimar la densidad se obtienen lo siguiente
 
density(iris$Sepal.Length)

#Call:
# density.default(x = iris$Sepal.Length)

#Data: iris$Sepal.Length (150 obs.); Bandwidth 'bw' #= 0.2736

# x y 
# Min. :3.479 Min. :0.0001495 
# 1st Qu.:4.790 1st Qu.:0.0341599 
# Median :6.100 Median :0.1534105 
# Mean :6.100 Mean :0.1905934 
# 3rd Qu.:7.410 3rd Qu.:0.3792237 
# Max. :8.721 Max. :0.3968365

#Para la gráfica se hace uso de la funación plot()

plot(density(iris$Sepal.Length), xlab="Rango de Valores", ylab="Densidad", main="Gráfica de la Densidad", col="3",type="b", add=TRUE)

Density

Pie y Barras

Para estas dos gráficas se requiere tomar los datos para formar tablas, las cuales facilitan la gráfica tanto de barras como de pie. Principalmente se usan con variables categóricas, para estos datos la gráfica de barras no muestra gran funcionalidad por que la cantidad es la misma para las tres categorías.

#Se usan los mismos datos

table(iris$Species)
#setosa versicolor virginica 
# 50 50 50 
 
pie(table(iris$Species), radius = 0.9, col=rainbow(24),main="Gráfica Circular", clockwise=TRUE)
barplot(table(iris$Species), main="Gráfica de Barras",col="2", border="7", ylab="Cantidad")

Pie_1

Barras

La ventaja de usar gráficos para representar la información o el comportamiento de las variables analizadas resulta ser más atractivo cuando varios tipos de gráficas se combinan. En el caso de gráficos para una sola variable dos ejemplos rápidos se obtienen al combinar boxplot y jitter, histogramas y densidad.

#Combinación de gráficas

#Gráfica combinada 1
boxplot(iris$Sepal.Length, main="Boxplot de la Longitud de Sepal-Datos Iris", ylab="Tamaño", col="2")
stripchart(iris$Sepal.Length, method='jitter',vertical=TRUE,pch=1, main="Gráfica de Puntos", ylab="Rango de Datos", add=TRUE)

#Gráfica combinada 2
hist(iris$Sepal.Length,col="2",ylab="Frecuencia relativa", xlab="Longitud del Sépalo", main="Histográma de la Longitud de Sépalo-Datos Iris", labels = TRUE,border="7", probability = TRUE)
lines(density(iris$Sepal.Length), xlab="Rango de Valores", ylab="Densidad", main="Gráfica de la Densidad", col="3",type="b", add=TRUE)

Comb_1

Comb_2

En lo siguiente voy a replicar las gráficas haciendo uso de la librería ggplot2, a primera vista si no se conoce el modelo bajo el cual trabaja ggplot2 puede parecer bastante engorroso pasar de las gráficas base de R a las que proporciona esta librería.

Mi impresión es la siguiente, resulta muy fácil cuando uno aprende a usar R hacer el histograma y agregarle detalles a la gráfica con solo usar la función hist(), en cambio en ggplot2 se requiere hacer una combinación de comandos, ejemplo ggplot()+geom_hist()+…

Esto a primera vista hace parecer que ggplot2 complica mucho el hacer una simple gráfica, pero no es así. El valor o la relevancia de ggplot2 es cuando uno hacer gráficas más elaboradas, ya que cierta parte del procesamiento de los datos o de la detección de patrones de varias variables resulta inmediatamente visible, lo cual es hasta ahora para mi muy complicado hacerlo solo con las gráficas básicas de R. Así que invito a leer el libro de Hadley Wickham ( referencia [1]) o visitar el sitio de ggplot y por supuesto irse familiarizando con ” la gramática de gráficas”.

Boxplot

Como mencioné replico las gráficas en ggplot2, pero para eso hago en general dos versiones , haciendo uso de la función qplot y de ggplot. No explico más sobre las gráficas, pero comparto el código para replicar cada una.

#Boxplot
qplot(data=iris, y=iris$Sepal.Length,x=iris$Species, geom="boxplot", main="Boxplot por tipo de Iris",xlab="Tipo de Iris", ylab="Longitud de Sepal", colour="red")
ggplot(data=iris, aes(y=iris$Sepal.Length))+geom_boxplot(aes(iris$Species), col="red")+ylab("Longitud del Sepal")+xlab("Tipo de Iris")+ggtitle("Boxplot por tipo de Iris")

Boxplot_ggplot

Gráfica de Punto

#Gráficas de Puntos

qplot(data=iris, y=iris$Sepal.Length,x=iris$Species, geom="jitter", main="Jitter de la Longitud de la Sepal por tipo de Íris", ylab="Longitud", xlab="Tipo de Íris")
ggplot(data=iris, aes(y=iris$Sepal.Length,x=iris$Species ))+geom_jitter()+ylab("Longitud")+xlab("Tipo de Íris")+ggtitle("Jitter de longitud de Sepal")

Jitter_ggplot

Histograma

#Hitograma
qplot(data=iris, x=iris$Sepal.Length, geom="Histogram", col="red", main="Histograma", ylab="Cantidad", xlab="Rango de Valores")
qplot(data=iris, x=iris$Sepal.Length, main="Histograma", xlab="Rango de Valores", ylab="Frecuencia")+geom_histogram(col="red")

#Para generar el histograma con la medición de la densidad
ggplot(data=iris, aes(x=iris$Sepal.Length))+geom_histogram(aes(y=..density..), col="red")+xlab("Rango de Valores")+ylab("Frecuencia Relativa")+ggtitle("Histograma")

Hist_ggplot

Densidad

#Density
qplot(data=iris, x=iris$Sepal.Length, geom="Density",main="Densidad", ylab="Frecuencia Relativa", xlab="Rango de Valores")
#Para rellenar el área
ggplot(data=iris, aes(x=iris$Sepal.Length))+geom_density(colour="red", fill="orange")+ylab("Densidad")+xlab("Rango de Valores de la Longitud")+ggtitle("Densidad de la Longitud de la Sepalo")

Densidad_ggplot

Gráficas de Barras y de pie

#Barras

qplot(data=iris, factor(iris$Species), geom="bar", main="Ejemplo de gráfica de Barras", ylab="Cantidad",xlab="Tipo de Íris", fill=factor(iris$Species))

#Pie
ggplot(data=iris, aes(x=factor(iris$Species),fill=factor(iris$Species)))+geom_bar(width=1)+coord_polar()+xlab("Clasificado por Tipo de Especia")+ylab("")

Bar_ggplotPie_ggplot

Combinar gráficas en ggplot2, es muy sencillo solo se agrega a la gráfica que se está haciendo la otra gráfica que se desea. Ejemplo agregar la densidad al histograma resulta sencillo, ya que solo se necesita agregar  “+geom_density()”. Hago dos ejemplos para mostrar como funciona ggplot2.

#Boxplot y jitter

ggplot(data=iris, aes(y=iris$Sepal.Length))+geom_boxplot(aes(iris$Species), col="red")+geom_jitter(aes(iris$Species))+ylab("Longitud del Sepal")+xlab("Tipo de Iris")+ggtitle("Boxplot por tipo de Iris")

#Histogramas y Densidad

ggplot(data=iris, aes(x=iris$Sepal.Length))+geom_histogram(aes(y=..density..), col="red")+geom_density(colour="blue", size=1.5)+xlab("Rango de Valores")+ylab("Frecuencia Relativa")+ggtitle("Histograma")

Boxplot-jitter_ggplot

Hist_density_ggplot

Lattice…otra librería.

Cuando se requiere hacer una exploración de datos con varias variables, no resulta muy fácil pensar en como hacer eso y peor aún si se requiere hacer una comparación entre esas variables por varios años o varios periodos.

En general la mayoría de problemas involucran varias variables de distinta naturaleza, es decir; algunas pueden ser variables categóricas, indicadoras otras variables cuantitativas o cualitativas; en fin;  hacer un análisis de este tipo de datos requiere un cierto tiempo y las gráficas nativas a mi parecer hacer resultan no ser la mejor herramienta para trabajar.

En este caso las dos librerías, ggplot2 y lattice creo que ayudan bastante, detrás de estas dos librerías están dos teorías distintas sobre la exploración o visualización, es por eso que cada una requiere su tiempo de entrenamiento y sobre todo de investigación y aprendizaje. Dejo en las referencias los textos base para aprender a fondo como funcionan estas librerías.

Para las gráficas hago uso de un conjunto de datos que se descargarán automáticamente en R con una línea de código.

#Carga de datos y exploración básica

#Se cargan los datos desde el servidor
hsb2 <- read.table('http://www.ats.ucla.edu/stat/r/modules/hsb2.csv', header=T, sep=",")
#Se revisan los aspectos generales de los datos
head(hsb2)
dim(hsb2)
str(hsb2)

#Agrego una nueva variable
hsb2$gsex=factor(hsb2$female,labels=c("Male","Female"))
summary(factor(hsb2$gsex))
#Male Female 
# 91 109

 Boxplot y gráfica de puntos.

#Boxplot
bwplot(~read,hsb2, main="Boxplot de lectura", xlab="Lectura")
bwplot(~read|gsex,hsb2,main="Boxplot de lectura", xlab="Lectura")

#dotplot
dotplot(~read,hsb2,main="Gráfica de puntos de lectura", xlab="Lectura")
dotplot(~read|gsex,hsb2,main="Gráfica de puntos de lectura", xlab="Lectura")

Boxplot_latticeBoxplot_lattice2Dot_lattice2

Histogramas y Densidad

#Histograma
histogram(~math,hsb2,main="Histogramas por Género", xlab="Lectura",ylab="Porcentage Total")
histogram(~math|gsex,hsb2, ylab="Porcentage Total", xlab="Math", main="Histogramas por Género")

#Densidad
densityplot(~math, hsb2,main="Densidad de la variable math", xlab="Rango de valores", ylab="Densidad")
densityplot(~math|gsex, hsb2,main="Densidad de la variable math", xlab="Rango de valores", ylab="Densidad")

hist_latticeHist_lattice2Density_latticeDensity_lattice2

Cuantiles y Scatter Plot

Estas dos gráficas, no las había comentado. La primera se puede calcular para cualquier variable y es un modo rápido de identificar el comportamiento de la distribución de la variable, principalmente se puede validar el comportamiento de las colas de la distribución. La segunda es apropiada para detectar la posible relación entre dos variables y para explorar muchas variables se puede construir un panel de scatterplot para detectar visualmente entre qué variables es posibles que existe alguna relación.

#qqplot
qqmath(~math,hsb2, main="Gráfica de cuantiles o qqplot", xlab="qnorm",ylab="Variable Math")
qqmath(~math|gsex,hsb2, main="Gráfica de cuantiles o qqplot", xlab="qnorm",ylab="Variable Math")

#scatter plot
xyplot(write~read,hsb2, main="Scatter Plot de las variables write vs read",xlab="Variable read",ylab="Variable write")
xyplot(write~read|gsex,hsb2, main="Scatter Plot de las variables write vs read",xlab="Variable read",ylab="Variable write")

qqplot_latticeqqplot_lattice2Scatterplot_latticeScatterplot_lattice2

Gráficas en ggplot2

Lo único que hago en lo siguiente es replicar el tipo de gráficas separadas por una variable categórica.

Boxplot y dotplot

#boxplot
ggplot(data=hsb2,aes(y=read),colour=factor(hsb2$gsex))+geom_boxplot(aes(x=hsb2$gsex,fill=factor(hsb2$gsex)))+xlab("Genero")+ylab("Variable read")+
 ggtitle("Boxplot de la variable read vs genero")+theme(plot.title = element_text(lineheight=.8, face="bold"))

#dotplot
ggplot(data=hsb2,aes(y=read))+geom_jitter(aes(x=hsb2$gsex,colour=factor(hsb2$gsex)))+xlab("Genero")+ylab("Variable read")+
 ggtitle("Jitter de la variable read vs genero")+theme(plot.title = element_text(lineheight=.8, face="bold"))

Boxplot_ggplot_2Dotplot_ggplot

Histogramas y Densidad

#Histograma
ggplot(data=hsb2,aes(x=read))+geom_histogram(colour="black",aes(fill=factor(gsex)))+facet_grid(.~gsex)+xlab("Genero")+ylab("Variable read")+
 ggtitle("Histogramas de la variable read vs genero")+theme(plot.title = element_text(lineheight=.8, face="bold"))

#Density

ggplot(data=hsb2,aes(x=read))+geom_density(colour="black",aes(fill=factor(gsex)))+facet_grid(.~gsex)+xlab("Genero")+ylab("Variable read")+
 ggtitle("Densidad de la variable read vs genero")+theme(plot.title = element_text(lineheight=.8, face="bold"))

Hist_ggplot2Density_ggplot2

Cuantiles y Scatterplot

#qqnorm

ggplot(data=hsb2,aes(sample=read))+geom_point(stat="qq",aes(colour=factor(gsex)))+facet_grid(.~gsex)+xlab("Genero")+ylab("Variable read")+
 ggtitle("Cuantiles de la variable read vs genero")+theme(plot.title = element_text(lineheight=.8, face="bold"))

#Scatter plot

ggplot(data=hsb2,aes(x=read, y=write))+geom_point(aes(colour=factor(gsex)))+facet_grid(.~gsex)+xlab("Genero")+ylab("Variable read")+
 ggtitle("Scatterplot de la variable read vs write")+theme(plot.title = element_text(lineheight=.8, face="bold"))

Qqplot_ggplotScatterplot_ggplotLos ejemplos anteriores muestran la construcción de gráficos donde podemos ver la relación entre variables o explorar con mayor detalle. El siguiente paso entre el análisis exploratorio y lo que ahora es muy sencillo por las capacidades de computo es hacer análisis exploratorio con cierto nivel de interactividad.

Los casos más llamativos suelen ser las simulaciones, estas se pueden hacer tomando como parámetro una variable temporal. Ejemplo, si se desea ver el comportamiento de cierta población sobre la frontera de dos países se puede usar un mapa y ver con respecto al tiempo los flujos o movimientos de las personas.

Estas simulaciones a mi me parecen gratas para tener idea del fenómeno que se explora más que de la naturaleza de las variables.

En R se pueden hacer gráficos con cierta capacidad de interactividad está ggvis o shiny, así que los ejemplos siguientes los hago con ggvis. Para aprender a usar Shiny la recomendación es ver la documentación en la página oficial.

Página oficial Shiny

Gráficas de Puntos

#Puntos por Género
slider<-input_slider(1,100)

hsb2 %>% 
  ggvis(~as.factor(female),~read, 
        fill :="red"
       )%>% 
       layer_points(size :=slider)%>%
       layer_points(stroke := "black", fill := NA, size :=slider )%>%
       add_axis("x",title="Genero, 0 = Masculino y 1 = Femenino")%>%
       add_axis("y",title="Lectura")

La respuesta que se obtienen del código anterior es:

puntos_ggvis

#Densidad
hsb2 %>% 
  ggvis(~read, 
        fill :="red"
       )%>% 
       layer_densities(adjust = input_slider(0.1, 2))%>%
       add_axis("x",title="Densidad de la variable Lectura")%>%
       add_axis("y",title="")

La imagen que se obtiene son las siguientes:

Densidad_1.png

Variando la estimación se tiene:

Densidad_2.png

Gráfica de Barras

#Densidad
hsb2 %>% 
  ggvis(~read, 
        fill :="red"
       )%>% 
       layer_bars()%>%
       add_axis("x",title="Grafica de Barras")%>%
       add_axis("y",title="")

EjempBarras_ggvis.png

Más ejemplos de como funciona ggvis se pueden consultar en la página oficial:

Página Oficial de ggvis

Referencias:

1.- Ggpplot2 -Hadley  Wickham.

2.-Lattice – Deeppayan Sarkar.

 

 

 

 

Anuncios

Split-Apply-Combine-Parte 1

Sobre Split-Apply-Combine

La idea de esta entrada es aplicar la visión de dividir-aplicar-combinar (Split-Apply-Combine), en las referencias [1,2] se explican más detalles sobre el modelo o metodología guía, la cual fue inspirada por Map-Reduce. Esta última es una metodología apropiada cuando se tienen un cluster de computadoras, en este caso la versión Split-Apply-Combina se centra en el caso del análisis de datos mediante una sola máquina para diseñar una buena estrategia de análisis.

En la entrada desarrollo el ejemplo mediante R project y Python. La intención es mostrar como los dos lenguajes cuentan con las herramientas para realizar el mismo tipo de análisis. Trato de hacer un ejemplo amplio, por lo cual elegí una base más o menos grande de R project, la cual si bien no tiene muchas variables ( solo 16) permite hacer varias cosas con ellas. Por supuesto que el análisis puede tener otro tipo de enfoque, lo único que hago es usar esa base para emplear varias herramientas de R y de Python, las cuales en general uno las consulta de mera independiente.

Divido esta entrada en 3 partes.

Parte 1.-Exploración directa de los datos.

Parte 2.-Procesando los datos y analizando otras posibles relaciones.

Parte 3.-Definiendo técnicas para aplicar y concentrar esto para realizar un proceso Split-Apply-Combine.

Decidí dividir en tres partes para compartir algunos ejemplos sencillos sobre como hacer algunos gráficos y también un poco de análisis. Todos los gráficos usados entran perfectamente en los temas de exploración de datos o análisis exploratorio, en ocasiones solo uso algunas funciones para mostrar como funcionan y el valor que agrega a la exploración puede ser pobre y sin relevancia mayor.

En la referencia [3] se pueden ver detalles sobre las gráficas en R y en la referencia [4] sobre las gráficas en Python.

Parte 1.-Exploración directa de los datos.

En el código considero instaladas las librerías requeridas, en caso de contar con ellas  en caso de usar RStudio se puede hacer uso de Tools para instalar paquetes, lo cual es rápido y fácil.

Los datos corresponden a los tiempos de vuelo del año 2013, contienen información de los vuelos de 3 aeropuertos JFK, LGA y EWR.

#Código para cargar las librerías y datos
library(nycflights13)
library(ggplot2)
library(grid)
library(GGally)
library(gridExtra)#Funciones para la librería Grid

Los datos en general primero son explorados para conocer cuantos datos se tienen como missing values y las dimensiones de estos datos, es decir; cuantas columnas y cuantas filas tiene el archivo.

#Código para revisar las propiedades básicas de los datos
data(flights)
#Para conocer información de los datos 
#?flights

dim(flights)
#[1] 336776     16

#missing value
sum(is.na(flights))
#[1] 60593
flights2=na.omit(flights)
dim(flights2)
#[1] 327346     16

#tipo de datos
str(flights2)
#Aspectos básicos de los datos
head(flights2)
#También se puede ver la parte final de la tabla de datos
#tail(flights2)

#Para revisar el resumen estadístico de los datos
#Se usa el siguiente comando

summary(flights2)

Debido a que se tienen varias variables que son categóricas, se puede revisar su comportamiento considerándolas como “factores”. Un modo de revisar como se comportan ese tipo de datos se puede hacer con el siguiente comando.

#Explorando unas variables categóricas

sort(summary(factor(flights2$dest)),decreasing = TRUE)
sort(summary(factor(flights2$origin)),decreasing = TRUE)
#EWR    JFK     LGA
#117127 109079  101140

Cuando se revisan los datos de manera numérica uno no aprecia mucho la relevancia del comportamiento de los datos. Entonces siempre se buscan algunas gráficas sencillas que representen la información de manera clara y fácil.

Todas las gráficas siguientes pueden ser mejoradas, al final depende del interés de cada persona para definir el tipo de gráfica que se hace.

#Primeras Gráficas

p1=ggplot(data=flights2,aes(x=factor(origin),y=month))+geom_boxplot(col="black",alpha=0.7,aes(fill=factor(origin)))+
xlab('Origen de los Vuelos')+ylab('Mes de vuelo')+ggtitle('Comportamiento de los lugares de salida por mes')+theme(plot.title=element_text(lineheight = 2,face='bold'))

p2=ggplot(data=flights2,aes(x=factor(month)))+geom_bar(col="black",aes(fill=factor(origin)),position="dodge")+
  xlab('Mes de Vuelos')+ylab('Número de vuelos')+ggtitle('Comportamiento de vuelos por mes con respecto al aeropuerto de salida')+theme(plot.title=element_text(lineheight = 2,face='bold'))

grid.arrange(p1,p2,ncol=2,main="Gráficas del comportamiento de vuelos por mes")

La gráfica que se obtiene es la siguiente:Gráficas_vuelos_por_mesLa intensión es revisar la relación que existe entre la cantidad de vuelos por mes respecto al aeropuerto de salida u origen. La primera gráfica muestra como los 3 aeropuertos tienen un mes en el cual es la media de vuelos y por otro lado el JFK muestra que cubre un mayor número de meses con actividad. En las barras se observa que en EWR se realiza un mayor número de vuelos, además muestra las altas en vuelos en primavera y verano.

##Comportamiento de los tiempos de retraso de despegue y de arrive

q1=ggplot(data=flights2,aes(x=dep_time))+geom_histogram(color="black",aes(fill=factor(origin)))+
  xlab('Hora de despegue')+ylab('Número de Vuelos')+ggtitle('Hora de Despegue por aeropuerto de salida')+theme(plot.title=element_text(lineheight = 2,face='bold'))

q2=ggplot(data=flights2,aes(x=arr_time))+geom_histogram(colour="black",aes(fill=factor(origin)))+
  xlab('Hora de arrivo')+ylab('Número de vuelos')+ggtitle('Hora de Arrivo por aeropuerto de salida')+theme(plot.title=element_text(lineheight = 2,face='bold'))

grid.arrange(q1,q2,nrow=1,ncol=2,main="Gráficas del comportamiento de vuelos por mes")

El gráfico que se obtiene es:

Despegue_y_arrivo_por_aeropuertoSe muestran los histogramas de la cantidad de vuelos por hora de despegue y arribo divididos por el aeropuerto de origen. Se aprecian las horas en las cuales se realizan el mayor número de vuelos , los cuales son sumamente notorios. Por otro lado se aprecia la hora de llegada, las cuales muestran cuatro horas pico o el horario con mayor número de arribos.

En la base de datos se tienen registrados los minutos de retraso en despegues y en arribos a su destino, una idea sencilla es graficar el cruce de ambos datos y explorarlos.

#Gráfica de retrasos en despeque y arrivo
ggplot(data=flights2,aes(x=dep_delay,y=arr_delay))+geom_point(aes(colour=factor(origin)))+
  geom_smooth(method='lm',colour='black')+
  xlab('Retraso en Despegar')+ylab('Retraso en arrivo')+ggtitle('Relación entre retraso de despegue y arrivo por aeropuerto')+theme(plot.title=element_text(lineheight = 2,face='bold'))

La gráfica que se genera es la siguiente:

Relación_despegue_vs_arrivoAgregué la línea de tendencias entre los datos calculada con la regresión lineal entre los datos. Esta recta muestra una buena descripción gráficamente o eso aparenta, pero con un poco de cuidado se ve que los mejores datos descritos son aquellos que tienen mayor tiempo de retraso, mientras que la mayoría de datos se muestran como una mancha en los primeros 500 minutos.

Lo que se me ocurrió revisar el comportamiento de la distribución de los datos, haciendo uso de un histograma, después de observar que solo se apreciaba unas cuantas barras estimadas probé transformar los dato y calcular su logaritmo y luego volver a revisar su histograma. Lo que se observa de los datos transformados es la siguiente gráfica:

Hist_Dist_despegue_y_arrivosLa cual se puede obtener con el siguiente código:

#Tranformación de los datos e Histograma
l1=ggplot(data=flights2,aes(x=log(87+arr_delay)))+geom_histogram(color="black",aes(fill=factor(origin)))+
xlab('Log(87+arr_delay)')+ylab('Conteo')+ggtitle('Histograma de los retrasos en tiempo de arrivo')+theme(plot.title=element_text(lineheight = 2,face='bold'))

l2=ggplot(data=flights2,aes(x=log(43+dep_delay)))+geom_histogram(color="black",aes(fill=factor(origin)))+
  xlab('Log(43+dep_delay)')+ylab('Conteo')+ggtitle('Histograma de los retrasos de tiempo de despegues')+theme(plot.title=element_text(lineheight = 2,face='bold'))

grid.arrange(l1,l2,nrow=1,ncol=2,main="Gráficas del comportamiento de vuelos por mes")

Se observa entonces que los datos muestran comportamientos de distribuciones de cols pesadas, lo cual requiere una revisión más meticulosa. Haciendo el gráfico de cruce entre los dos tiempos de retrasos, pero considerando sus valores transformados se obtienen el siguiente gráfico log-log.

Log_vs_log_distancia-arrivosEl otro par de variables que sugiere que tienen alguna relación son la distancia del vuelo y el tiempo de vuelo. La gráfica se puede realizar con el siguiente código:

ggplot(data=flights2,aes(x=air_time,y=distance))+geom_point(aes(colour=factor(origin)))+
  xlab('Tiempo de vuelo')+ylab('Distancia recorrida')+ggtitle('Cruce entre la distancia y el tiempo de vuelo')+theme(plot.title=element_text(lineheight = 2,face='bold'))

La gráfica que se obtiene es la siguiente:

Cruce_Dis_vs_Tiempo_vueloLa gráfica a primera vista sugiere una relación lineal, pero también se puede explorar si no resulta favorable considerar el log-log de los datos, esto por aquellos datos que muestran desconexión en la parte superior de la gráfica.

ggplot(data=flights2,aes(x=log(distance),y=log(air_time)))+geom_point(aes(colour=factor(origin)))+
  xlab('Logaritmo del Tiempo de vuelo')+ylab('Logaritmo de la Distancia recorrida')+ggtitle('Cruce entre la distancia y el tiempo de vuelo')+theme(plot.title=element_text(lineheight = 2,face='bold'))

La gráfica que se obtiene es la siguiente:

Cruce_Log_de_Dist_vs_Timepo_VueloTambién muestra una relación lineal pero es posible que revisando un ajuste lineal entre los datos sea favorable considerar el log-log para cubrir una mayor  población de los datos.

Los siguientes gráficos solo son ejemplos para explorar la información en busca de alguna posible relación entre los datos.

JitterHoras_de_despegueEl código de los dos gráficos es el siguiente:

ggplot(data=flights2,aes(x=factor(carrier),y=factor(origin)))+geom_jitter()
#ggplot(data=flights2,aes(x=hour))+geom_bar(aes(colour=origin,fill=origin),position = "dodge")+coord_flip()

ggplot(data=flights2,aes(x=hour))+geom_bar(color="black",aes(fill=origin))+
  xlab('hora del día')+ylab('Conteo')+ggtitle('Histograma de las horas de despegue o salida')

Estos dos gráficos, sobre todo el primero; son informativos por ejemplo las barras negras muestran por aeropuerto qué aerolíneas tienen actividad. Es inmediatamente es claro cuales aerolíneas tienen presencia y la diferencia entre la actividad por aeropuerto.

La segunda gráfica muestra 3 momentos donde no se registran vuelos, lo cual resulta raro pero los datos de muestran esto, lo cual implica a ser explorado con mayor detalle.

Un gráfico que suele hacerse entre varias variables o entre una matriz de datos es el scatter plot, para explorar la posible relación entre cada par de variables. Para realizarlo en R con ggplot, se ejecuta el siguiente código:

#Scatter Plot
ggpairs(data=flights2[,c("dep_delay","arr_delay","air_time","distance")],columns=1:4,title="Datos")

La gráfica que se obtiene es la siguiente:

Scatterplot-flighLa gráfica de arriba solo muestra la relación entre varias variables de los datos no de todas. La información de la gráfica incluye la correlación, la cual muestra que es casi nula entre algunas de las variables y muy próxima a 1 en dos pares de variables. La otra opción es hacer una revisión entre las variables pero no solo usando la correlación, sino la el índice de información Mutua. Este último no solo considera la posible relación lineal, sino también una posible relación no lineal. Para realizar el cálculo en R project se puede usar la librería “entropy”.

Ejemplo en R la información mutua entre arr_delay y distance, es de 0.0406. Lo cual indica que no existe alguna relación que analizar.

Con la breve exploración anterior se puede ir pensando en el tipo de cosas que pueden resultar interesantes o que podían ser modeladas, ejemplo pronosticar conociendo el lugar de despegue la hora y la aerolínea el lugar de arribo, o construir un modelo para clasificar los datos de vuelos por el aeropuerto de origen. Pronosticar la cantidad de vuelos por aeropuerto para el siguiente año, o pronosticar los tiempo de atraso en arribar un vuelo conociendo el origen, el horario, el mes de vuelo y el lugar al cual arribará.

Por su puesto que el tipo de preguntar a responder depende de la persona que está explorando los datos o el negocio que requiere este análisis. Por lo cual en esta entrada solo deseaba mostrar algunos gráficos que se pueden ayudar a explorar los datos, al final la primera parte de realizar algún análisis es explorar aspectos estadísticos básicos y apoyarse de alguna gráfica ayuda a tener alguna visualización de la información.

Análisis similar con Python

 El procesamiento de datos en Python en general es realizado siempre en el módulo pandas, las estructuras de datos para procesar información es similar a R project. Se cuenta con estructuras de datos como Data.Frame y Series, como su nombre lo indica funcionan equivalentemente a las de R.

Se pueden usar en Python algunos de los datos de R project haciendo uso de algún módulo, ejemplo el módulo Stats Models tienen un api para conectarse con los datos de R project, lo cuales se encuentran su lista en Rdatasets.

En el ejemplo lo que hice fue exportar los datos de la librería nycflights13 a un archivo csv y cargarlo en una sección en Pandas de Python.

El código es el siguiente:

#Carga de datos
import pandas as pd
#Cargar datos
flights=pd.read_csv('flights.csv')

Para procesar o explorar la descripción básica de los datos se hacer con los siguientes código.

#Revisión de los datos
#Se ve un resumen de lso datos
flights.head()
flights.shape()

Unas de las cosas estándar al hacer análisis es procesar los missing data, lo cual se puede hacer en python con el siguiente código.

#Revisión
#Un modo burdo de ver que tienen missin values
flights[flights.isnull()!=True].count()
#Nuevo data.frame para los datos sin missin value
flights2=flights.dropna()
flights2[flights2.isnull()!=True].count()

Otro aspecto básico es revisar la descripción de la información de manera general, es decir; revisar aquella variables que son categóricas como origin o dest y también revisar la descripción estadística de variables que pueden ser consideradas continuas, como dep_delay o distance.

#Revisión de algunas variables
#Para conocer la información en general de los datos
flights2.info()
flights2.describe()
#Se exploran algunas de las variables que no son númericas y otras númericas
#Variables continua
flights2['dep_delay'].describe()
flights2['distance'].describe()

#Variables categoricas
flights2['origin'].astype('category').value_counts()
flights2['origin'].astype('category').describe()
flights2['dest'].astype('category').value_counts()
flights2['dest'].astype('category').describe()

Ahora para visar algunas gráficas básicas sobre las variables se usa en general matplotlib, pese a que pandas cuanta con algunas gráficas básicas como histogramas,gráficas de barras y boxplot.

Otra opción de reciente desarrollo es ggplot en python, la cual no cuenta con la misma flexibilidad que en R, pero está en desarrollo. La diferencia entre matplot y ggplot es en esencia que este último fue desarrollado con la perspectiva de “Grammar of Graphics”, mientras que matplot fue pensado en el marco de desarrollo de gráficos  que se usan en matlab. El concepto de ggplot, en recientes años a tomado relevancia ya que se pueden construir gráficos de manera rápida que involucran de fondo una transformación de los datos.

Un ejemplo es el siguiente, el cual se hace con los gráficos de base de pandas.

#Boxplot
df=flights2[['month','origin']]
df.boxplot(by='origin')

Boxplot_por_Mes

El gráfico es similar al que se obtienen en ggplot con R, pero en su defecto en R no se requiere seleccionar los datos y directamente indicar que se agrupen para hacer el gráfico.

Entonces para hacer un análisis gráfico rápido me resulta más fácil pensarlo en R que en Python, pero se obtienen ciertas ventajas en Python que no se obtienen en R.

Otra opción que existe es usar los gráficos de R desde pandas con el módulo rpy2, por medio del cual de cierto modo se usa todo lo que se quiera de R y se utiliza en python.

Un ejemplo de ggplot en Python, usando el módulo para python y no desde R, es el siguiente:

#Gráfica de barras
from ggplot import *


print ggplot(flights2,aes(x='month',fill='factor(origin)'))+\
 geom_bar(color="black")+\
 ggtitle('Barras por cada Mes')+\
 theme(plot_title=element_text(lineheight=2))+\
 ylab('Cantidad de Vuelos por Mes')+\
 xlab('Meses')

Barras_por_mes

El gráfico es parecido al primero que mostré en R. El boxplot de los vuelos en matplotlib se puede obtener del siguiente modo:

#Boxplot Maplotlib
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('ggplot')

fig,ax1=plt.subplots()
ax1.boxplot(Mes,showmeans=True)
ax1.set_title('Boxplot de vuelos por mes')
ax1.set_xlabel('Valores')
ax1.set_ylabel('Meses')
plt.show()

Boxplot de los meses

Los histogramas para explorar el comportamiento de los tiempo de retraso y de despegue se obtienen en ggplot para python se obtienen con el siguiente código.

#Histogramas
from ggplot import *
print ggplot(flights2,aes(x='dep_time',fill='origin'))+\
 geom_histogram(color="black")+\
 ggtitle('Histograma de la hora despegue')+\
 theme(plot_title=element_text(lineheight=2))+\
 ylab('Cantidad de vuelos')+\
 xlab('Horario')

print ggplot(flights2,aes(x='arr_time',fill='origin'))+\
 geom_histogram(color="black")+\
 ggtitle('Histograma de la hora de arribo')+\
 theme(plot_title=element_text(lineheight=2))+\
 ylab('Cantidad de vuelos')+\
 xlab('Horario')

Histograma_despegues

Histograma_arribos

La gráfica del cruce entre los retrasos de arribo y despegue se obtienen de manera similar a la que se realiza en ggplot para R, lo único que se hace notar, es que la librería ggplot para python es más lenta al crear una gráfica con muchos datos.

#Scatter plot
from ggplot import *
print ggplot(flights2,aes(x='dep_delay',y='arr_delay'))+\
 geom_point()+\
 geom_smooth(color="red")+\
 ggtitle('Cruce de retrasos')+\
 theme(plot_title=element_text(lineheight=2))+\
 ylab('Retrasos en arribos')+\
 xlab('Retrasos en despegue')

Cruce_de_retrasos

Para hacer una gráfica similar en matplotlib se observa que el código es más elaborado, se obtiene una gráfica similar pero con mayor cantidad de líneas de programación.

#Ejemplo en Matplotlib
import matplotlib.pyplot as plt

for aero in ['LGA', 'JFK', 'EWR']:
 x =flights2.loc[flights2.loc[:,'origin']==aero,'dep_delay']
 y = flights2.loc[flights2.loc[:,'origin']==aero,'arr_delay'] 
 
 if aero=='EWR':
 color='red'
 plt.scatter(np.asarray(x.values)[:len(x)-1],np.asarray(y.values)[:len(y)-1],
 c=color, label=aero)
 
 if aero =='JFK':
 color='blue'
 plt.scatter(np.asarray(x.values)[:len(x)-1],np.asarray(y.values)[:len(y)-1],
 c=color, label=aero)

 if aero=='LGA':
 color='green'
 plt.scatter(np.asarray(x.values)[:len(x)-1],np.asarray(y.values)[:len(y)-1],
 c=color, label=aero) 
 

plt.legend(loc=4)
plt.grid(True)
plt.title('Scatter plot de los retrasos')
plt.ylabel('Retrasos en despegues')
plt.xlabel('Retrasos en arribos')
plt.show()

La gráfica es la siguiente:

Scatter_plot_retrasos

Otra gráfica fácil de hacer es la del comportamiento de los histogramas de los retrasos, tanto de despegues como de arribos.

El código es el siguiente:

#Histogramas
import matplotlib.pyplot as plt

plt.style.use('bmh')

x =flights2['dep_delay']
y = flights2['arr_delay'] 

x1=np.asarray(x.values)[:len(x)-1]
y1=np.asarray(y.values)[:len(y)-1]
plt.hist(x1, histtype="stepfilled",
 bins=20, alpha=0.8, normed=True)
plt.hist(y1, histtype="stepfilled",
 bins=20, alpha=0.8, normed=True)
plt.title('Histogramas de los retrasos de despeque y de llegada')
plt.xlabel('Valores de los retrasos')
plt.ylab('Cantidad de retrasos')
plt.show()

La gráfica es la siguiente:

Histogramas_de_los_retrasos

Para hacer un panel de gráficos como el de la exploración en R, se tiene que diseñar el panel con el número de gráficos que se desea. Esto en el fondo también sucede con R, solo que en matplotlib uno tiene que hacer el código con mayor detalle.

Espero que estas cuantas gráficas hechas en python de una imagen de lo versátil que es, se requiere en general procesar más los datos pero se puede tener mayor control sobre el tipo de gráficos que se pueden hacer.En la referencia [4] se pueden consultar muchas gráficas de muestra.

Referencias

1.-http://static.googleusercontent.com/media/research.google.com/es//archive/mapreduce-osdi04.pdf

2.-http://www.jstatsoft.org/v40/i01/paper

3.-http://ggplot2.org/

4.-http://matplotlib.org/

5.-http://pandas.pydata.org/pandas-docs/stable/groupby.html