12  Otra estéticas

You are reading the work-in-progress third edition of the ggplot2 book. This chapter should be readable but is currently undergoing final polishing.

Además de la posición y el color, ggplot2 puede utilizar otras funciones estéticas para representar datos. En este capítulo, analizaremos las escalas de tamaño (Sección 12.1), de forma (Sección 12.2), de ancho de línea (Sección 12.3) y de tipo de línea (Sección 12.4), que utilizan características visuales distintas a la ubicación y el color para representar los valores de los datos. Además, hablaremos de las escalas manuales (Sección 12.5) y de identidad (Sección 12.6): estas no utilizan necesariamente características visuales diferentes, pero construyen asignaciones de datos de una forma inusual.

12.1 Tamaño

La estética de tamaño se usa típicamente para escalar puntos y texto. La escala predeterminada para la estética de tamaño es scale_size(), donde un aumento lineal en la variable se asigna a un aumento lineal en el área (no en el radio) del geom. Escalar en función del área es una opción predeterminada sensata, ya que la percepción humana del tamaño se asemeja más al escalar el área que al escalar el radio. Por defecto, el valor más pequeño de los datos (más precisamente, en los límites de escala) se asigna a un tamaño de 1 y el más grande a un tamaño de 6. El argumento range permite escalar el tamaño de los geoms:

base <- ggplot(mpg, aes(displ, hwy, size = cyl)) + 
  geom_point()

base
base + scale_size(range = c(1, 2))

Hay varias escalas de tamaño que vale la pena mencionar brevemente:

  • scale_size_area() y scale_size_binned_area() son versiones de scale_size() y scale_size_binned() que garantizan que un valor de 0 se asigne a un área de 0.

  • scale_radius() asigna el valor de los datos al radio en lugar de al área (Sección 12.1.1).

  • scale_size_binned() es una escala de tamaño que se comporta como scale_size(), pero asigna valores continuos a categorías de tamaño discretas, de forma análoga a las escalas de posición y color agrupadas que se describen en Sección 10.4 y Sección 11.4, respectivamente. Las leyendas asociadas con esta escala se describen en Sección 12.1.2.

  • scale_size_date() y scale_size_datetime() están diseñados para manejar datos de fechas, de forma análoga a las escalas de fechas analizadas en Sección 10.2.

12.1.1 Escalas de tamaño de radio

Existen situaciones en las que el escalado de área no es deseable, y para ello se proporciona la función scale_radius(). Para ilustrar cuándo scale_radius() es apropiada, considere un conjunto de datos que contiene datos astronómicos que incluyen el radio de diferentes planetas:

planets
#>      name  type position radius    orbit
#> 1 Mercury Inner        1   2440 5.79e+07
#> 2   Venus Inner        2   6052 1.08e+08
#> 3   Earth Inner        3   6378 1.50e+08
#> 4    Mars Inner        4   3390 2.28e+08
#> 5 Jupiter Outer        5  71400 7.78e+08
#> 6  Saturn Outer        6  60330 1.43e+09
#> 7  Uranus Outer        7  25559 2.87e+09
#> 8 Neptune Outer        8  24764 4.50e+09

En este caso, un gráfico que utiliza la estética del tamaño para representar el radio de los planetas debe usar scale_radius() en lugar del scale_size() predeterminado. También es importante en este caso establecer los límites de escala para que un planeta con radio 0 se dibuje con un disco con radio 0.

base <- ggplot(planets, aes(1, name, size = radius)) + 
  geom_point() + 
  scale_x_continuous(breaks = NULL) + 
  labs(x = NULL, y = NULL, size = NULL)
  
base + ggtitle("not to scale")
base + 
  scale_radius(limits = c(0, NA), range = c(0, 10)) + 
  ggtitle("to scale")

A la izquierda es difícil distinguir Júpiter de Saturno, a pesar de que la diferencia entre ambos debería ser el doble del tamaño de la Tierra; Compare esto con el gráfico de la derecha, donde el radio de Júpiter es visiblemente mayor.

12.1.2 Escalas de tamaño agrupadas

Las escalas de tamaño agrupadas funcionan de forma similar a las escalas agrupadas para la estética de color y posición (Sección 11.4 y Sección 10.4). Una diferencia radica en cómo se muestran las leyendas. La leyenda predeterminada para una escala de tamaño agrupada, y para todas las escalas agrupada, excepto la estética de posición y color, se rige por guide_bins(). Por ejemplo, en los datos mpg, podríamos usar scale_size_binned() para crear una versión agrupada de la variable continua hwy:

base <- ggplot(mpg, aes(displ, manufacturer, size = hwy)) +
  geom_point(alpha = .2) +
  scale_size_binned()

base

A diferencia de guide_legend(), la guía creada para una escala agrupada por guide_bins() no organiza las claves individuales en una tabla. En lugar de ello, están organizados en una columna (o fila) a lo largo de un único eje vertical (u horizontal), que de forma predeterminada se muestra con su propio eje. Los argumentos importantes para guide_bins() se enumeran a continuación:

  • axis indica si se debe dibujar el eje (el valor predeterminado es TRUE)

    base + guides(size = guide_bins(axis = FALSE))
    #> Warning: Ignoring unknown argument to `guide_bins()`: `axis`.

  • direction es una cadena de caracteres que especifica la dirección de la guía, ya sea "vertical" (por defecto) o "horizontal"

    base + guides(size = guide_bins(direction = "horizontal"))

  • show.limits especifica si se muestran marcas en los extremos del eje guía (el valor predeterminado es FALSE)

    base + guides(size = guide_bins(show.limits = TRUE))

  • axis.colour, axis.linewidth y axis.arrow se utilizan para controlar el eje guía que se muestra junto a las entradas de la leyenda

    base + guides(
      size = guide_bins(
        axis.colour = "red",
        axis.arrow = arrow(
          length = unit(.1, "inches"), 
          ends = "first", 
          type = "closed"
        )
      )
    )
    #> Warning: Ignoring unknown arguments to `guide_bins()`: `axis.colour` and
    #> `axis.arrow`.

  • keywidth, keyheight, reverse y override.aes tienen el mismo comportamiento para guide_bins() com para guide_legend() (see Sección 11.3.6)

12.2 Forma

Los valores se pueden asignar a la estética de la forma. El uso típico de esto es cuando tiene una pequeña cantidad de categorías discretas: si la variable de datos contiene más de 6 valores, resulta difícil distinguir entre formas y generará una advertencia. La función predeterminada scale_shape() contiene un solo argumento: establezca solid = TRUE (el valor predeterminado) para usar una “paleta” que consta de tres formas sólidas y tres formas huecas, o establezca solid = FALSE para usar seis formas huecas formas:

base <- ggplot(mpg, aes(displ, hwy, shape = factor(cyl))) + 
  geom_point()

base
base + scale_shape(solid = FALSE)

Aunque es poco probable que un gráfico sea legible con más de 6 marcadores distintos, hay 25 formas posibles para elegir, cada una asociada con un valor entero:

Puede especificar los tipos de marcador para cada valor de datos manualmente usando scale_shape_manual():

base + 
  scale_shape_manual(
    values = c("4" = 16, "5" = 17, "6" = 1 , "8" = 2)
  )

Para obtener más información sobre básculas manuales, consulte Sección 12.5.

12.3 Ancho de línea

La estética del ancho de línea, introducida en ggplot2 3.4.0, se utiliza para controlar el ancho de las líneas. En versiones anteriores de ggplot2 se usaba la estética del tamaño para este propósito, lo que causaba algunas dificultades para geoms complejas como geom_pointrange() que contienen tanto puntos como líneas. Para estas geoms suele ser importante poder controlar por separado el tamaño de los puntos y el ancho de las líneas. Esto se ilustra en los gráficos siguientes. En el gráfico más a la izquierda, tanto la estética del tamaño como del ancho de línea se establecen en sus valores predeterminados. El gráfico del medio aumenta el tamaño de los puntos sin cambiar el ancho de línea, mientras que el gráfico de la derecha aumenta el ancho de línea sin cambiar el tamaño de los puntos.

base <- ggplot(airquality, aes(x = factor(Month), y = Temp))

base + geom_pointrange(stat = "summary", fun.data = "median_hilow")
base + geom_pointrange(
  stat = "summary", 
  fun.data = "median_hilow", 
  size = 2
)
base + geom_pointrange(
  stat = "summary", 
  fun.data = "median_hilow", 
  linewidth = 2
)

En la práctica, lo más probable es que establezcas el ancho de línea como un parámetro fijo, como se muestra en el ejemplo anterior, pero es una verdadera estética y se puede asignar a valores de datos:

ggplot(airquality, aes(Day, Temp, group = Month)) + 
  geom_line(aes(linewidth = Month)) + 
  scale_linewidth(range = c(0.5, 3))

Las escalas de ancho de línea se comportan como escalas de tamaño en la mayoría de los casos, pero existen diferencias. Como se analizó anteriormente, el comportamiento predeterminado de una escala de tamaño es aumentar linealmente con el área del marcador de trazado (por ejemplo, el diámetro de un marcador de trazado circular aumenta con la raíz cuadrada del valor de los datos). Por el contrario, el ancho de línea aumenta linealmente con el valor de los datos.

Se pueden agregar escalas de ancho de línea agrupadas usando scale_linewidth_binned().

12.4 Tipo de línea

Es posible asignar una variable a la estética del tipo de línea en ggplot2. Esto funciona mejor para variables discretas con una pequeña cantidad de categorías, y scale_linetype() es un alias para scale_linetype_discrete(). Las variables continuas no se pueden asignar a tipos de línea a menos que se use scale_linetype_binned(): aunque existe una función scale_linetype_continuous(), lo único que hace es producir un error. Para ver por qué la estética del tipo de línea es adecuada sólo para casos con unas pocas categorías, considere este gráfico:

ggplot(economics_long, aes(date, value01, linetype = variable)) +
  geom_line()

Con cinco categorías, la gráfica es bastante difícil de leer y es poco probable que quieras utilizar la estética del tipo de línea para más que eso. La “paleta” predeterminada para el tipo de línea la proporciona la función scales::linetype_pal() e incluye los 13 tipos de línea que se muestran a continuación:

df <- data.frame(value = letters[1:13])
base <- ggplot(df, aes(linetype = value)) +
  geom_segment(
    mapping = aes(x = 0, xend = 1, y = value, yend = value),
    show.legend = FALSE
  ) +
  theme(panel.grid = element_blank()) +
  scale_x_continuous(NULL, NULL) 

base

Puede controlar el tipo de línea especificando una cadena con hasta 8 valores hexadecimales (es decir, de 0 a F). En esta especificación, el primer valor es la longitud del primer segmento de línea, el segundo valor es la longitud del primer espacio entre segmentos, y así sucesivamente. Esto le permite especificar sus propios tipos de línea usando scale_linetype_manual(), o alternativamente, pasando una función personalizada al argumento palette:

linetypes <- function(n) {
  types <- c("55",  "75", "95", "1115", "111115", "11111115",
             "5158", "9198", "c1c8")
  return(types[seq_len(n)])
}

base + discrete_scale("linetype", palette = linetypes)
#> Warning: Removed 4 rows containing missing values or values outside the scale range
#> (`geom_segment()`).

Tenga en cuenta que las últimas cuatro líneas están en blanco, porque la función linetypes() definida anteriormente devuelve NA cuando el número de categorías excede 9. La función discrete_scale() contiene un argumento na.value usado para especificar qué Se traza un tipo de línea para estos valores. De forma predeterminada, esto produce una línea en blanco, pero puede anular esto configurando na.value = "dotted":

base + discrete_scale("linetype", palette = linetypes, na.value = "dotted")

Los tipos de línea válidos se pueden configurar utilizando una cadena de caracteres legible por humanos: "blank" para una línea de color blanco, "solid" para una línea de color negro, "dashed" para una línea discontinua, "dotted" para una línea de puntos, "dotdash" para una línea que alterna entre discontinua y puntos, "longdash" para una línea discontinua con fragmentos más largos, y"twodash" para una línea que alterna entre discontinua con fragmentos cortos y largos.

12.5 Escala manual

Las escalas manuales son solo una lista de valores válidos que se asignan a valores discretos únicos. Si desea personalizar estas escalas, necesita crear su propia escala nueva con la versión “manual” de cada una: scale_linetype_manual(), scale_shape_manual(), scale_colour_manual(), etc. La escala manual tiene una argumento importante, values, donde especifica los valores que la escala debe producir si se nombra este vector, hará coincidir los valores de la salida con los valores de la entrada; de lo contrario, coincidirá en el orden de los niveles de la variable discreta. Necesitará algunos conocimientos de los valores estéticos válidos, que se describen en vignette("ggplot2-specs").

Las escalas manuales aparecieron antes, en ?sec-manual-color y Sección 12.2. En este ejemplo, mostraremos un uso creativo de scale_colour_manual() para mostrar múltiples variables en el mismo gráfico y mostrar una leyenda útil. En la mayoría de los sistemas de trazado, colorearías las líneas y luego agregarías una leyenda:

huron <- data.frame(year = 1875:1972, level = as.numeric(LakeHuron))

ggplot(huron, aes(year)) +
  geom_line(aes(y = level + 5), colour = "red") +
  geom_line(aes(y = level - 5), colour = "blue")
Figura 12.1

Eso no funciona en ggplot porque no hay forma de agregar una leyenda manualmente. En su lugar, asigne etiquetas informativas a las líneas:

ggplot(huron, aes(year)) +
  geom_line(aes(y = level + 5, colour = "above")) +
  geom_line(aes(y = level - 5, colour = "below"))
Figura 12.2

Y luego dile a la escala cómo asignar etiquetas a colores:

ggplot(huron, aes(year)) +
  geom_line(aes(y = level + 5, colour = "above")) +
  geom_line(aes(y = level - 5, colour = "below")) +
  scale_colour_manual("Direction",
    values = c("above" = "red", "below" = "blue")
  )
Figura 12.3

12.6 Escalas de identidad

Las escalas de identidad, como scale_colour_identity() y scale_shape_identity(), se utilizan cuando los datos ya están escalados de manera que los datos y los espacios estéticos sean los mismos. El siguiente código muestra un ejemplo en el que la escala de identidad es útil. luv_colours contiene las ubicaciones de todos los colores integrados de R en el espacio de color LUV (el espacio en el que se basa HCL). Una leyenda es innecesaria, porque el color del punto se representa a sí mismo: los datos y los espacios estéticos son los mismos.

head(luv_colours)
#>      L         u    v           col
#> 1 9342 -3.37e-12    0         white
#> 2 9101 -4.75e+02 -635     aliceblue
#> 3 8810  1.01e+03 1668  antiquewhite
#> 4 8935  1.07e+03 1675 antiquewhite1
#> 5 8452  1.01e+03 1610 antiquewhite2
#> 6 7498  9.03e+02 1402 antiquewhite3

ggplot(luv_colours, aes(u, v)) + 
geom_point(aes(colour = col), size = 3) + 
scale_color_identity() + 
coord_equal()