2018-08-31

Gráficos de An Introduction to Statistical Learning con ggplot2 y plotly - Figura 1.4. interactiva

Problema

Queremos añadir interactividad al gráfico creado en la entrada anterior, el gráfico de la derecha de la figura 1.4 del libro An Introduction to Statistical Learning. El gráfico representa el conjunto de datos NCI-60, cada tipo de cáncer con un color y símbolo diferente. Las observaciones que corresponden al mismo tipo de cáncer tienden a estar cerca em este espacio bidimensional.

Solución

Empleamos el paquete plotly que permite crear gráficos interactivos en la web. En concreto la función de ggplotly que convierte un objeto ggplot2 en un objeto plotly.

# Librerías y datos NCI60 
library(ISLR)
library(tidyverse)
library(plotly)
nci.labs <- NCI60$labs
nci.data <- NCI60$data
pr.out <- prcomp(nci.data, scale = TRUE)

# Gráfico 2
df2 <- data.frame(pr.out$x[, 1:2], nci.labs)
p2 <- ggplot(df2, aes(x = PC1, y = PC2, colour = nci.labs)) +
  geom_point(size = 3)+
  labs(x = "Z1", y = "Z2")+
  theme_bw()+
  theme(legend.position="none")

# Interactividad
ggplotly(p2)

Entradas relacionadas

2018-08-30

Gráficos de An Introduction to Statistical Learning con ggplot2 - Figura 1.4.

Gráfico a replicar

Continuamos con la serie iniciada sobre la creación de gráficos del libro An Introduction to Statistical Learning. En esta ocasión replicaremos los gráficos de la figura 1.4. Se trata de dos diagramas de dispersión del conjunto de datos NCI-60 y cada observación representa una de las 64 líneas celulares (cell lines) correspondientes a un tipo de cáncer. A la izquierda, representados dos vectores de análisis de componentes principales. Parece haber 4 grupos de observaciones que separamos por colores. A la derecha, el mismo gráfico de la izquierda pero representados cada tipo de cáncer con un color y símbolo diferente. Las observaciones que corresponden al mismo tipo de cáncer tienden a estar cerca en este espacio bidimensional.

Solución con ggplot2

# Librerías y datos NCI60 
library(ISLR)
library(tidyverse)
nci.labs <- NCI60$labs
nci.data <- NCI60$data

# Análisis de componentes principales (ACP o PCA) con NCI60 
pr.out <- prcomp(nci.data, scale=TRUE)

# Gráfico 1
df1 <- data.frame(pr.out$x[, 1:2], nci.labs) %>% 
  mutate(groups =ifelse(
  PC1 < -40, 'group1', ifelse(
  PC1 > -42 & PC2 > 1, 'group2', ifelse(
  PC1 > 25 & PC2 < 1, 'group3', 'group4'))))
p1 <- ggplot(df1, aes(x = PC1, y = PC2, colour = groups)) +
  geom_point(size = 3)+
  labs(x = "Z1", y = "Z2")+
  scale_color_manual(values = c("group1" = "red", "group2" = "blue", "group3" = "green4", "group4" = "cyan4" ))+
  theme_bw()+
  theme(legend.position="none")

# Gráfico 2
df2 <- data.frame(pr.out$x[, 1:2], nci.labs)
p2 <- ggplot(df2, aes(x = PC1, y = PC2, colour = nci.labs)) +
  geom_point(size = 3)+
  labs(x = "Z1", y = "Z2")+
  theme_bw()+
  theme(legend.position="none")

# Gráficos lado a lado: dos alternativas
library(gridExtra)
grid.arrange(p1, p2, ncol = 2)

library(cowplot)
plot_grid(p1, p2, labels = "AUTO")

# Con leyenda modificando su título
ggplot(df2, aes(x = PC1, y = PC2, colour = nci.labs)) +
  geom_point(size = 3)+
  labs(x = "Z1", y = "Z2", colour = "Types of cancer")+
  theme_bw()

Gráficos con ggplot2

Alternativa con el paquete Graphics

Con el paquete graghics de la configuración base de R.

# Asigno colores manualmente para el primer gráfico
df3 <- data.frame(pr.out$x[, 1:2], nci.labs) %>% 
  mutate(groups =ifelse(
  PC1 < -40, 'red', ifelse(
  PC1 > -42 & PC2 > 1, 'blue', ifelse(
  PC1 > 25 & PC2 < 1, 'green4', 'cyan4'))))

# Función para asignar colores del segundo gráfico
Cols <- function(vec){
  cols=rainbow(length(unique(vec)))
  return(cols[as.numeric(as.factor(vec))])
}
# Gráficos
par(mfrow = c(1,2))
plot(df1[, 1:2], col = df3$groups, pch = 19, xlab = "Z1", ylab = "Z3")
plot(df1[, 1:2], col = Cols(nci.labs), pch = 19, xlab = "Z1", ylab = "Z2")

Entradas relacionadas

2018-08-27

Gráficos de An Introduction to Statistical Learning con ggplot2 - Figura 1.3.

Gráfico a replicar

Continuamos con la serie iniciada sobre la creación de gráficos del libro An Introduction to Statistical Learning con ggplot2 parte 1. En esta ocasión replicaremos el gráfico de la figura 1.3. Se trata de un diagrama de caja en el que representamos el resultado de un análisis discriminante cuadrático (lda). Aplicamos un análisis análisis discriminante cuadrático al subconjunyo de datos de Smarket comprendido entre 2001-2007 y predecimos la probabilidad de que el mercado de valores decrezca usando los datos de 2005.

Solución

# Análisis discriminante cuadrático
library(ISLR)
library(MASS)
library(ggplot2)
train <- (Smarket$Year < 2005)
Direction.2005 <- Smarket$Direction[!train]
Smarket.2005 <- Smarket[!train,]
qda.fit <-  qda(Direction ~ Lag1 + Lag2, data = Smarket, subset = train)
qda.class <- predict(qda.fit, Smarket.2005)$class
mean(qda.class == Direction.2005)
[1] 0.5992063
En media la predicción de probabilidad de que decrezca el mercado de valores es mayor en los días en los que el mercado decrece. Basándonos en estos resultados, podemos predecir correctamente la dirección del movimiento de mercado en un 60% de las veces.

  • Gráfico
  • En este caso la creación del gráfico es sencilla y prácticamente idéntica a la de la entrada anterior. El único reto es utilizar correctamente la salida de datos de qda.pred.

    qda.pred <- predict(qda.fit, Smarket.2005)
    qda.pred <- cbind(data.frame(qda.pred), pred = Direction.2005)
    
    ggplot(qda.pred, aes(x = pred, y = posterior.Down, fill = pred)) +
      stat_boxplot(geom = "errorbar", width = 0.5) +
      geom_boxplot(show.legend = FALSE, outlier.alpha = .5) +
      scale_fill_manual(values = c("royalblue", "orangered")) +
      labs(x = "Today's Direction", y = "Predicted probability")
    
    Dejo el panel de fondo por defecto pues ayuda a evaluar mejor el gráfico. Si lo que queremos en blanco tal y como el libro añadiríamos al código anterior:

    theme(panel.background = element_blank())

    Entradas relacionadas

    2018-08-14

    Gráficos de An Introduction to Statistical Learning con ggplot2 - Figura 1.2

    Gráfico a replicar

    Continuamos con la serie iniciada sobre la creación de gráficos del libro An Introduction to Statistical Learning con ggplot2 parte 1. En esta ocasión replicaremos el gráfico de la figura 1.2. Se trata de tres pares de diagramas de caja, representando el índice S&P 500 entre 2001 y 2005. En cada uno de ellos se representa si el índice subió o bajó respecto al día anterior para tres momentos en el tiempo: ayer, hace dos días y hace tres días.

    Solución

    No lo replicamos idénticamente a propósito. Es más eficinet usar facet_grid para mostrar los tres en un solo gráfico y no repetir títulos de los ejes 3 veces. La parte esencial para obtenerlo es la transformación del data frame de formato ancho a largo con la función gather de tidyr. Renombramos los niveles de la variable key y añadimos colores similares, títulos de los ejes y cierto nivel de transparencia para los valores atípicos (outliers).

    library(tidyr)
    library(dplyr)
    Smarket %>%
      gather(key, value, Lag1:Lag3) %>%
      mutate(key = recode(
        factor(key),
        Lag1 = "Yesterday",
        Lag2 = "Two Days Previous",
        Lag3 = "Three Days Previous"
      )) %>% 
      ggplot(aes(x = Today, y = value, fill = Direction)) +
      geom_boxplot(outlier.alpha = .5) +
      facet_grid( ~ key) +
      scale_fill_manual(values = c("royalblue", "orangered")) +
      labs(x = "Today's Direction", y = "Percentage change in S&P")+
      theme(panel.background = element_blank())
    
  • Alternativa
  • Podríamos haber creado los tres gráficos de manera independiente como mostramos a continuación y unirlos con gridExtra. En este caso necesitamos repetir cada argumento o refinamiento del gráfico tres veces.

    library(gridExtra)
    # Yesterday
    p1 <-
      ggplot(Smarket, aes(x = Direction, y = Lag1, fill = Direction)) +
      geom_boxplot(show.legend = FALSE, outlier.alpha = .5) + ggtitle("Yesterday") +
      scale_fill_manual(values = c("royalblue", "orangered")) +
      labs(x = "Today's Direction", y = "Percentage change in S&P")
    # Two Days Previous
    p2 <-
      ggplot(Smarket, aes(x = Direction, y = Lag2, fill = Direction)) +
      geom_boxplot(show.legend = FALSE, outlier.alpha = .5) + ggtitle("Two Days Previous") +
      scale_fill_manual(values = c("royalblue", "orangered")) +
      labs(x = "Today's Direction", y = "Percentage change in S&P")
    # Three Days Previous
    p3 <-
      ggplot(Smarket, aes(x = Direction, y = Lag3, fill = Direction)) +
      geom_boxplot(show.legend = FALSE, outlier.alpha = .5) + ggtitle("Three Days Previous") +
      scale_fill_manual(values = c("royalblue", "orangered")) +
      labs(x = "Today's Direction", y = "Percentage change in S&P")
    grid.arrange(p1, p2, p3, ncol = 3)
    

    Entradas relacionadas

    2018-08-12

    Ajustar espacio entre los elementos de una leyenda en ggplot2

    Problema

    Tenemos el siguiente gráfico en el que deseamos separar los dos elementos de la leyenda: automatic y manual.

    library(tidyverse)
    mtcars %>%
      mutate(transmission = ifelse(am, "manual", "automatic")) %>%
      ggplot() +
      aes(x = transmission, fill = transmission) +
      geom_bar() +
      labs(fill = NULL) +
      theme(
        #legend.spacing.x = unit(.5, "char"), # adds spacing to the left too
        legend.position = "top",
        legend.justification = c(0, 0),
        legend.title = element_blank(),
        legend.margin = margin(c(5, 5, 5, 0))
      )
    

    Solución

  • Primera opción: espacio entre los 4 elementos
  • Empleamos legend.spacing.x que crea un espacio entre los 4 elementos, las muestras de color y los textos.

    mtcars %>%
      mutate(transmission = ifelse(am, "manual", "automatic")) %>%
      ggplot() +
      aes(x = transmission, fill = transmission) +
      geom_bar() +
      labs(fill = NULL) +
      theme(
        legend.spacing.x = unit(.5, "char"),
        legend.position = "top",
        legend.justification = c(0, 0),
        legend.title = element_blank(),
        legend.margin = margin(c(5, 5, 5, 0)))
    
  • Segunda opción: espacio entre los 2 grupos de elementos
  • Empleamos margin dentro de element_text para crear un espacio solamente entre los grupos de elementos, el correspondiente a la serie automatic y el correspondiente a manual.

    mtcars %>%
      mutate(transmission = ifelse(am, "manual", "automatic")) %>%
      ggplot() +
      aes(x = transmission, fill = transmission) +
      geom_bar() +
      labs(fill = NULL) +
      theme(legend.position = "top",
        legend.justification = c(0, 0),
        legend.title = element_blank(),
        legend.margin = margin(c(5, 5, 5, 0)),
        legend.text = element_text(margin = margin(r = 10, unit = "pt")))
    

    Entradas relacionadas

    Referencias

    2018-08-10

    Gráficos de An Introduction to Statistical Learning con ggplot2 - Figura 1.1.

    Introducción

    Uno de los libros más populares para aprender estadística repleto de ejemplos en R es An Introduction to Statistical Learning. En esta y tal vez sucesivas entradas, vamos a recrear con ggplot2 algunos de los gráficos mostrados en el libro. En este caso los 3 primeros gráficos de la figura 1.1.

    Solución

     # Cargamos paquetes y datos necesarios
    library(ISLR)
    attach(Wage)
    library(ggplot2)
    

    1. Diagrama de dispersión: edad y salarios
    2. Los salarios como una función de la edad. En media, los salarios se incrementan con la edad hasta llegar a los 60 años, a partir de entonces empiezan a declinar.

      A diferencia del gráfico original, mostramos un intervalo de confianza alrededor de la línea que se traza siguiendo el método de suavizado (smoothing method) de gam (generalized additive models) al tener más de 1.000 observaciones. Es un típico ejemplo de overplotting, la representación de las observaciones es tan densa que dificulta la lectura del gráfico. Trataremos este problema en otra entrada.

      ggplot(Wage, aes(x= age, y = wage)) + 
        geom_point()+
        geom_smooth() # se = FALSE sin intervalo de confianza
      
    3. Diagrama de dispersión: años y salarios.
    4. Representamos los salarios como una función del año. Hay un incremento ligero pero constante de aproximadamente 10.000 dólares de 2003 a 2009.

      Si tratamos de aplicar la función anterior geom_smooth, nos aparecerá el siguiente mensaje 'Warning message: Computation failed in `stat_smooth()`: x has insufficient unique values to support 10 knots: reduce k.' Para resolverlo usamos stat_summary para representar la media.

      ggplot(Wage, aes(x= year, y = wage)) + 
        geom_point() + stat_summary(
          fun.y = mean,
          colour = "blue",
          geom = "line",
          size = 1.5
        )
      
    5. Diagrama de caja: educación y salarios
    6. Los diagramas de caja representan los salarios como una función de la educación con 1 indicando el nivel más bajo (sin diploma de bachillerato) y 5 el nivel más alto (nivel de postgrado avanzado). En media, lo salarios se incrementan con el nivel de educación.

      Utilizamos la función geom_boxplot con los argumentos por defecto e indicamos fill para colorear el interior de las mismas.

      ggplot(Wage, aes(x= education, y = wage, fill = education)) + 
        geom_boxplot()
      

    Entradas relacionadas

    Nube de datos