Análisis de Grafos

En esta entrada hago una recopilación de varios post de Andrie de Vries. Ya que el ejemplo que realiza se puede replicar sin problema alguno, la muestra de datos es suficientemente grande como para ser interesante y combina varias técnicas para detectar comunidades o clusters, con la finalidad de encontrar los nodos más sobre salientes del grafo.

Una área de investigación importante tanto en matemáticas, en física como en ingeniería; es la investigación en Grafos Grandes o redes largas (Large Graph). Sobre este tema recomiendo la referncia [1]. En lo personal es una área que me gusta y que pese a saber poco, trato de leer y de aprender al respecto, quizás más aspectos teóricos que prácticos; pero suele ser grato tener algunos ejemplos de donde aparecen los objetos matemáticos estudiados.

No puedo, ni pretendo hablar de teoría de grafos o gráficas por que no soy el adecuado para hablar a detalle del tema, pero recomiendo las referencias [2,3] para acercarse al tema desde el lado de algoritmos y desde el punto de vista de matemáticas discretas. Un libro en línea que puede ser una grata introducción a manejar grafos en python se puede ver en la referencia [4].

De que trata el ejemplo.

Hago uso de las idea y parte del código de Andrine Vries para mostrar como procesar un grafo. Este está formado por una muestra de paquetes o librerías de R, así que con más  7000 nodos es interesante aplicar ciertos algoritmos.

Las etapas son las siguientes:

  1. Cargar los datos y explorar parte de ellos.
  2. Aplicar el algoritmos PageRank.
  3. Aplicar técnicas de Cluster para grafos y comparar entre algunos algoritmos.
  4. Mostrar algunas representaciones gráficas sobre el grafo y el impacto de los algoritmos en él.

La idea es explicar el uso de cada librería en los puntos anteriores y el uso de Gephi.

Etapa 1. Generar los datos

Antes de mostrar un ejemplo sencillo de como generar un grafo, la idea de grafo es contar con nodos y con aristas. Donde las aristas conectan a los nodos o se quedan conectando al mismo nodo. Una idea gráfica se puede ver como la siguiente imagen:

usa-7-2

Grafo de libro Fractional Graph Theory

Pero también puede ser algo mucho más extraño, por la cantidad de nodos y la conexión entre las aristas. De modo tal que se pueden ver como:

map-of-internet

Visualización de la Intenet

Entonces la conexión entre redes y grafos pues es natural, prácticamente son lo mismo; pero la perspectiva con la cual la estudian desde el punto de vista de física es distinta a la que se estudia en matemáticas.

En R se tiene la librería miniCRAN con la cual se pueden extraer datos de los paquetes o librerías. Cuando se instala una librería muestra en la mayoría de los casos la solicitud de instalar las librerías con las cuales tiene dependencia en caso de no contar con ellas. Así que hay muchas librerías que tienen dependencia con muchas otras librerías y otras, simplemente con unas cuantas. La mayoría usan las librerías base de R, pero con miniCRAN se pueden ignorar estas y analizar solo las que no son básicas.

#Ejemplo 1
 librería(miniCRAN)

tags<-"ggplot2"

#Se extraen datos de las librerías con las cuales tiene relación de tres modos diferente, considerando o descartando algunas.

pkgDep(tags, suggests=FALSE, enhances=FALSE, includeBasePkgs = TRUE)

pkgDep(tags, suggests=FALSE, enhances=FALSE)

pkgDep(tags, suggests=TRUE, enhances=TRUE)

#Gráfica de las relaciones entre el paquete ggplot2

set.seed(1)

plot(makeDepGraph(tags, includeBasePkgs=FALSE, suggests=TRUE, enhances=TRUE), 
 legendPosEdge = c(-1, 1), legendPosVertex = c(1, 1), vertex.size=30, cex=0.7)

La gráfica que se obtiene es la siguiente:

ggplot2_graphs

Si se replica el código pero para una lista de librerías, se puede pensar en buscar el grafo de ciertas librerías que se usan para tareas relacionadas, ejemplo dplyr y reshape2, ggplot2 y lattice; etc. Pero para mostrar que no todos los paquetes están relacionados se puede considerar en la lista algunas librerías que tienen un uso diferente, como tm y lars.

#Ejemplo 2
library(miniCRAN)

tags<-c("dplyr","reshape2","ggplot2","tm","lattice","data.table","lars")

set.seed(1)

plot(makeDepGraph(tags, includeBasePkgs=FALSE, suggests=TRUE, enhances=TRUE), 
 legendPosEdge = c(-1, 1), legendPosVertex = c(1, 1), vertex.size=15,cex=0.5)

La gráfica que se obtienen es la siguiente:

dplyr-reshape2-data.table-ggplot2-lattice-tm_graphs

Observando la imagen se observa que hay dos nodos; tm y lars, que se muestran “disjuntos” a la red que muestran los otros paquetes. En este caso, se aprecia gráficamente que entre las librerías para procesar datos y generar gráficas existen ciertas relaciones, las cuales pueden ser analizadas.

Entonces la idea es extraer el grafo de todos los paquetes de R hasta hoy 29-09-2015 y aplicar algunos algoritmos para jugar con él. La cantidad de paquetes disponibles es de 7234 hasta hoy, lo cual hace pensar en que una imagen gráfica de dicho grafo es algo complicada para detectar cuales paquetes se aglomeran más que otros, o cuales son casi asilados del resto (como en las imágenes anteriores).

La extracción de los datos se realiza con el siguiente código:

library(miniCRAN)
library(magrittr)

MRAN <- "http://mran.revolutionanalytics.com/snapshot/2015-09-29/"

#Se extrae la matriz con todos los paquetes
pdb <- MRAN %>%
 contrib.url(type = "source") %>%
 available.packages(type="source", filters = NULL)

#Para visualizar el tipo de dato y las primeras 5 filas de la matriz de datos
class(pdb)
head(pdb)

#Se construye un grafo con la matriz

g <- pdb[, "Package"] %>%
 makeDepGraph(availPkgs = pdb, suggests=FALSE, enhances=TRUE, includeBasePkgs = FALSE)

#Se puede ver el tipo de dato
class(g)
head(g)

Etapa 2.Aplicación de PageRank

Por el tamaño del grafo resulta conveniente aplicar algún tipo de algoritmo para detectar algo sobre la relación entre paquetes. La idea de aplicar el algoritmo PageRank para detectar los paquetes que tienen más relevancia en la red.

Para ver detalles sobre el algoritmo les recomiendo la referencia [5]. En breve la idea del algoritmo es asignar un valor numérico a cada paquete y por medio de eso poder definir cuales tienen mayor relevancia según el valor que se le asignó que es un modo de sintetizar el peso o impacto del paquete en los otros paquetes. Esto no le hace el merito adecuado a dicho algoritmo, pero los detalles teóricos se salen de poder explicarse en la entrada.

Aplicando el algoritmo que se tienen implementado en la librería igraph, se obtienen los siguientes resultados:

#Aplicación de pageRank
library(igraph)

#Se aplica el algoritmo
pr <- g %>%
 page.rank(directed = FALSE) %>%
 use_series("vector") %>%
 sort(decreasing = TRUE) %>%
 as.matrix %>%
 set_colnames("page.rank")

head(pr, 10)
# Los 10 paquetes más importantes
#   page.rank
#Rcpp 0.021333171
#MASS 0.019112827
#Matrix 0.009390048
#ggplot2 0.009136545
#mvtnorm 0.008061911
#lattice 0.007902018
#survival 0.007814334
#plyr 0.007025619
#sp 0.004832534
#XML 0.004669243

Haciendo una representación gráfica del orden implementado por el algoritmo PageRank, se obtienen lo siguiente:

#Top 10
set.seed(40)
pr %>%
 head(10) %>%
 rownames %>%
 makeDepGraph(pdb) %>%
 plot(main="Top de paquetes", cex=0.5)

#Top 30
set.seed(40)
pr %>%
 head(30) %>%
 rownames %>%
 makeDepGraph(pdb) %>%
 plot(main="Top 30 de paquetes", cex=0.5)

Las gráficas que se obtienen son las siguientes:

top_10

Top_30

Se observa que el grafo de los primeros 10 es más o menos claro, pero que el de los primeros 30 ya empieza a mostrar cierta complejidad o se muestra más complicado para determinar visualmente algunos aspectos, pese a eso se aprecian en la imagen un par de paquetes asilados.

Etapa 3.-Detectando comunidades.

Los clusters, son parte de las técnicas de aprendizaje no supervidado en Machine Learning. Existen muchas técnicas o algoritmos, algunos al paso del tiempo ya sea por la eficiencia computacional o por el tipo de resultados que han permitido obtener terminan siendo predominantes o persistir ante la aparición de nuevas técnicas o algoritmos.

En la entrada “Análisis de Cluster, un ejemplo sencillo” mostré como usar dicha técnica con unos conjuntos de datos. La situación cambia un poco cuando se trabaja sobre grafos o redes, ya que se tiene en particular un tipo de datos (el grafo) sobre el cual se hace uso de sus propiedades para definir los algoritmos para detectar clusters.

En las referencias [6,7,8,9] se puede leer varios exploraciones experimentales sobre el tipo de algoritmos que más predominan en las investigaciones y al implementar dichos algoritmos. Aplico dos algoritmos para detectar comunidades o clusters en el grafo y mido la similaridad entre las dos comunidades con la medida de similaridad de Jaccard para comparar los resultados obtenidos entre los dos algoritmos.

Siguiendo a Andrie de Vries, solo tomo el 80% de la red de los cuales se eligen los nodos más importantes según el algoritmo PageRank.

#Se aplica al mismo grafo ordenado por PageRank pk
#Se selecciona el 80% de los datos

cutoff <- quantile(pr[, "page.rank"], probs = 0.2)
popular <- pr[pr[, "page.rank"] >= cutoff, ] 
toKeep <- names(popular)

vids <- V(g)[toKeep]
gs <- induced.subgraph(g, vids = toKeep)

#Aplicación del primer algoritmo walktrap community
#Se obtienen 2118 comunidades

cl <- walktrap.community(gs, steps = 3)

#Se ordenas
topClusters <- table(cl$membership) %>% 
 sort(decreasing = TRUE) %>% 
 head(25)

#Se gráfica el comportamiento de los cluster o de las comunidades

plot(topClusters, main="Tamaño Cluster", ylab="Numero de cluster", type="b", lwd=2)

#Se aplica el segundo algoritmo, infoMaps community
#Se obtienen 2280 comunidades

cl1 <- infomap.community(gs)

topClusters1 <- table(cl1$membership) %>% 
 sort(decreasing = TRUE) %>% 
 head(25)

plot(topClusters1, main="Tamaño de Clusters", ylab="Numero de clusters", type="b", lwd=2)

Cluster_walktrap

InfoMaps_clusters

Las gráficas muestran el comportamiento de los cluster o comunidades, lo cual muestra que se pueden elegir los primero 10 clusters como los más importantes. Siguiendo a Andrie de Vries se eligen los 10 clusters más importantes.

Para comparar el comportamiento entre los dos algoritmos; además de que el primero detecta 2118 comunidades y el segundo 2280, comparo los 10 cluster más importantes por medio del índice de similaridad de Jaccard. Para los que tienen nociones de teoría de conjuntos, la idea es muy sencilla es comparar cuantos elementos están en la intersección dividido entre los elementos en la unión. Esto da una medida de similaridad, con la cual comparo entre las 10 comunidades más importantes por algoritmo.

#Eligiendo los 10 clusters más importantes

cluster <- function(i, clusters, pagerank, n=10){
 group <- clusters$names[clusters$membership == i]
 pagerank[group, ] %>% sort(decreasing = TRUE) %>% head(n)
}

#Para walktrap
z1 <- lapply(names(topClusters)[1:10], cluster, clusters=cl, pagerank=pr, n=20)

#Para infoMaps
z2 <- lapply(names(topClusters1)[1:10], cluster, clusters=cl1, pagerank=pr, n=20)

#Comparación entre los cluster de cada algoritmo

Jaccard<-function(A,B){
 a=length(intersect(A,B))
 b=length(union(A,B))
 a/b
 }
s=vector(length=10)

for(i in 1:10){
 L1=names(z1[[i]])
 L2=names(z2[[i]])
 s[i]=Jaccard(L1,L2)
 }

library(ggplot2)
t=1:10
qplot(x=t,y=s,geom=c("line", "point"), main="Similaridad entre los dos algoritmos", xlab="Número de Cluster",ylab="Valor de Similaridad")

Similaridad

Se observa que en los dos algoritmos en el primer cluster se tienen más similaridad, la lista de librerías por algoritmo son las siguientes:

#Para el algoritmo Walktrap
names(z1[[1]])
 [1] "MASS" "Matrix" "mvtnorm" "lattice" 
 [5] "survival" "igraph" "coda" "nlme" 
 [9] "rgl" "boot" "RColorBrewer" "numDeriv" 
[13] "Hmisc" "mgcv" "cluster" "gtools" 
[17] "car" "fields" "lme4" "xtable" 

#Para el algoritmo infoMaps
names(z2[[1]])
 [1] "Rcpp" "plyr" "XML" "stringr" 
 [5] "reshape2" "foreach" "jsonlite" "rJava" 
 [9] "cluster" "car" "fields" "lme4" 
[13] "corpcor" "e1071" "doParallel" "vegan" 
[17] "quadprog" "rpart" "randomForest" "plotrix"

La interpretación o explicación de los resultados puede varias, ejemplo en los conjuntos de librerías anteriores aparece una combinación entre librerías para procesar datos, para graficar, para aplicar modelos predictivos o de clasificación, etc.

Para visualizar el grafo de las librerías, la intención era mostrarlo con Gephi pero tuve un problema con el programa y hasta que después repare o vea que es lo que tiene comparto la visualización de toda la red. Pero con igraph se puede hacer una imagen buena de como se comportan los cluster en la red.

#Uso de igraph, parte de código de Andrei de Vries

#Se carga la librería
library(igraph)

# Se preparan los datos para construir la gráfica

cl$degree <-(degree(gs)[cl$names])
cl$cluster<-unname(ave(cl$degree, cl$membership,FUN=function(x)names(x)[which.max(x)]))
V(gs)$name <- cl$cluster

E(gs)$weight <- 1
V(gs)$weight <- 1

gcon<-contract.vertices(gs, cl$membership,vertex.attr.comb = list(weight = "sum", name = function(x)x[1], "ignore"))

gcon<-simplify(gcon, edge.attr.comb = list(weight = "sum", function(x)length(x)))

gcc<-induced.subgraph(gcon, V(gcon)$weight > 20)

V(gcc)$degree<-unname(degree(gcc))

#construcción de la gráfica
par(mar = rep(0.1, 4)) 
g.layout<-layout.kamada.kawai(gcc)
plot.igraph(gcc, edge.arrow.size = 0.1, layout = g.layout, vertex.size = 0.5 * (V(gcc)$degree))

La imagen de grafo que se obtiene es el siguiente:

Grafo1_vis

Se muestra en la imagen como la librería con círculos mayores tienen mayor relevancia en la parte de la red, por su puesto que no están las 7000 librerías representadas pero esta imagen da idea de cuales son las librerías más importantes o las más usadas, partiendo de la clasificación hecha con el algoritmo walktrap y pagerank.

Espero la entrada de una idea como tratar en general datos que pueden ser analizados como un grafo, cabe mencionar que cuando se analiza un corpus de textos o un texto, este también puede ser analizado y explorado visualizando su matriz de términos como la matriz asociada a un grafo y eso hace que se tengan más herramientas para analizar lo que sucede con dicho texto o la relevancia de sus tópicos.

Referencias:

  1. Large Network and graph limits.Lásló Lovasz
  2. Estructura de datos y algoritmos.
  3. Graph Theory
  4. http://interactivepython.org/runestone/static/pythonds/index.html
  5. http://www.mmds.org/
  6. http://www-personal.umich.edu/~mejn/papers/epjb.pdf
  7. http://arxiv.org/abs/1004.3539
  8. http://deim.urv.cat/~clara.granell/publications/ijcss_clara.pdf
  9. http://www.syssec-project.eu/m/page-media/3/moradi-sea12.pdf
Anuncios

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.