Capítulo 4 Gráficos

4.1 Introducción

En este capitulo se muestra como crear diferentes tipos de gráficos, tanto estáticos usando el paquete ggplot2 (Wickham, 2016; Wickham et al., 2020), como dinámicos usando los paquetes highcharter (Kunst, 2019), plotly (Sievert et al., 2020), y dygraphs (Vanderkam et al., 2018).

En este capitulo se van a utilizar los siguientes paquetes:

library(babynames)
library(nycflights13)
library(gapminder)
library(dygraphs)
library(highcharter)
library(plotly)
library(RColorBrewer)
library(viridis)
library(rio)
library(cowplot)
library(patchwork)
library(tidymodels)
library(tidyverse)

Los tres primeros corresponden con conjuntos de datos. Así mismo se vuelven a importar y manipular los datos con que se venia trabajando:

data("airquality")
dat1 <- import("data/LungCapData2.csv", setclass = 'tibble')
titanic <- import("data/titanic.csv", setclass = 'tibble')

titanic = titanic %>% 
  mutate(Pclass = as_factor(Pclass),
         Survived = as_factor(Survived),
         Sex = as_factor(Sex))

airq = airquality %>% 
  mutate(Month = factor(Month,
                        levels = 5:9,
                        labels = c("Mayo", "Junio", "Julio", 
                                   "Agosto", "Setiembre")),
         Sensation = case_when(Temp < 60 ~ 'Cold',
                               Temp < 70 ~ 'Cool',
                               Temp < 85 ~ 'Warm',
                               T ~ 'Hot') %>% 
           as.factor())

4.2 Estáticos

El paquete por excelencia, como se menciono al principio del capitulo, para crear gráficos en R es ggplot2. Este se basa en la gramática de gráficos (grammar of graphics), de ahí el gg en el nombre.

La estructura básica de cualquier gráficos es:

ggplot(data = <DATA>) +
  <GEOM_FUNCTION>(mapping = aes(<MAPPINGS>),
                  stat = <STAT>, position = <POSITION>) +
  <FACET_FUNCTION> +
  <SCALE_AESTHETIC_TYPE> +
  <THEME_FUNCTION>

donde las partes principales son ggplot y geom_*, el resto no son necesarias. Dentro de geom_* se mapean la variables de la tabla a los argumentos de la función (x, y, col, fill, size, shape, alpha). La idea básica es trabajar en capas para poder modificar el gráfico con mayor detalle y facilidad.

4.2.1 Histograma

Este se utiliza para datos numéricos continuos.

Dentro de geom_histogram hay 3 opciones para definir la discretizacion:

  • bins = Numero de clases
  • binwidth = El ancho de las clases
  • breaks = Un vector con los puntos donde separar los datos

El primer gráfico (Figura 4.1) muestra el resultado de geom_histogram por defecto. Aquí se esta graficando la temperatura (‘Temp’) de la tabla ‘airquality’ en el eje x, es el eje que hay que usar en los histogramas.

p = ggplot(data = airquality, mapping = aes(x=Temp)) +
  geom_histogram()
p
Histograma básico

Figura 4.1: Histograma básico

La apariencia del gráfico anterior se puede mejorar usando los argumentos col y fill, donde el primero corresponde con el color del borde de las barras, y el segundo con el relleno de las barras (Figura 4.2).

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,col="black",fill="blue")
Histograma modificando la cantidad de barras y apariencia

Figura 4.2: Histograma modificando la cantidad de barras y apariencia

El eje x, sobre el cual estamos graficando los datos, se puede modificar con más detalle usando las funciones scale_x_*, donde en este caso usamos scale_x_continuous() por estar trabajando con datos continuos (Figura 4.3). El primer argumento de estas funciones es el nombre que se le quiere dar al eje, y en el caso siguiente, se modifican las etiquetas del eje con el argumento labels, donde se puede usar una de tantas funciones que se encuentran en el paquete scales.

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(binwidth = 2,col="black",fill="blue") + 
  scale_x_continuous('Temperatura', labels = label_number(suffix = ' ºC'))
Histograma modificando la apariencia del eje x

Figura 4.3: Histograma modificando la apariencia del eje x

Otra de las capas que se puede usar son las facetas o paneles, que permiten separar un tipo de gráfico, en este caso un histograma, en diferentes gráficos de acuerdo a otra variable, por lo general categórica (Figura 4.4). La función para esto es facet_wrap(~ variable). Esta función es útil para una variable, para dos o más variables es mejor usar facet_grid(filas ~ cols) (Ver Figuras 4.12 y 4.13).

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,col="black",fill="blue") +
  facet_wrap(~ Month)
Histograma en paneles

Figura 4.4: Histograma en paneles

Se venían rellenando las barras todas de un mismo color, por lo que el argumento fill se pone fuera del aes(). Si se quiere rellenar las barras de acuerdo al conteo o densidad es necesario insertar dentro del aes() de geom_histogram el fill=after_stat(.), donde el punto (.) puede corresponder con el conteo (count) o la densidad (density). Así como se modifica el eje x anteriormente con scale_x_*, se puede modificar el relleno con scale_fill_*. En este caso (Figura 4.5) se usa scale_fill_distiller() para usar una de las paletas disponibles en el paquete RColorBrewer (Neuwirth, 2014), donde se tiene que especificar el nombre de la paleta de colores a usar, en este caso palette = 'YlOrRd'.

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,aes(fill=after_stat(count)),col="black") +
  scale_fill_distiller(palette = 'YlOrRd')
Histograma con relleno de acuerdo al conteo

Figura 4.5: Histograma con relleno de acuerdo al conteo

Las paletas disponibles se observan en la Figura 4.6, donde el primer bloque de colores corresponde con las paletas secuenciales (seq), el segundo bloque con las paletas cualitativas (qual), y el tercer bloque con las paletas divergentes (div).

Paletas disponibles en *RColorBrewer*

Figura 4.6: Paletas disponibles en RColorBrewer

Así como se puede modificar el relleno de las barras, se puede modificar que el eje y no corresponda con el conteo sino con la densidad (Figura 4.7), para esto es necesario insertar dentro del aes() de geom_histogram el y=after_stat(density), y esto es necesario si se quiere agregar la curva de densidad de los datos (geom_density) para ver su distribución.

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,aes(y=after_stat(density)),
                 col="black",fill="blue") +
  geom_density(col="red")
Histograma mostrando la densidad en el eje y en vez del conteo, con la curva de densidad superpuesta

Figura 4.7: Histograma mostrando la densidad en el eje y en vez del conteo, con la curva de densidad superpuesta

La densidad no es lo mismo que la frecuencia relativa (Figura 4.8). La densidad es el ajuste a la función de densidad de los datos donde la integral suma a 1, la frecuencia relativa es el porcentaje de observaciones por clase. Para esto es necesario insertar dentro del aes() de geom_histogram el y=after_stat(count/sum(count)).

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,aes(y=after_stat(count/sum(count))),
                 col="black",fill="blue")
Histograma mostrando la frecuencia relativa en el eje y en vez del conteo o la densidad

Figura 4.8: Histograma mostrando la frecuencia relativa en el eje y en vez del conteo o la densidad

A veces se quiere representar la frecuencia acumulada (absoluta o relativa), con lo que el histograma va a presentar una tendencia ascendente hasta llegar al total de observaciones (absoluta) o hasta uno (relativa). Para lograr esto se hace uso de la función cumsum al definir aes(y), como se muestra en las Figuras 4.9 y 4.10, para frecuencias absolutas y relativas respectivamente.

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,aes(y=after_stat(cumsum(count))),
                 col="black",fill="blue")
Histograma mostrando la frecuencia absoluta acumulada. En este caso \(N = 153\).

Figura 4.9: Histograma mostrando la frecuencia absoluta acumulada. En este caso \(N = 153\).

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,aes(y=after_stat(cumsum(count/sum(count)))),
                 col="black",fill="blue")
Histograma mostrando la frecuencia relativa acumulada

Figura 4.10: Histograma mostrando la frecuencia relativa acumulada

Combinando lo aprendido hasta ahora se pueden modificar el relleno junto con el eje y, así como agregar la curva de densidad, para generar un gráfico que brinda más información (Figura 4.11).

ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,
                 aes(y=after_stat(density),fill=after_stat(count)),
                 col="black") +
  geom_density(col="red")
Histograma mostrando la densidad en el eje y en vez del conteo, con la curva de densidad superpuesta, y relleno de acuerdo al conteo

Figura 4.11: Histograma mostrando la densidad en el eje y en vez del conteo, con la curva de densidad superpuesta, y relleno de acuerdo al conteo

Estos últimos dos gráficos agregan más cosas que permiten crear gráficos más complejos e informativos sin mucho esfuerzo, incluyendo paneles de acuerdo a dos variables usando facet_grid. El primero (Figura 4.12) agrega el relleno de acuerdo a una variable categórica, así como un paneleo por dos variables definiendo filas y columnas. El segundo (Figura 4.13) construye sobre el primero pero modificando las etiquetas de los paneles usando el argumento labeller, donde se define labeller(variable = vector con nombres), ademas se cambia el relleno con scale_fill_viridis y se modifican las etiquetas con un vector (c('actual' = 'nuevo')). El vector con nombres de labeller y el vector de etiquetas llevan la estructura c('actual' = 'nuevo'), donde ‘actual’ es el valor que tiene la variable y ‘nuevo’ es el nombre que se quiere aparezca en el gráfico.

ggplot(titanic, aes(x = Age, fill = Survived)) +
  facet_grid(Sex ~ Pclass) +
  geom_density(alpha = 0.5)
Curva de densidad haciendo uso de varias variables categóricas

Figura 4.12: Curva de densidad haciendo uso de varias variables categóricas

ggplot(titanic, aes(x = Age, fill = Survived)) +
  facet_grid(Sex ~ Pclass, 
             labeller = labeller(Sex = c('male'='Masculino',
                                         'female'='Femenino'),
                                 Pclass = c('1'='1era','2'='2nda','3'='3era'))) +
  geom_density(alpha = 0.5) +
  scale_fill_viridis_d('Sobrevivió', labels = c('1'='Si','0'='No'))
Versión mejorada del gráfico anterior

Figura 4.13: Versión mejorada del gráfico anterior

4.2.2 Barras

Este se utiliza para datos categóricos.

Dentro de geom_bar el argumento position puede tener cualquiera de estos tres valores:

  • stack: Apila barras una encima de otra
  • dodge: Pone barras de manera adyacente
  • fill: Las barras tienen la misma altura, normalizadas a 1 (proporciones)

geom_bar hace el conteo de clases, en caso de tener ya el conteo hecho se usa geom_col.

De manera general se puede pasar solo una variable para realizar el conteo, pero este tipo de gráficos es más útil cuando se pueden agregar otras variables categóricas.

En el primer ejemplo (Figura 4.14) se hace el conteo por genero, y se rellena por si fuman o no, lo que brinda una visión de la cantidad (o proporción) de hombres y mujeres que fuman o no. En este ejemplo se utiliza position = "fill", lo que hace que todas las barras tengan las misma altura y comprendan el rango de 0 a 1 en el eje y, lo que asemeja a una visión de proporciones. Adicionalmente, se modifica el eje y (scale_y_continuous) asignándole un nombre y cambiando las etiquetas a porcentaje (labels = label_percent()).

ggplot(dat1, aes(Gender,fill=Smoke)) + 
  geom_bar(position = "fill") + 
  scale_y_continuous('Proporción',labels = label_percent())
Gráfico de barras con el argumento de posición `fill`, para mostrar proporciones entre categorias

Figura 4.14: Gráfico de barras con el argumento de posición fill, para mostrar proporciones entre categorias

El siguiente gráfico (Figura 4.15) es similar al primero, en que se grafican los mismos datos, pero de otra manera. Se usa position = "dodge", lo que pone una barra a la par de la otra (esto para la categoría usada en el relleno); adicionalmente, se modifica el eje x (scale_x_discrete) asignándole un nombre y modificando los nombres de las etiquetas (labels); por ultimo, se modifica de forma manual el relleno (scale_fill_manual) asignándole un nombre, que es el que aparecer en la leyenda, las etiquetas (que deben tener el mismo orden de los niveles de la variable), y los valores (values) son los colores a usar para cada nivel.

ggplot(dat1, aes(Gender,fill=Smoke)) + 
  geom_bar(position = "dodge") + 
  scale_x_discrete('Genero', labels = c('Femenino','Masculino')) + 
  scale_fill_manual('Fumado', labels = c('Si','No'), 
                    values = c('darkred','green4'))
Gráfico de barras con apariencia modificada y posición de las barras una a la par de la otra

Figura 4.15: Gráfico de barras con apariencia modificada y posición de las barras una a la par de la otra

De igual manera se pueden generar paneles de acuerdo a una variable categórica (Figura 4.16).

ggplot(titanic, aes(x = Sex, fill = Survived)) + 
  facet_wrap(~ Pclass) + 
  geom_bar()
Gráfico de barras en paneles

Figura 4.16: Gráfico de barras en paneles

Cuando se gráfica una variable únicamente el orden de las barras va a estar en función del orden de los niveles (Figura 4.17), pero esta representación puede que no sea la más clara visualmente. Para corregir lo anterior se pueden reordenar los niveles de la variable (únicamente para el gráfico) de acuerdo a la frecuencia (de mayor a menor), usando fct_infreq del paquete forcats (Figura 4.18).

gss_cat %>% 
  ggplot(aes(marital)) + 
  geom_bar()
Gráfico de barras básico con orden de barras de acuerdo al orden de los niveles

Figura 4.17: Gráfico de barras básico con orden de barras de acuerdo al orden de los niveles

gss_cat %>% 
  ggplot(aes(fct_infreq(marital))) + 
  geom_bar()
Gráfico de barras ordenado de acuerdo a la frecuencia de los niveles

Figura 4.18: Gráfico de barras ordenado de acuerdo a la frecuencia de los niveles

Los ejemplos anteriores usaban geom_bar, pero en el caso de que ya se tenga el conteo se puede usar geom_col. En este caso hay que especificar la variable a graficar en x y el conteo en y, el resto de modificaciones se pueden aplicar de igual manera a como se venia mostrando. En este ejemplo (Figura 4.19) debido a que los niveles corresponden con nombres largos y hay muchos, se usa el cambiar los ejes por medio de coord_flip, lo que va a poner en ‘y’ lo que estaba en ‘x’ y viceversa.

mpg %>% 
  count(manufacturer, year) %>% 
  mutate(year = as.factor(year)) %>% 
  ggplot(aes(manufacturer,n,fill=year)) + 
  geom_col(position = 'dodge') + 
  coord_flip() + 
  scale_fill_brewer(palette = 'Dark2')
Gráfico de barras precontado y cambiando ejes para mayor claridad

Figura 4.19: Gráfico de barras precontado y cambiando ejes para mayor claridad

4.2.3 Boxplot

Este tipo se usa para datos numéricos continuos que normalmente se separan por una variable categórica. Los datos continuos se grafican en el eje y, por lo que hay que especificar esto explícitamente en el aes() (Figura 4.20), y si se quiere separar por una variable categórica, esta se asigna al eje x (Figura 4.21).

ggplot(airq,aes(y=Temp)) +
  geom_boxplot()
Gráfico boxplot básico

Figura 4.20: Gráfico boxplot básico

ggplot(airq,aes(x = Month,y = Temp)) +
  geom_boxplot()
Gráfico boxplot separado por variable categórica

Figura 4.21: Gráfico boxplot separado por variable categórica

En el tercer ejemplo (Figura 4.22) se agregan un par de funciones que no se habían visto: labs y theme_bw. labs permite modificar los nombres de los ejes y estéticas (col, fill, etc.) sin tener que usar las funciones scale_*_*. theme_bw es uno de los tantos temas que vienen definidos y cambia la apariencia a un gráfico en blanco y negro, removiendo el fondo gris que en muchos casos no es lo mejor.

ggplot(airq,aes(x = Month,y = Temp)) +
  geom_boxplot(fill="white",col="red") +
  labs(x="Mes",y="Temperatura") +
  theme_bw()
Gráfico boxplot con apariencia modificada

Figura 4.22: Gráfico boxplot con apariencia modificada

4.2.4 Dispersión

Estos aplican para datos numéricos continuos en ambos ejes. Un gráfico básico se muestra en el primer ejemplo (Figura 4.23).

ggplot(airquality, aes(Ozone,Temp)) + 
  geom_point()
Gráfico de dispersión básico

Figura 4.23: Gráfico de dispersión básico

Para el caso de puntos se puede cambiar el tipo de icono con el argumento shape, este puede definirse de manera global para todos los puntos o de acuerdo a una variable categórica (Figura 4.24).

ggplot(airq, aes(Ozone,Temp,shape=Month)) + 
  geom_point()
Gráfico de dispersión con la forma de los puntos de acuerdo a una variable categórica

Figura 4.24: Gráfico de dispersión con la forma de los puntos de acuerdo a una variable categórica

Una tarea común en gráficos de dispersión es agregar líneas de tendencia. Para agregar líneas de tendencia en ggplot2 se usa la función geom_smooth. Por defecto ajusta una curva loess, pero para cambiarlo se usa el argumento method = 'lm' (Figura 4.25), y para especificar una ecuación diferente a la regresión simple (y ~ x) se usa formula, donde y y x son genéricos (Figura 4.26), NO hay que poner el nombre de las variables que se esta graficando.

ggplot(airquality, aes(Wind,Temp)) + 
  geom_point() + 
  geom_smooth(method = "lm")
Gráfico de dispersión con línea de tendencia lineal

Figura 4.25: Gráfico de dispersión con línea de tendencia lineal

ggplot(airquality, aes(Ozone,Temp)) + 
  geom_point() + 
  geom_smooth(method = "lm", formula = y~poly(x,2))
Gráfico de dispersión con línea de tendencia polinomial

Figura 4.26: Gráfico de dispersión con línea de tendencia polinomial

En este caso (Figura 4.27) cuando se aplica el paneleo (facet_wrap) se obtiene una gráfico de dispersión con su respectiva línea de tendencia para cada uno de los niveles de la variable categórica.

ggplot(airquality, aes(Wind,Temp)) + 
  geom_point() + 
  geom_smooth(method = "lm") + 
  facet_wrap(~ Month)
Gráfico de dispersión en paneles con línea de tendencia para cada panel

Figura 4.27: Gráfico de dispersión en paneles con línea de tendencia para cada panel

4.2.5 líneas

Estos gráficos son una versión del gráfico de dispersión, donde el eje x corresponde con una variable continua que tiene cierta secuencia o patrón, por lo general tiempo o espacio.

El primer gráfico (Figura 4.28) muestra como ha cambiado el uso del nombre ‘Max’ a lo largo del tiempo. Primero se filtran los datos para el nombre de interés, y se seleccionan las variables a usar en el gráfico. Como el eje y corresponde con proporción, se modifica para que muestre el porcentaje.

babynames %>% 
  filter(name == "Max") %>% 
  select(year, prop, sex) %>% 
  ggplot(mapping = aes(x = year, y = prop)) + 
  geom_line(mapping = aes(color = sex)) + 
  scale_y_continuous(labels = label_percent())
Gráfico de línea básico

Figura 4.28: Gráfico de línea básico

En el segundo gráfico de líneas (Figura 4.29) se grafica el numero de tormentas por año, de nuevo, realizando una manipulación de los datos para obtener la información que se desea desplegar. El ultimo gráfico (Figura 4.30) simplemente hace la separación de diferentes líneas de acuerdo a una variable categórica.

storms %>%
  group_by(year) %>% 
  summarize(n_storm = n_distinct(name)) %>% 
  ggplot() +
  geom_line(mapping = aes(x = year, y = n_storm))
Gráfico de línea básico con otros datos

Figura 4.29: Gráfico de línea básico con otros datos

storms %>%
  group_by(year,status) %>% 
  summarize(n_storm = n_distinct(name)) %>% 
  ggplot() +
  geom_line(mapping = aes(x = year, y = n_storm, col = status))
Gráfico de línea básico, con diferentes líneas de acuerdo a una variable categórica

Figura 4.30: Gráfico de línea básico, con diferentes líneas de acuerdo a una variable categórica

4.2.6 Gráficos estadísticos

Estos sirven para resumir los datos. Los ejemplos que aquí se muestran corresponden con el despliegue de intervalos de confianza de una variable numérica para diferentes niveles de una variable categórica.

ggplot(airquality, aes(Month, Temp)) +
  stat_summary(fun.y = mean,
               geom = "point",
               color = "black") +
  stat_summary(fun.data = mean_cl_normal,
               geom = "errorbar",
               width = 0.2) +
  theme_bw()
Gráfico estadístico mostrando intervalo de confianza como barras de error

Figura 4.31: Gráfico estadístico mostrando intervalo de confianza como barras de error

ggplot(airquality, aes(Month, Temp)) +
  stat_summary(fun.data = mean_cl_normal,
               geom = "pointrange",
               color = "red",
               size=1) +
  theme_bw()
Gráfico estadístico mostrando intervalo de confianza como punto y rango

Figura 4.32: Gráfico estadístico mostrando intervalo de confianza como punto y rango

4.2.7 Transformación de ejes

En algunas ocasiones, dependiendo de la escala y rango que tenga los datos, una transformación de uno o ambos ejes sea necesaria, siendo los más típico para datos numéricos continuos. El ejemplo más típico es la transformacional logarítmica (natural o base 10), para los casos donde los datos comprenden varios ordenes de magnitud.

En ggplot2 esto puede hacerse de dos maneras:

  • scale_<eje>_<tipo>(trans = '#'),
  • coord_trans(<eje> = '#')

donde # corresponde con la transformacional a realizar, y puede tomar los siguientes valores: “asn”, “atanh”, “boxcox”, “date”, “exp”, “hms”, “identity”, “log”, “log10”, “log1p”, “log2”, “logit”, “modulus”, “probability”, “probit”, “pseudo_log”, “reciprocal”, “reverse”, “sqrt”, y “time”. Siendo las más comunes las resaltadas en negrita, donde “log” se refiere al logaritmo natural, “log10” al logaritmo base 10, y “reverse” para invertir el eje.

La diferencia de usar scale_* o coord_trans radica en cuando se aplica la transformacional. Con scale_* la transformación es aplicada a los datos antes de ser graficados, por lo que se grafica son los datos transformados (Figura 4.33, B); con coord_trans la transformación se aplica después de ser graficados, o sea se aplica sobre el eje, modificando la apariencia y no los datos en si (Figura 4.33, C).

La Figura 4.33, es una grilla de gráficos, la cual fue realizada por medio de cowplot (Wilke, 2019). Otro paquete para generar grillas de gráficos es patchwork (Pedersen, 2019), y este ofrece más flexibilidad con la manipulación y posicionamiento de los gráficos (Figura 4.34). En ambos casos, se ve claramente en el subgráfico A que el eje x tiene varios ordenes de magnitud. En el subgráfico B se aplico scale_x_continuous(trans = 'log10'), lo cual aplica una transformación logarítmica a los datos antes de plotearlos y por eso los diferentes valores. En el subgráfico C se aplico coord_trans(x = 'log10'), lo cual simplemente modifica la apariencia del eje, donde se observa esa escala logarítmica, manteniendo los valores originales; adicionalmente se cambian los valores del eje (scale_x_continuous(breaks = c(10,100,1000,10000))) para que no se vean tan apilados.

cow1 = ggplot(msleep) + 
  geom_point(aes(bodywt,sleep_total))

cow2 = ggplot(msleep) + 
  geom_point(aes(bodywt,sleep_total)) + 
  scale_x_continuous(trans = 'log10')

cow3 = ggplot(msleep) + 
  geom_point(aes(bodywt,sleep_total)) + 
  coord_trans(x = 'log10') +
  scale_x_continuous(breaks = c(10,100,1000,10000))

plot_grid(cow1, cow2, cow3, ncol = 1, labels = 'AUTO')
Ejemplo de transformación de ejes, en este caso solo el eje x, usando *cowplot*. **A** es el gráfico sin datos tranformados; **B** es el gráfico usando `scale_*`; **C** es el gráfico usando `coord_trans`

Figura 4.33: Ejemplo de transformación de ejes, en este caso solo el eje x, usando cowplot. A es el gráfico sin datos tranformados; B es el gráfico usando scale_*; C es el gráfico usando coord_trans

cow1 / (cow2 | cow3) + 
  plot_annotation(tag_levels = 'A') & 
  theme_bw()
Ejemplo de transformación de ejes, en este caso solo el eje x, usando *patchwork*. **A** es el gráfico sin datos tranformados; **B** es el gráfico usando `scale_*`; **C** es el gráfico usando `coord_trans`

Figura 4.34: Ejemplo de transformación de ejes, en este caso solo el eje x, usando patchwork. A es el gráfico sin datos tranformados; B es el gráfico usando scale_*; C es el gráfico usando coord_trans

4.2.8 Limites de ejes (Zoom)

Otra acción que tal vez se quiera realizar puede ser delimitar los valores mínimos y máximos de los ejes, ya sea para tener control sobre estos, o para realizar una especie de acercamiento (zoom) en una región del gráfico.

La manera apropiada de realizar esto es por medio de coord_cartesian(*lim), donde *lim se refiere al eje x o y. la otra forma que tal vez aparezca por ahí, pero no da los resultados deseados es usando scale_<eje>_<tipo>(limits). En ambos casos se brinda un vector de mínimo y máximo.

La Figura 4.35 muestra el gráfico inicial, y como afectan las diferentes funciones. De manera similar a la transformación, scale_* aplica los limites antes de graficar, por lo que los datos que caen fuera de esos limites son descartados y no ploteados (de ahí la advertencia). En cambio, coord_cartesian aplica los limites después de graficados los datos, por lo que simplemente es un cambio en la representación del eje y no en los datos.

z1 = gss_cat %>% 
  ggplot(aes(y=marital)) + 
  geom_bar()

z2 = gss_cat %>% 
  ggplot(aes(y=marital)) + 
  geom_bar() + 
  scale_x_continuous(limits = c(0,5000))

z3 = gss_cat %>% 
  ggplot(aes(y=marital)) + 
  geom_bar() + 
  coord_cartesian(xlim = c(0,5000))

z1 / (z2 | z3) + 
  plot_annotation(tag_levels = 'A') & 
  theme_bw()
Ejemplo de modificar los límites del eje y en este caso. **A** es el gráfico original **B** es el gráfico usando `scale_*`; **C** es el gráfico usando `coord_cartesian`

Figura 4.35: Ejemplo de modificar los límites del eje y en este caso. A es el gráfico original B es el gráfico usando scale_*; C es el gráfico usando coord_cartesian

4.2.9 Salvando gráficos

Se muestran funciones para salvar gráficos, donde las extensiones más usadas son .png, .tiff, y .pdf. Por defecto ggsave salva el ultimo gráfico creado, a menos que se haya guardado el gráfico en un objeto y se le pase dicho objeto al argumento plot. El resto de argumentos son claros en lo que representan. Para el caso de un .pdf hay que remover el argumento type.

ggsave(filename = "figures/Testgg.png",
       plot = p, dpi = 300,
       width = 7, height = 4, units = "in",
       type = "cairo")

ggsave(filename = "figures/Testgg.pdf",
       plot = p, dpi = 300,
       width = 7, height = 4, units = "in")

4.3 Interactivos

Una vez sabiendo utilizar ggplot2 la forma más sencilla de hacer un gráfico interactivo es mediante plotly::ggplotly(). El paquete plotly (Sievert et al., 2020) se usa para gráficos interactivos y tiene una sintaxis un poco diferente a ggplot2, por lo que hay ciertos gráficos que no van a ser convertidos apropiadamente, pero la mayoría de gráficos debieran funcionar.

Otros paquetes para gráficos interactivos son:

  • highcarter: Sintaxis similar a ggplot, con ciertas limitantes,
  • rbokeh: Gráficos interactivos generales,
  • dygraphs: Series temporales,
  • mapview y leaflet: Mapas

En las siguientes secciones se va a recrear alguno de los gráficos anteriores para hacerlo interactivo con ggplotly, y se va a crear uno similar con highcharter. El ejercicio de entender como funciona highcharter queda a cargo del lector, en general los ejemplos y funciones son claras.

Una característica de estos gráficos interactivos, cuando tienen leyenda, es que al hacer click sobre una de la entradas de la leyenda, esta serie de datos es escondida del gráfico, dejando visible únicamente lo otro. En el caso de highcharter los ejes se ajustan automáticamente, este no es el caso para plotly.

4.3.1 Histograma

La versión interactiva de la Figura 4.11 se muestra en la Figura 4.36, la versión usando highcharter se muestra en la Figura 4.37.

(ggplot(airquality,aes(x=Temp)) +
  geom_histogram(bins = 20,
                 aes(y=after_stat(density),fill=after_stat(count)),
                 col="black") +
  geom_density(col="red")) %>% 
  plotly::ggplotly()

Figura 4.36: Gráfico interactivo de un histograma con plotly

with(airq, hchist(Temp,color='red',name='Temp')) %>% 
  hc_xAxis(title = list(text = 'Temperatura')) %>% 
  hc_exporting(enabled=T)

Figura 4.37: Gráfico interactivo de un histograma con highcharter

4.3.2 Barras

La versión interactiva de la Figura 4.19 se muestra en la Figura 4.38, la versión usando highcharter se muestra en la Figura 4.39. En la versión de highcharter, si se cambia ‘bar’ por ‘column’, el gráfico cambia orientación.

(mpg %>% 
  count(manufacturer, year) %>% 
  mutate(year = as.factor(year)) %>% 
  ggplot(aes(manufacturer,n,fill=year)) + 
  geom_col(position = 'dodge') + 
  coord_flip() + 
  scale_fill_brewer(palette = 'Dark2')) %>% 
  plotly::ggplotly()

Figura 4.38: Gráfico interactivo de barras con plotly

mpg %>% 
  count(manufacturer, year) %>% 
  hchart('bar', hcaes(x = manufacturer, y = n, group = year)) %>% 
  hc_xAxis(title = list(text = 'Constructor')) %>%
  hc_yAxis(title = list(text = 'Cantidad')) %>%
  hc_exporting(enabled=T)

Figura 4.39: Gráfico interactivo de barras con highcharter

4.3.3 Boxplot

La versión interactiva de la Figura 4.21 se muestra en la Figura 4.40, la versión usando highcharter se muestra en la Figura 4.41.

(ggplot(airq,aes(x = Month,y = Temp)) +
  geom_boxplot()) %>% 
  plotly::ggplotly()

Figura 4.40: Gráfico interactivo boxplot con plotly

with(airq, hcboxplot(x = Temp, var = Month)) %>% 
  hc_yAxis(title = list(text = 'Temperatura')) %>%
  hc_xAxis(title = list(text = 'Mes')) %>%
  hc_exporting(enabled=T)

Figura 4.41: Gráfico interactivo boxplot con highcharter

4.3.4 Dispersión

La versión interactiva de la Figura 4.25 se muestra en la Figura 4.42, la versión usando highcharter se muestra en la Figura 4.43, con el agregado de que muestra la ecuación de cada línea de tendencia.

(ggplot(airquality, aes(Wind,Temp)) + 
  geom_point() + 
  geom_smooth(method = "lm")) %>% 
  plotly::ggplotly()

Figura 4.42: Gráfico interactivo de dispersión con plotly

hchart(airq, 'scatter', hcaes(Wind, Temp, group=Month), regression = T) %>% 
  hc_xAxis(title = list(text = 'Viento')) %>%
  hc_yAxis(title = list(text = 'Temperatura')) %>%
  hc_colors(viridis(n_distinct(airq$Month))) %>% 
  hc_add_dependency('plugins/highcharts-regression.js') %>% 
  hc_exporting(enabled=T)

Figura 4.43: Gráfico interactivo de dispersión con highcharter

4.3.5 líneas

La versión interactiva de la Figura 4.30 se muestra en la Figura 4.44, la versión usando highcharter se muestra en la Figura 4.45, y la versión usando dygraphs se muestra en la Figura 4.46. En este ultimo caso es necesario que los datos estén en formato ancho, donde la primer columna corresponde con el eje x, y el resto de columnas corresponden con las series temporales/espaciales a graficar por separado.

(storms %>%
  group_by(year,status) %>% 
  summarize(n_storm = n_distinct(name)) %>% 
  ggplot() +
  geom_line(mapping = aes(x = year, y = n_storm, col = status))) %>% 
  plotly::ggplotly()

Figura 4.44: Gráfico interactivo de líneas con plotly

storms %>%
  group_by(year,status) %>% 
  summarize(n_storm = n_distinct(name)) %>% 
  hchart('line', hcaes(year, n_storm, group = status)) %>% 
  hc_xAxis(title = list(text = 'Año')) %>%
  hc_yAxis(title = list(text = 'Cantidad')) %>%
  hc_exporting(enabled=T) %>% 
  hc_tooltip(shared=T,crosshairs=T,
             backgroundColor='rgba(247,247,247,0.5)',shadow=F) %>% 
  hc_chart(zoomType='x')%>%
  hc_add_theme(hc_theme_google()) %>% 
  hc_plotOptions(line = list(marker = list(
                               enabled = F,
                               radius = 2
                               )
  ))

Figura 4.45: Gráfico interactivo de líneas con highcharter

storms %>%
  group_by(year,status) %>% 
  summarize(n_storm = n_distinct(name)) %>% 
  pivot_wider(names_from = status,values_from = n_storm) %>% 
  dygraph() %>% 
  dyAxis('x', label = 'Año') %>% 
  dyAxis('y', label = 'Cantidad') %>% 
  dyRangeSelector()

Figura 4.46: Gráfico interactivo de líneas con dygraphs

4.3.6 Transformación de ejes

La versión interactiva, usando highcharter, de la Figura 4.33 C se muestra en la Figura 4.47; la versión con ggplotly seria igual que las anteriores.

hchart(msleep, 'scatter', hcaes(bodywt, sleep_total)) %>% 
  hc_xAxis(title = list(text = 'Body Weight'), 
           type = 'logarithmic') %>%
  hc_yAxis(title = list(text = 'Sleep')) %>% 
  hc_chart(zoomType='xy') %>% 
  hc_add_theme(hc_theme_gridlight())

Figura 4.47: Gráfico interactivo con eje logarítmico

4.4 Recursos

Se presentan recursos a consultar para ahondar más en los temas presentados.

tidyverse

ggplot2 Libro de ggplot2.

highcharter

rbokeh

dygraphs

Referencias

Kunst, J. (2019). highcharter: A Wrapper for the ’Highcharts’ Library. https://CRAN.R-project.org/package=highcharter

Neuwirth, E. (2014). RColorBrewer: ColorBrewer Palettes. https://CRAN.R-project.org/package=RColorBrewer

Pedersen, T. L. (2019). patchwork: The Composer of Plots. https://CRAN.R-project.org/package=patchwork

Sievert, C., Parmer, C., Hocking, T., Chamberlain, S., Ram, K., Corvellec, M., & Despouy, P. (2020). plotly: Create Interactive Web Graphics via ’plotly.js’. https://CRAN.R-project.org/package=plotly

Vanderkam, D., Allaire, J., Owen, J., Gromer, D., & Thieurmel, B. (2018). dygraphs: Interface to ’Dygraphs’ Interactive Time Series Charting Library. https://CRAN.R-project.org/package=dygraphs

Wickham, H. (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org

Wickham, H., Chang, W., Henry, L., Pedersen, T. L., Takahashi, K., Wilke, C., Woo, K., Yutani, H., & Dunnington, D. (2020). ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics. https://CRAN.R-project.org/package=ggplot2

Wilke, C. O. (2019). cowplot: Streamlined Plot Theme and Plot Annotations for ’ggplot2’. https://CRAN.R-project.org/package=cowplot