Warning: package 'tidyverse' was built under R version 4.2.2
── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
✔ ggplot2 3.4.0      ✔ purrr   0.3.5 
✔ tibble  3.1.8      ✔ dplyr   1.0.10
✔ tidyr   1.2.1      ✔ stringr 1.5.0 
✔ readr   2.1.3      ✔ forcats 0.5.2 
Warning: package 'ggplot2' was built under R version 4.2.2
Warning: package 'tibble' was built under R version 4.2.2
Warning: package 'tidyr' was built under R version 4.2.2
Warning: package 'readr' was built under R version 4.2.2
Warning: package 'purrr' was built under R version 4.2.2
Warning: package 'dplyr' was built under R version 4.2.2
Warning: package 'stringr' was built under R version 4.2.2
Warning: package 'forcats' was built under R version 4.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
Warning: package 'patchwork' was built under R version 4.2.2

Graficando con R

Existen muchos paquetes que nos permiten visualizar nuestros datos. En R base tenemos la funcion plot() y sus variantes, pero también podemos encontrar a Plotly (Sievert, 2020), RGL, Lattice (Sarkar, 2008), ggstatsplot (Patil, 2021) y varios más. El paquete que vamos a utilizar nosotros será ggplot2 (Wickham, 2016) que forma parte del tidyverse (Wickham et al., 2019).

Lo bueno de este paquete es que tiene la misma filosofía del tidyverse por lo que, al visualizar datos, también podremos utilizar funciones de paquetes como dplyr, forcats o cualquier otro dentro del universo tidy. ggplot trabaja por capas. En principio se crea una base del gráfico (1ra capa) y luego se van agregando las demás (datos, estéticas, aspectos y otras más). Eso es a grandes rasgos lo que se hace con este paquete.

Instalación y carga

  • Instalación install.packages("ggplot2") (o si ya instalaron el tidyverse entonces viene incluido)

  • Carga library("ggplot2") (o si ya cargaron el tidyverse entonces viene incluido. Ver abajo)

  • Tidyverse

Ver/Ocultar código
library(tidyverse) # Esto carga una serie de paquetes, entre ellos ggplot

 ── Attaching packages ────────────────────────────────────────── tidyverse 1.3.1 ──
 ✔ ggplot2 3.3.6     ✔ purrr   0.3.4
 ✔ tibble  3.1.7     ✔ dplyr   1.0.9
 ✔ tidyr   1.2.0     ✔ stringr 1.4.0
 ✔ readr   2.1.2     ✔ forcats 0.5.1
 ── Conflicts ───────────────────────────────────────────── tidyverse_conflicts() ──
 ✖ dplyr::filter() masks stats::filter()
 ✖ dplyr::lag()    masks stats::lag()

Arrancando con ggplot

Como se menciona más arriba, el paquete ggplot ofrece una gramática para graficar que funciona a través de capas (si alguna vez usaste programas de diseño como por ej. Photoshop entones la lógica es más o menos la misma)

  • Capa 1 Si tan solo usamos la función ggplot(), lo que obtenemos es lo siguiente:
Ver/Ocultar código
ggplot()

Esta seria la capa principal. Como si fuera la base del gráfico. Sobre esta base es que luego se agregan los demás aspectos del gráfico.

  • Capa 2.1

Esta segunda capa comprende los datos que se visualizaran. Entones dentro de la función ggplot() el primer argumento es data y allí es donde ingresamos nuestro objeto con los datos. Como pueden ver abajo, si solo se ingresan los datos el resulado no cambia. Para eso hay que agregar aspectos.

Ver/Ocultar código
datosEj <- tibble(ejex = 1:9, # Este el objeto con los datos. En este caso no tiene mucho sentido
                  ejey = 1:9) # mas alla del ejemplo, pero es necesario para poner algo en el argumento data


ggplot(data = datosEj)

  • Capa 2.2

Para agregar los aspectos o aes() lo que hay que hacer es incluir un nuevo argumento luego de data. Como se ve en el código de abajo, luego de data se agrega mapping y dentro de este argumento se especifican las aes(). El resultado que se obtiene en esta instancia es que ahora a la base del grafico se le suman los ejes y el rango de valores. Esto puede variar en funcion del tipo de variable que incluyamos en cada eje.

Ver/Ocultar código
datosEj <- tibble(Eje_X = 1:9,
                  Eje_Y = 1:9)

# Aqui es donde se incluyen las variables para # los ejes X e Y

ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) 

El resultado que se obtiene en esta instancia es que ahora a la base del gráfico se le suman los ejes y el rango de valores. Esto puede variar en función del tipo de variable que incluyamos en cada eje. Arriba graficamos dos variables numéricas, mientras que en el resultado de abajo se grafica una variable numérica y otra categórica con tres niveles (A; B; C)

Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9)


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) # En el eje X incluimos la variable categórica

  • Capa 3

Ya tenemos una base, los datos, los ejes definidos. Qué más falta? Los aspectos geométricos!! Barras? Columnas? Puntos? Tortas?. Bueno, estos últimos tal vez casi nunca (por si quieren leer sobre esto: Link 1; Link 2; Link 3; Link 4).

Vamos con el primer ejemplo con dos variables numéricas. Para este caso uno de los geom_ utilizados puede ser geom_point(). Esto nos genera un gráfico de dispersión o scatterplot. La manera de agregar esta capa es utilizando el +.

Ver/Ocultar código
datosEj <- tibble(Eje_X = 1:9,
                  Eje_Y = 1:9)



ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) + # Con el + sumamos la siguiente capa
  geom_point() 

Pueden utilizarse varios geom dentro del mismo gráfico. Se agrega una capa más y listo.

Ver/Ocultar código
datosEj <- tibble(Eje_X = 1:9,
                  Eje_Y = 1:9,
                  Eje_Xinvertido = 1:9,
                  Eje_Yinvertido = 9:1)



ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) + # Con el + sumamos la siguiente capa
  geom_point() + # En este caso son puntos
  geom_point(mapping = aes(x = Eje_Xinvertido, y = Eje_Yinvertido))  # Incluso puede sumarse otra capa mas

En el caso de la base con variables numéricas y categóricas. En este caso, podria sernos de utilidad geom_col

Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9)


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) +
  geom_col()

Si necesitamos dar un poco más de información, entonces podríamos usar geom_boxplot o geom_violin. Con el primero hacemos un gráfico de cajas y con el según un gráfico con violines

  • Cajas
Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9)


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) +
  geom_boxplot()

  • Violines
Ver/Ocultar código
datosEj <- palmerpenguins::penguins # En este ejemplo use pinguinos porque quedaba mejor que los datos inventados


ggplot(data = datosEj, mapping = aes(x = species, y = body_mass_g)) +
  geom_violin()
Warning: Removed 2 rows containing non-finite values (`stat_ydensity()`).

Más y más capas

Otras capas muy utilizadas son las del titulo, subtitulo y nombres de los ejes. Esto se puede modificar agregando otra capa que incluya labs

Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9)


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) +
  geom_col() +
  labs(title = "Grafico con tres columnas",
       x = "Variable categorica",
       y = "Variable numerica")

Tambien pueden rotarse los ejes. A veces es útil para visualizar mejor los datos. La función que nos permite eso es coord_flip Por ejemplo, rotemos el gráfico de arriba

Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9)


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y)) +
  geom_col() +
  labs(title = "Grafico con tres columnas",
       x = "Variable categorica",
       y = "Variable numerica") +
  coord_flip()

¿Y donde esta el color?

Los colores pueden incluirse de muchas maneras. Una de ellas es incluir colour o color (como gusten) en las aes del principio. Otra opcion es rellenar el geom con fill. Por ejemplo:

Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9)


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y, fill = "orange")) +
  geom_col() +
  labs(title = "Grafico con tres columnas",
       x = "Variable categorica",
       y = "Variable numerica") +
  coord_flip()

No solo pueden incluirse colores, sino que tambien pueden usarse otras variables categoricas. Por ejemplo

Ver/Ocultar código
datosEj <- tibble(Eje_X = rep(c("A","B", "C"), 3), # Creamos la variable categórica. Repetimos A B y C tres veces
                  Eje_Y = 1:9,
                  mascolor = rep(c("D", "E", "F"), 3))


ggplot(data = datosEj, mapping = aes(x = Eje_X, y = Eje_Y, fill = mascolor)) +
  geom_col() +
  labs(title = "Grafico con tres columnas",
       x = "Variable categorica",
       y = "Variable numerica") +
  coord_flip()

Con datos que no son inventados esto cobra mucho más sentido. Veamos con pinguinos.

Ver/Ocultar código
datosEj <- palmerpenguins::penguins |> na.omit()


ggplot(data = datosEj, mapping = aes(x = body_mass_g, y = bill_length_mm, colour = species)) +
  geom_point() +
  labs(title = "Tamaño del pico en función del peso",
       x = "Peso en gramos",
       y = "Tamaño del pico") 

Ultima capa

Lo último que suele agregarse a un gráfico es el tema (traducción directa de theme). Esto lo que hace es cambiar el aspecto general del gráfico. Existen themes predeterminados como por ejemplo: theme_bw, theme_light, theme_linedraw, theme_minimal y asi. Pueden ir probando todos y luego decidir cual queda mejor en su trabajo. Y tambien pueden customizar su propia theme, pero eso es una tarea un poco más compleja (pueden leer de eso aca).

¿Como se agrega el theme? Como todas las capas, con el + y la función theme_NOMBRE. Veamos algunos de los mencionados arriba.

Ver/Ocultar código
datosEj <- palmerpenguins::penguins |> na.omit()


p1 <- ggplot(data = datosEj, mapping = aes(x = body_mass_g, y = bill_length_mm, colour = species)) +
  geom_point() +
  labs(title = "theme_bw",
       x = "Peso en gramos",
       y = "Tamaño del pico") +
  theme_bw() +
  theme(legend.position = "none")

p2 <- ggplot(data = datosEj, mapping = aes(x = body_mass_g, y = bill_length_mm, colour = species)) +
  geom_point() +
  labs(title = "theme_light",
       x = "Peso en gramos",
       y = "Tamaño del pico") +
  theme_light() +
  theme(legend.position = "none")

p3 <- ggplot(data = datosEj, mapping = aes(x = body_mass_g, y = bill_length_mm, colour = species)) +
  geom_point() +
  labs(title = "theme_minimal",
       x = "Peso en gramos",
       y = "Tamaño del pico") +
  theme_minimal() +
  theme(legend.position = "none")

p4 <- ggplot(data = datosEj, mapping = aes(x = body_mass_g, y = bill_length_mm, colour = species)) +
  geom_point() +
  labs(title = "theme_linedraw",
       x = "Peso en gramos",
       y = "Tamaño del pico") +
  theme_linedraw() +
  theme(legend.position = "bottom")


p1 + p2 + p3 + p4

References

Patil, I. (2021). Visualizations with statistical details: The ’ggstatsplot’ approach. Journal of Open Source Software, 6(61), 3167. https://doi.org/10.21105/joss.03167
Sarkar, D. (2008). Lattice: Multivariate data visualization with r. Springer. http://lmdvr.r-forge.r-project.org
Sievert, C. (2020). Interactive web-based data visualization with r, plotly, and shiny. Chapman; Hall/CRC. https://plotly-r.com
Wickham, H. (2016). ggplot2: Elegant graphics for data analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org
Wickham, H., Averick, M., Bryan, J., Chang, W., McGowan, L. D., François, R., Grolemund, G., Hayes, A., Henry, L., Hester, J., Kuhn, M., Pedersen, T. L., Miller, E., Bache, S. M., Müller, K., Ooms, J., Robinson, D., Seidel, D. P., Spinu, V., … Yutani, H. (2019). Welcome to the tidyverse. Journal of Open Source Software, 4(43), 1686. https://doi.org/10.21105/joss.01686