Gráficos con ggplot2 (A): Primeras ideas

Programación y manejo de datos con R (Slides 06-A)

Pedro J. Pérez

Sintaxis de ggplot2 [ 🌟 ]

ggplot(iris, aes(x = Sepal.Length,
                 y = Petal.Length,
                 color = Species)) +
    geom_point()

Forma más compacta de escribirlo

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
    geom_point()

Gráfico en slow-motion!

iris |>
iris |>
ggplot() +
iris |>
ggplot() +
   aes(x = Sepal.Length) +
iris |>
ggplot() +
   aes(x = Sepal.Length) +
   aes(y = Petal.Length) +
iris |>
ggplot() +
   aes(x = Sepal.Length) +
   aes(y = Petal.Length) +
   aes(color = Species)  +
iris |>
ggplot() +
   aes(x = Sepal.Length) +
   aes(y = Petal.Length) +
   aes(color = Species)  +
  geom_point()
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa

La forma habitual(!) de escribirlo es:

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
    geom_point()

IMAGINA qué harán las siguientes instrucciones. Después las ejecutas.

#- Fíjate: sólo hay 2 variables en aes() ---------------------------------------
ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point()

#- Fíjate: ahora usamos geom_line() --------------------------------------------
ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_line()

#- Fíjate: ahora usamos 2 geom_xx() --------------------------------------------
ggplot(iris, aes(Sepal.Length, Petal.Length)) + geom_point() +
      geom_smooth()

#- Fíjate: volvemos a tener 3 variables asociadas a estéticas ------------------
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point()

#- Fíjate: hay argumentos dentro de geom_point(). Uno de ellos es "color" ------
ggplot(iris, aes(Sepal.Length, Petal.Length)) +
      geom_point(color = "red", size = 2, alpha = 0.2)
ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point()

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_line()

ggplot(iris, aes(Sepal.Length, Petal.Length)) + geom_point() +
      geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point()

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
      geom_point(color = "red", size = 2, alpha = 0.2)

Mapear vs fijar: ¿dentro o fuera de aes()? [ 🌟 ]

Mapear (dentro de aes()): el color depende de una variable → ggplot2 crea una leyenda

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point(aes(color = Species))

Fijar (fuera de aes()): el color es un valor fijo para todos los puntos → no hay leyenda

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point(color = "steelblue")

Un error muy típico con aes(): ¿por qué los puntos salen rojos y no azules?

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point(aes(color = "blue"))

Dentro de aes(), "blue" no es un color: es una “variable” que vale siempre "blue". ggplot2 le asigna el primer color de su paleta (rojo) y crea una leyenda llamada “blue”.

Vamos a profundizar un poco más en ggplot2

Es importante que veas que estas 3 expresiones hacen el mismo gráfico:

ggplot(iris, aes(Sepal.Length, Petal.Length)) + geom_point()

ggplot(iris) + geom_point(aes(Sepal.Length, Petal.Length))

ggplot() + geom_point(data = iris, aes(Sepal.Length, Petal.Length))

✔ Si utilizas la tercera expresión; es decir, si especificas los datos dentro de geom_xx(), es necesario poner el nombre del argumento: (data = iris , …) [ 🌟 ]

Repito esto porque es IMPORTANTE …. [ 🌟 ]

  • Podemos especificar los mappings de variables en estéticas dentro de cada geom_xx()
ggplot(iris) + geom_point(aes(Sepal.Length, Petal.Length))


  • Podemos especificar los datos dentro de cada geom_xx() . En este caso no te olvides de poner (data = …)
ggplot() + geom_point(data = iris, aes(Sepal.Length, Petal.Length))



  • Bueno, sí, ¿y qué más da? Pues importa, y muuuucho.

  • Esto nos va a dar mucha flexibilidad/control en nuestros gráficos. Lo vemos.

¿Qué hacen estas 3 expresiones?

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
     geom_point() + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
    geom_point(aes(color = Species)) + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
    geom_point() + geom_smooth(aes(color = Species))

Ejemplos: ¿por qué no funcionan 4 de estas 5 expresiones?

ggplot(iris) + geom_point(aes(Sepal.Length, Petal.Length)) +
    geom_smooth(aes(color = Species))
#> Error in `geom_smooth()`:
#> ! Problem while computing stat.
#> ℹ Error occurred in the 2nd layer.
#> Caused by error in `compute_layer()`:
#> ! `stat_smooth()` requires the following missing aesthetics: x and y.

ggplot() + geom_point(data = iris, aes(Sepal.Length, Petal.Length)) +
    geom_line(aes(Sepal.Length, Petal.Length))
#> Error in `geom_line()`:
#> ! Problem while computing aesthetics.
#> ℹ Error occurred in the 2nd layer.
#> Caused by error:
#> ! objeto 'Sepal.Length' no encontrado

ggplot(aes(Sepal.Length, Petal.Length)) + geom_point(data = iris) +
    geom_line()
#> Error in `fortify()`:
#> ! `data` must be a <data.frame>, or an object coercible by `fortify()`,
#>   or a valid <data.frame>-like object coercible by `as.data.frame()`, not a
#>   <ggplot2::mapping> object.
#> ℹ Did you accidentally pass `aes()` to the `data` argument?

ggplot() + geom_point(data = iris, aes(Sepal.Length, Petal.Length)) +
    geom_line()

ggplot(iris, aes(Sepal.Length, Petal.Length)) |>   #- ¡ojo! las capas se unen con +
    geom_point()
#> Error in `geom_point()`:
#> ! `mapping` must be created by `aes()`.
#> ✖ You've supplied a <ggplot2::ggplot> object.
#> ℹ Did you use `%>%` or `|>` instead of `+`?

Un ejemplo un poco marciano

iris_2 <- iris |> filter(Species != "setosa") #- lirios que no son "setosa"

ggplot() +
geom_point(data = iris, aes(Sepal.Length, Petal.Length, color = Species)) +
   geom_smooth(data = iris_2, aes(Sepal.Length, Petal.Length) )

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point(aes(color = Species)) + geom_smooth(data = iris_2)

Otro ejemplo/tarea más:

Tarea: Quiero que las 2 especies de lirios grandes (versicolor y virginica) se representen con el mismo color, ¿cómo lo hago?

Hay varias soluciones, una de las más marcianas es la Solución 1.

iris_2 <- iris |> filter(Species != "setosa")            #- lirios grandes
iris_solo_setosa <- iris |> filter(Species == "setosa")  #- lirios pequeños ("setosa")

ggplot(iris, aes(Sepal.Length, Petal.Length)) + geom_point() +
    geom_point(data = iris_solo_setosa, aes(color = Species)) +
    geom_smooth(data = iris_2, aes(Sepal.Length, Petal.Length) )

iris_solo_setosa <- iris |> filter(Species == "setosa")
iris_solo_2_clases <- iris |>
  mutate(Species_2 = ifelse(Species %in% c("versicolor", "virginica"),
                            "lirios_grandes", "setosa"))

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point() +
  geom_point(data = iris_solo_setosa, aes(color = Species)) +
  geom_smooth(data = iris_solo_2_clases,
              aes(Sepal.Length, Petal.Length, color = Species_2) )

iris_solo_2_clases <- iris |>
  mutate(Species_2 = ifelse(Species %in% c("versicolor", "virginica"),
                            "lirios_grandes", "setosa"))

ggplot(iris_solo_2_clases,
       aes(Sepal.Length, Petal.Length, color = Species_2)) +
  geom_point() + geom_smooth()

Un ejemplo más

  • Para ir acabando con la “filosofía”/sintaxis/gramática de ggplot2 intenta imaginar qué gráficos hacen las 6 expresiones de más abajo. Fíjate sobre todo en la tercera expresión.
ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point() + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point() + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
   geom_point(color = "purple") + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point() + geom_smooth(color = "brown")

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point() + geom_smooth(aes(color = Species))

ggplot(iris) +
  geom_point(aes(Sepal.Length, Petal.Length, color = Species) ) +
  geom_smooth(aes(Sepal.Length, Petal.Length, color = Species))
ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point() + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point() + geom_smooth()

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
   geom_point(color = "purple") + geom_smooth()

El color = "purple" de geom_point() está fuera de aes(): fija el color de los puntos y “pisa” el mapping global color = Species, pero sólo para los puntos; las curvas siguen coloreadas por especie.

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point() + geom_smooth(color = "brown")

ggplot(iris, aes(Sepal.Length, Petal.Length)) +
  geom_point() + geom_smooth(aes(color = Species))

ggplot(iris) +
  geom_point(aes(Sepal.Length, Petal.Length, color = Species) ) +
  geom_smooth(aes(Sepal.Length, Petal.Length, color = Species))

Un gráfico es un objeto de R: podemos guardarlo y añadirle capas

  • Un gráfico de ggplot2 es un objeto más de R: podemos guardarlo con un nombre (<-) y luego añadirle capas con +
p <- ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point()
  • p no se dibuja al crearlo; se dibuja cuando lo “imprimimos” (al escribir p o print(p))
p

p + geom_smooth()

  • Lo usaremos mucho en las siguientes slides: haremos un gráfico p y le iremos añadiendo cosas (títulos, temas, …)

¿Veremos alguna vez otros gráficos?

the aesthetic parameters de cada geom_xx()

  • Cuando empecemos a hacer otros tipos de gráficos será de utilidad conocer qué parámetros admite cada geom_xx().

  • Puedes verlos en la ayuda de cada geom (por ejemplo ?geom_point, sección Aesthetics), en la web de ggplot2 o en la viñeta vignette("ggplot2-specs")

Para practicar: los pingüinos de Palmer

Desde R 4.5, el paquete datasets incluye penguins: datos de 344 pingüinos de 3 especies del archipiélago Palmer (Antártida)

Tarea: haz un gráfico de puntos con la longitud de la aleta (flipper_len) en el eje X, el peso (body_mass) en el eje Y y el color según la especie (species). Añade una recta de regresión para cada especie con geom_smooth(method = "lm").

head(penguins, n = 3)
#>   species    island bill_len bill_dep flipper_len body_mass    sex year
#> 1  Adelie Torgersen     39.1     18.7         181      3750   male 2007
#> 2  Adelie Torgersen     39.5     17.4         186      3800 female 2007
#> 3  Adelie Torgersen     40.3     18.0         195      3250 female 2007
ggplot(penguins, aes(flipper_len, body_mass, color = species)) +
  geom_point() +
  geom_smooth(method = "lm")

Para saber más

En las siguientes slides veremos más elementos de un ggplot: títulos, themes, facetting, anotaciones, escalas, …