7  Scales

Las escalas son una parte fundamental de la visualización de datos. Son las encargadas de mapear los valores de los datos a los elementos visuales de la gráfica. Podemos dividirlas en las siguientes clases:

Además, se puede subdividir las escalas en función de la estética que modifican:

En este capítulo vamos a trabajar con tres datasets:

Para comenzar, vamos a cargar los paquetes necesarios y a leer los datos que utilizaremos en este capítulo.

## Cargar paquetes
library(gapminder)
library(geomtextpath)
library(tidyverse)
## Cargar datos
inventario_tbl <- read_rds("../data/inventario_prep.rds")

7.1 Estructura de las escalas

Las escalas en ggplot2 son funciones que tienen una estructura de generalmente tres palabras separadas por un guión bajo. Estas palabras son:

  • scale: es la primera palabra de la función siempre.

  • Nombre de la estética: es la segunda palabra de la función y se refiere a la estética que se quiere modificar (x, y, color, fill, alpha, linetype, linewidth, shape o size).

  • Tipo de escala: es la tercera palabra de la función y se refiere al tipo de escala que se quiere aplicar (continuous, discrete, manual, identity, log, …).

En las siguientes sección veremos algunas de las más importantes.

7.2 Escalas de posición

Las escalas de posición se utilizan para mapear los valores de los datos a las posiciones de los elementos visuales de la gráfica. Todos los gráficos tienen dos escalas de posición que son la estética x y la estética y. Todos los gráficos traen una escala por defecto que depende de si la variable es categórica o numérica:

Nota

Existe alguna excepción como el formato fecha que utiliza scale_*_date() o el formato fecha-tiempo que utiliza scale_*_datetime().

Vamos a empezar con un ejemplo sencillo utilizando el dataset iris.

En este primer ejemplo, generamos un gráfico de la distribución de la anchura del sépalo según la especie. Tenemos que añadir una semilla para que el proceso aleatorio de geom_jitter() sea el mismo en ambos ejemplos.

set.seed(123)
ggplot(iris, aes(x = Species, y = Sepal.Width)) +
    geom_jitter(height = 0, width = .2)
Fig. 7.1: Distribución de la anchura del pétalo por especie de Iris

Si añadimos las escalas que supuestamente son las que vienen por defecto, no debería cambiar nada en nuestro gráfico:

set.seed(123)
ggplot(iris, aes(x = Species, y = Sepal.Width)) +
    geom_jitter(height = 0, width = .2) +
    scale_x_discrete() +
    scale_y_continuous()
Fig. 7.2: Distribución de la anchura del pétalo por especie de Iris

Pues bien, hasta aquí nada nuevo. Vamos a empezar a ver finalmente qué podemos hacer con las escalas de posición.

7.2.1 Escalas de posición continuas

Para trabajar sobre escalas de posición continuas vamos a partir de este ejemplo que ya hemos trabajado en secciones anteriores del dataset de gapminder. Vamos a empezar preparando los datos:

gapminder_tbl <- gapminder |> 
    filter(continent != "Africa") |>
    mutate(year = as_date(
        paste0(year, "-01-01")
    ))

Como veis, estamos convirtiendo la columna year a tipo de dato Date en lugar de numeric. En un rato veréis por qué.

base_plot <- gapminder_tbl |> 
    ggplot(
        aes(x = year, y = gdpPercap, color = country, group = country)
    ) +
    geom_line(color = "grey80") +
    geom_textpath(
        aes(x = year, y = gdpPercap, label = country),
        data  = gapminder_tbl |> filter(country %in% c("Kuwait", "Nicaragua", "Haiti")),
        color = "#BC3908",
        lwd   = 1,
        size  = 3
    ) +
    labs(
        x     = NULL,
        y     = "PIB per cápita",
        color = NULL,
        title = "La mayoría de países aumentaron su PIB per cápita entre 1952 y 2007. \nKuwait, Nicaragua y Haiti no"
    ) +
    theme_minimal()

base_plot
Fig. 7.3: Spaguetti plot mostrando la evolución del PIB per cápita de los países del mundo

Vamos a ver qué podemos modificar:

Podemos indicar un vector de valores para especificar los valores que queremos ver en los ejes. Además, con name también podemos modificar el nombre de este eje (al igual que en la función labs()).

base_plot +
    scale_y_continuous(
        name   = "PIB per cápita ($)",
        breaks = seq(0, 100000, 20000)
    )

Fíjate que al superar los 5 dígitos la notación es decimal. Podemos cambiar este comportamiento del siguiente modo:

options(scipen = 999)
base_plot +
    scale_y_continuous(
        name   = "PIB per cápita ($)",
        breaks = seq(0, 100000, 20000)
    )

En lugar de indicar los intervalos que queremos, podemos indicar un número de intervalos para que la función los calcule óptimamente. Vamos a indicar un total de 10 intervalos:

base_plot +
    scale_y_continuous(
        name     = "PIB per cápita ($)",
        n.breaks = 10
    )

Si te fijas, en la grilla del gráfico tenemos unas líneas más gruesas en las etiquetas y otras más finas entre las etiquetas. Estás líneas más finas son los intervalos menores. Para ver lo que significa esto, vamos a crear un minor break cada $2000.

base_plot +
    scale_y_continuous(
        name         = "PIB per cápita ($)",
        n.breaks     = 10,
        minor_breaks = seq(0, 110000, 2000)
    )

Las etiquetas son los valores que muestran los intervalos que creamos con breaks o n_breaks. Podemos poner lo que queramos. Por ver un ejemplo obvio de lo que se puede hacer:

base_plot +
    scale_y_continuous(
        name   = "PIB per cápita ($)",
        breaks = seq(0, 100000, 20000),
        labels = c("Cero", "Primera", "Segunda", "Tercera", "Cuarta", "Quinta")
    )

Ahora vamos a ver un ejemplo mucho más útil utilizando el paquete scales. Este paquete nos permite añadir símbolos, separar unidades, etc. En lugar de tener valores como 100000, vamos a modificarlos para que muestren $100,000. Para ello utilizamos la función label_dollar() que por defecto modifica el comportamiento al que nosotros queremos.

base_plot +
    scale_y_continuous(
        breaks = seq(0, 100000, 20000),
        labels = scales::label_dollar()
    )

Como en España es común separar decimales por comas y los miles por puntos, podemos modificar este comportamiento así:

base_plot +
    scale_y_continuous(
        breaks = seq(0, 100000, 20000),
        labels = scales::label_dollar(
            big.mark     = ".",
            decimal.mark = ","
        )
    )

Puede parecer una sintaxis extraña. Este tipo de funciones se llaman function factories y es un tema avanzado y que queda fuera de los objetivos de este curso. En este enlace se puede ver una lectura adicional sobre este tipo de funciones.

Finalmente, vamos a ver que podemos hacer zoom a un área del gráfico. Vamos a ver el área de $0 hasta $20,000.

base_plot +
    scale_y_continuous(
        name   = "PIB per cápita ($)",
        limits = c(0, 20000)
    )

Este sería el funcionamiento básico de las funciones scale_*_continuous(). No obstante, podemos modificar la función utilizando una aceptable por variables continuas:

Las escalas normales van a mapear los valores originales de nuestros datos. Sin embargo, podemos aplicar transformaciones directas a las escalas como por ejemplo la transformación logarítmica:

base_plot +
    scale_y_log10()

Del mismo modo, podemos aplicar los mismos argumentos:

base_plot +
    scale_y_log10(
        name   = "PIB (escala logarítmica)",
        breaks = seq(0, 100000, 20000),
        labels = scales::label_dollar(
            big.mark     = ".",
            decimal.mark = ","
        )
    )

Como utilizamos logaritmos nos aparecen los decimales que son siempre dos ceros. Podemos eliminarlos:

base_plot +
    scale_y_log10(
        name   = "PIB (escala logarítmica)",
        breaks = seq(0, 100000, 20000),
        labels = scales::label_dollar(
            big.mark     = ".",
            decimal.mark = ",",
            accuracy     = 1
        )
    )

Para variables de tipo fecha tenemos una serie de funciones que nos ayudan a mostrar las etiquetas. Sin embargo, tenemos que convertir el tipo de dato a fecha, algo que hemos hecho previamente cuando creamos gapminder_tbl.

base_plot +
    scale_x_date()

En verdad, cuando la variable es de tipo fecha se aplica esta escala por defecto. Vamos a modificar sus etiquetas para ver los años de cinco en cinco. Podemos utilizar el argumento date_breaks que permite una sintaxis muy flexible y amigable:

base_plot +
    scale_x_date(
        date_breaks = "5 years"
    )

Vaya infortunio. Esta función nos añade los meses y los años… Pero no os preocupéis!! Paquete scales al rescate:

base_plot +
    scale_x_date(
        date_breaks = "5 years",
        labels      = scales::label_date(format = "%Y")
    )

El argumento format nos permite escribir el formato de fecha siguiendo unos estándares. Busca la ayuda de la función strptime() para ver las opciones disponibles. Las más comunes puedes verlas aquí. Existe una opción que no necesita del paquete scales:

base_plot +
    scale_x_date(
        date_breaks = "5 years",
        date_labels = "%Y"
    )

Pues esto sería todo por esta parte de la sección. Como ves, es muy sencillo trabajar con las escalas gracias a la gramática de gráficos adaptada a ggplot2.

7.2.2 Escalas de posición discretas

Vamos a ver ahora las escalas que mapean una variable de tipo categórico. La verdad es que aquí no vamos a introducir nada nuevo. La única diferencia con las anteriores es que utilizamos una función distinta y los argumentos que tenemos disponibles. En este caso no tiene sentido crear intervalos en la escala, ya que una variable categórica tiene los valores fijos. Lo que podemos es modificar las etiquetas y también la posición de la escala (esto lo podemos hacer también con las funciones anteriores, pero quería añadir algo nuevo en esta sección).

set.seed(123)
ggplot(iris, aes(x = Species, y = Sepal.Width)) +
    geom_jitter(height = 0, width = .2) +
    scale_x_discrete(
        name     = NULL,
        labels   = c("I. setosa", "I. versicolor", "I. virginica"),
        position = "top"
    )

Finalmente, puedes ver que todas las funciones tienen un argumento denominado guide. Esto lo veremos más adelante.

7.3 Escalas de colores

Las escalas de colores modifican el color de las líneas (color) y el color de relleno (fill). Las escalas de posición actúan sobre los ejes x e y, mientras que las que veremos en esta sección actúan sobre los colores de las geometrías generando una leyenda. Por defecto, se aplican las siguientes:

7.3.1 Variables continuas

Vamos a empezar viendo como actúan las escalas por defecto en variables continuas:

scatter_base <- gapminder |> 
    filter(year == 2007) |> 
    ggplot(
        aes(x = gdpPercap, y = lifeExp, color = pop)
    ) +
    geom_point() +
    labs(
        x = "PIB per cápita",
        y = "Esperanza de vida"
    ) +
    theme_minimal()

scatter_base
Fig. 7.4: Scatter plot del PIB per cápita, esperanza de vida y población de los países del mundo

La función scale_color_continuous() nos permite modificar la escala de colores con unos argumentos similares a los que vimos en las escalas de posición. Vamos a ver un ejemplo:

Los intervalos los definimos de nuevo con breaks o n.breaks.

scatter_base +
    scale_color_continuous(
        name   = "Población",
        breaks = seq(0, 1e9, 2e8)
    )

scatter_base +
    scale_color_continuous(
        name     = "Población",
        n.breaks = 3
    )

Las etiquetas las definimos con labels. Vamos a ver un ejemplo con el paquete scales:

scatter_base +
    scale_color_continuous(
        name   = "Población",
        labels = scales::label_number(
            big.mark     = ".",
            decimal.mark = ","
        )
    )

Podemos modificar el tipo de paleta de colores con el argumento type. Este es un argumento que las escalas de posición no tienen.

scatter_base +
    scale_color_continuous(
        name = "Población",
        type = "viridis"
    )

En la última pestaña hemos visto como utilizar una paleta de colores mediante el argumento type. Sin embargo, algunas paletas comunes traen sus propias funciones del tipo scale_color_*() con una mayor flexibilidad.

7.3.1.1 Paletas predefinidas

Las escalas viridis (Garnier 2018) son una familia de paletas de colores que seguramente has visto en muchos gráficos. Estas son unas paletas con un gran diseño y que además son amigables con problemas de visión como el daltonismo. En la siguiente aplicación puedes ver las escalas viridis modificando el argumento option de la función scale_color_viridis_c().

#| standalone: true
#| viewerHeight: 600

## Load packages
library(bslib)
library(dplyr)
library(gapminder)
library(ggplot2)
library(glue)
library(shiny)
library(shinyWidgets)

## UI
ui <- page_sidebar(
    sidebar = sidebar(
        open = "open",
        width = 200,
        selectInput(
            inputId = "option", 
            label   = "Paleta", 
            choices = c("A", "B", "C", "D", "E", "F", "G", "H"),
            selected = "D"
        ),
        prettySwitch(
            inputId  = "direction",
            label    = "Invertir paleta",
            status   = "success",
            fill     = TRUE
        ),
        prettySwitch(
            inputId = "binned",
            label   = "Binned",
            status  = "success",
            fill    = TRUE
        )
    ),
    verbatimTextOutput("code") |> card(),
    plotOutput("plot", width = 500) |> card()
)

## Server
server <- function(input, output, session) {
    
    output$code <- renderPrint({
        glue(
            
            if (input$binned) {
                'scatter_base +
                    scale_color_viridis_b(
                        option    = "{input$option}",
                        direction = {if (input$direction) -1 else 1}
                    )'
            } else {
                'scatter_base +
                    scale_color_viridis_c(
                        option    = "{input$option}",
                        direction = {if (input$direction) -1 else 1}
                    )'
            }
            
            )
    })

    ## Plot
    output$plot <- renderPlot({
        
        if (input$binned) {
            gapminder |> 
            filter(year == 2007) |> 
            ggplot(
                aes(x = gdpPercap, y = lifeExp, color = pop)
            ) +
            geom_point() +
            labs(
                x = "PIB per cápita",
                y = "Esperanza de vida"
            ) +
            theme_minimal(base_size = 8) +
            scale_color_viridis_b(
                option    = input$option,
                direction = if (input$direction) -1 else 1
            )
        } else {
            gapminder |> 
            filter(year == 2007) |> 
            ggplot(
                aes(x = gdpPercap, y = lifeExp, color = pop)
            ) +
            geom_point() +
            labs(
                x = "PIB per cápita",
                y = "Esperanza de vida"
            ) +
            theme_minimal(base_size = 8) +
            scale_color_viridis_c(
                option    = input$option,
                direction = if (input$direction) -1 else 1
            )
        }
        
        }, res = 96
    )
}

## Run app
shinyApp(ui = ui, server = server)

Estas funciones pueden terminar en:

Por otro lado, tenemos la familia de paletas de colores ColorBrewer (Neuwirth 2022), que podemos ver en la siguiente figura:

Fig. 7.5: Paletas de colores Brewer

Para acceder a ellas, podemos utilizar las funciones:

A medida que utilices ggplot2 irás descubriendo paquetes que traen sus propias escalas de colores. Algunos ejemplos son ggsci (Xiao 2024), {MetBrewer} (Mills 2022), o scico (Pedersen y Crameri 2023).

En la siguiente aplicación puedes probar distintas paletas ColorBrewer:

#| standalone: true
#| viewerHeight: 600

## Load packages
library(bslib)
library(dplyr)
library(gapminder)
library(ggplot2)
library(glue)
library(RColorBrewer)
library(shiny)
library(shinyWidgets)

## UI
ui <- page_sidebar(
    sidebar = sidebar(
        open = "open",
        width = 200,
        selectInput(
            inputId  = "option", 
            label    = "Paleta", 
            choices  = rownames(brewer.pal.info),
            selected = "Reds"
        ),
        prettySwitch(
            inputId  = "direction",
            label    = "Invertir paleta",
            status   = "success",
            fill     = TRUE
        ),
        prettySwitch(
            inputId = "binned",
            label   = "Binned",
            status  = "success",
            fill    = TRUE
        )
    ),
    verbatimTextOutput("code") |> card(),
    plotOutput("plot", width = 500) |> card()
)

## Server
server <- function(input, output, session) {
    
    output$code <- renderPrint({
        glue(
            
            if (input$binned) {
                'scatter_base +
                    scale_color_fermenter(
                        palette   = "{input$option}",
                        direction = {if (input$direction) -1 else 1}
                    )'
            } else {
                'scatter_base +
                    scale_color_distiller(
                        palette   = "{input$option}",
                        direction = {if (input$direction) -1 else 1}
                    )'
            }
            
            )
    })

    ## Plot
    output$plot <- renderPlot({
        
        if (input$binned) {
            gapminder |> 
            filter(year == 2007) |> 
            ggplot(
                aes(x = gdpPercap, y = lifeExp, color = pop)
            ) +
            geom_point() +
            labs(
                x = "PIB per cápita",
                y = "Esperanza de vida"
            ) +
            theme_minimal(base_size = 8) +
            scale_color_fermenter(
                palette   = input$option,
                direction = if (input$direction) -1 else 1
            )
        } else {
            gapminder |> 
            filter(year == 2007) |> 
            ggplot(
                aes(x = gdpPercap, y = lifeExp, color = pop)
            ) +
            geom_point() +
            labs(
                x = "PIB per cápita",
                y = "Esperanza de vida"
            ) +
            theme_minimal(base_size = 8) +
            scale_color_distiller(
                palette   = input$option,
                direction = if (input$direction) -1 else 1
            )
        }
        
        }, res = 96
    )
}

## Run app
shinyApp(ui = ui, server = server)

7.3.1.2 Paletas manuales

En algunos paquetes tenemos una infinidad de paletas de colores predefinidas, pero puede haber ocasiones en las que prefiramos definir nosotros mismos la paleta de colores. Para ello, tenemos tres funciones que nos permiten definir una paleta de colores continua de forma manual:

Vamos a ver estos tres en acción:

En este caso, debemos especificar dos colores, y el resto se interpola entre ellos:

scatter_base +
    scale_color_gradient(
        name = "Población",
        low  = "blue",
        high = "green"
    )

En este caso, especificaremos además el color del medio. Por defecto, este punto es el valor de 0, por lo que podemos modificarlo a nuestro parecer con midpoint:

scatter_base +
    scale_color_gradient2(
        name = "Población",
        low  = "blue",
        mid  = "red",
        high = "green",
        midpoint = 7e8
    )

Finalmente, esta es una de las opciones más flexibles ya que en muchas ocasiones utilizaremos paletas de colores de varios colores que vienen dentro de algún paquete, y que en lugar de traer funciones del tipo scale_color_*, traen vectores de códigos hexadecimales con los colores. Un ejemplo son las paletas que vienen dentro de la función hcl.colors():

scatter_base +
    scale_color_gradientn(
        name   = "Población",
        colors = hcl.colors(50, palette = "Spectral")
    )

Las paletas pueden explorarse aquí.

7.3.2 Leyendas

La apariencia de las leyendas se controla mediante las guías (guides). En el caso de variables continuas tenemos guide_colorbar(). Para modificar esto, debemos añadir la función guides(), y dentro elegir una estética que igualaremos a guide_colorbar(), como en este ejemplo:

scatter_base +
    guides(
        color = guide_colorbar()
    )

Dentro de esta función tenemos un montón de argumentos que podemos modificar para cambiar la apariencia de la leyenda, como pueden ser:

  • title: de nuevo, el título de la leyenda.

  • title.position: posición del título con respecto a la barra

  • title.hjust: justificación del título

  • direction: dirección de la barra

  • position: posición de la leyenda con respecto al gráfico

  • barwidth y barheight: anchura y altura de la barra

scatter_base +
    guides(
        color = guide_colorbar(
            title          = "Población",
            title.position = "top",
            title.hjust    = .5,
            direction      = "horizontal",
            position       = "top",
            barwidth       = unit(10, "cm"),
            barheight      = unit(2, "mm")
        )
    )

7.3.3 Variables discretas

Las escala que se aplica por defecto a las variables discretas es scale_color_discrete(). Vamos a partir del siguiente gráfico, donde la estética color utiliza la variable del continente:

scatter_base <- gapminder |> 
    filter(year == 2007) |> 
    ggplot(
        aes(x = gdpPercap, y = lifeExp, color = continent)
    ) +
    geom_point() +
    labs(
        x = "PIB per cápita",
        y = "Esperanza de vida"
    ) +
    theme_minimal()

scatter_base
Fig. 7.6: Scatter plot del PIB per cápita, esperanza de vida y continente

7.3.3.1 Paletas manuales

Vamos a ver a continuación las opciones más comunes para modificar en la función base:

  • name: título de la leyenda

  • labels: etiquetas que se muestran en la leyenda

  • type: vector de colores

scatter_base +
    scale_color_discrete(
        name   = "Continente",
        labels = c("África", "América", "Asia", "Europa", "Oceanía"),
        type   = hcl.colors(n = 5, palette = "Dark 2")
    )

A parte de la función scale_color_discrete(), tenemos con un nombre más intuitivo: scale_color_manual(). Como diferencia, utiliza el argumento values para definir los colores. Vamos a ver cómo se utiliza:

scatter_base +
    scale_color_manual(
        name   = "Continente",
        labels = c("África", "América", "Asia", "Europa", "Oceanía"),
        values = hcl.colors(n = 5, palette = "Dark 2")
    )

7.3.3.2 Paletas predefinidas

Para el caso de las variables categóricas, también tenemos la opción de utilizar scale_color_brewer() para una paleta de colores ColorBrewer Figura 7.5. Para variables categóricas, es más interesante utilizar el segundo grupo de paletas de la Figura 7.5, debido a que nos interesa tener colores distintos para cada clase, y no una paleta secuencial donde los colores son similares.

Si queremos utilizar una paleta de viridis, podemos utilizar la función scale_color_viridis_d().

Y estas serían las escalas de colores más comunes.

7.3.3.3 Leyendas

Para las variables discretas, la leyenda se controla mediante guide_legend(). Además de los argumentos que veíamos con guide_colorbar(), tenemos la opción de nrow para definir el número de filas de la leyenda o en su caso ncol para definir el número de columnas. Vamos a ver un ejemplo:

scatter_base +
    guides(
        color = guide_legend(
            title          = "Continente",
            title.position = "top",
            title.hjust    = .5,
            position       = "top",
            nrow           = 2
        )
    )

7.4 Otras escalas

Finalmente, existen escalas para otro tipo de estéticas. Estas funcionan de manera similar a las escalas de colores, ya que también generan una leyenda. En este libro, vamos a ver las escalas de tamaño y de forma.

7.4.1 Ejercicio 12

En este ejercicio vamos a trabajar con los datos de inventario. Vamos a empezar cargando los datos, convertirlos a tibble y vamos a ver de nuevo su estructura:

El siguiente ejercicio tiene cierta complejidad para preparar los datos. Fíjate que:

  • Las únicas parcelas que se visualizan, son las parcelas mixtas, no las monoespecíficas.

  • Se han ordenado los boxplot en orden descendente según el valor del DBH.

  • La parcela debe ser una variable categórica, no numérica

  • La paleta de colores utilizada es Set3 de ColorBrewer.

  • Para que las líneas de los intervalos mayores sean más llamativas que los intervalos menores, añadir:

theme(
    panel.grid.major = element_line(color = "grey85")
  )

Si en algún momento te atascas con el preprocesado, puedes ver esa parte en la pestaña de Pista.

Fig. 7.7: Resultado esperado del ejercicio 12

Primero se filtran las filas cuyas parcelas (id_plots) tengan presentes las dos especies dentro de la columna nombre_ifn.

En siguiente lugar, se convierte id_plots a variable categórica y se ordena según la variable dbh_mm.

inventario_tbl |>
  filter(
    all(c("Pinus sylvestris", "Pinus nigra") %in% nombre_ifn),
    .by = id_plots
  ) |> 
  mutate(
    id_plots = as.factor(id_plots) |> 
      fct_reorder(dbh_mm)
  )
# A tibble: 336 × 4
   id_plots dbh_mm height_m nombre_ifn      
   <fct>     <int>    <dbl> <fct>           
 1 0           251    NA    Pinus sylvestris
 2 0           296     9.26 Pinus sylvestris
 3 0           303    10.1  Pinus sylvestris
 4 0           105     5.48 Pinus sylvestris
 5 0           138     7.07 Pinus nigra     
 6 0           153     7.54 Pinus sylvestris
 7 0           233     9.60 Pinus sylvestris
 8 0           140     7.01 Pinus sylvestris
 9 0           200     7.36 Pinus sylvestris
10 0           210    10.1  Pinus sylvestris
# ℹ 326 more rows
inventario_tbl |>
  filter(
    all(c("Pinus sylvestris", "Pinus nigra") %in% nombre_ifn),
    .by = id_plots
  ) |> 
  mutate(
    id_plots = as.factor(id_plots) |> 
      fct_reorder(dbh_mm)
  ) |>
  ggplot(
    aes(x = dbh_mm / 10, y = id_plots, fill = nombre_ifn)
  ) +
  geom_boxplot() +
  scale_fill_brewer(
    name    = NULL,
    palette = "Set3",
  ) +
  scale_x_continuous(
    position     = "top",
    breaks       = seq(0, 40, 10),
    minor_breaks = seq(0, 40, 2.5)
  ) +
  labs(
    x = "DBH (cm)",
    y = "Parcela"
  ) +
  theme_minimal() +
  theme(
    panel.grid.major = element_line(color = "grey85")
  )
Fig. 7.8: Resultado del ejercicio 12

7.4.2 Escalas de tamaño

Las escalas de tamaño (scale_size_*) se utilizan para modificar el tamaño de elementos de la gráfica, como el tamaño de los puntos o de texto. Esta se puede aplicar tanto a variables continuas como a variables discretas, y las funciones que tenemos disponibles son:

Vamos a empezar trabajando sobre este gráfico:

bubble_base <- gapminder |> 
  filter(year == 2007) |> 
  ggplot(
      aes(x = gdpPercap, y = lifeExp, fill = continent, size = pop)
  ) +
  geom_point(
    shape = 21
  ) +
  labs(
      x = "PIB per cápita",
      y = "Esperanza de vida"
  ) +
  theme_minimal()

bubble_base
Fig. 7.9: Scatter plot del PIB per cápita, esperanza de vida y población de los países del mundo

El argumento más importante de estas funciones es range, que nos permite modificar el rango de tamaños que se van a mostrar en la leyenda. En el siguiente caso, el punto más pequeño tiene tamaño de 1, mientras que el más grande tiene tamaño de 20:

bubble_base +
  scale_size(
    name  = "Población",
    range = c(1, 20)
  )

También podemos modificar utilizando una medida del radio en lugar del área:

bubble_base +
  scale_radius(
    name  = "Población",
    range = c(1, 20)
  )

Como véis, el objetivo de las funciones es el mismo pero midiendo el tamaño de distinta manera.

7.4.3 Escalas de forma

Las escalas de forma (scale_shape_*) se utilizan para modificar la forma de los elementos de la gráfica, como la forma de los puntos. Esta se puede aplicar tanto a variables continuas como a variables discretas, y las funciones que tenemos disponibles son:

En el siguiente ejemplo se muestran los continentes con las formas que vienen por defecto. Son solid indicamos si las formas son sólidas, o si tienen un borde y relleno:

base_plot <- gapminder |> 
  filter(year == 2007) |> 
  ggplot(
      aes(x = gdpPercap, y = lifeExp, shape = continent)
  ) +
  geom_point(size = 2) +
  labs(
      x = "PIB per cápita",
      y = "Esperanza de vida"
  ) +
  theme_minimal()

solid_gg <- base_plot +
  scale_shape(
    name   = "Continente",
    labels = c("África", "América", "Asia", "Europa", "Oceanía")
  )

no_solid_gg <- base_plot +
  scale_shape(
    name   = "Continente",
    labels = c("África", "América", "Asia", "Europa", "Oceanía"),
    solid  = FALSE
  )

solid_gg + no_solid_gg

7.5 Resumen

En este capítulo hemos visto diversos tipos de escalas y sus funciones. Hemos visto cómo modificar los intervalos, el número de intervalos, las etiquetas, los límites, las transformaciones, las fechas, las paletas de colores, las paletas manuales, las leyendas, y las escalas de tamaño y forma. En la Tabla 7.1 se muestra un resumen de las escalas vistas en este capítulo, además de otras que pueden ser utilizadas para otras estéticas.

Tabla 7.1: Resumen de las escalas vistas en este capítulo
Escala Estética Tipo de escala Variable
scale_*_continuous() x, y Posición Continua
scale_*_discrete() x, y Posición Categórica
scale_*_log10() x, y Posición Continua
scale_*_sqrt() x, y Posición Continua
scale_*_date() x, y Posición Fecha
scale_*_continuous() color, fill Color Continua
scale_*_discrete() color, fill Color Discreta
scale_*_viridis_c() color, fill Color Continua
scale_*_viridis_d() color, fill Color Categórica
scale_*_viridis_b() color, fill Color Continua
scale_*_distiller() color, fill Color Continua
scale_*_brewer() color, fill Color Categórica
scale_*_fermenter() color, fill Color Continua
scale_*_gradient() color, fill Color Continua
scale_*_gradient2() color, fill Color Continua
scale_*_gradientn() color, fill Color Continua
scale_*_manual() color, fill Color Categórica
scale_size() size Otras Ambas
scale_area() size Otras Ambas
scale_shape() shape Otras Ambas
scale_linetype() linetype Otras Ambas
scale_linewidth() linewidth Otras Ambas

Referencias

Garnier, Simon. 2018. «Viridis: Default Color Maps from ’Matplotlib’». https://CRAN.R-project.org/package=viridis.
Mills, Blake Robert. 2022. «MetBrewer: Color Palettes Inspired by Works at the Metropolitan Museum of Art». https://CRAN.R-project.org/package=MetBrewer.
Neuwirth, Erich. 2022. «RColorBrewer: ColorBrewer Palettes».
Pedersen, Thomas Lin, y Fabio Crameri. 2023. «scico: Colour Palettes Based on the Scientific Colour-Maps». https://github.com/thomasp85/scico.
Xiao, Nan. 2024. «ggsci: Scientific Journal and Sci-Fi Themed Color Palettes for ’ggplot2’». https://nanx.me/ggsci/.