library(ggplot2)Introducción a la visualización de datos
Cuadernos prácticos del Máster de Bioinformática (curso 2024-2025)
1 Visualización de datos
El paquete {ggplot2} se basa en la idea de Wilkinson en «Grammar of graphics»: dotar a los gráficos de una gramática propia. Una de las principales fortalezas de R es la visualización con {ggplot2}.
La visualización de datos debería ser una parte fundamental de todo análisis de datos. No es solo una cuestión estética.
La filosofía detrás de {ggplot2} es entender los gráficos como parte del flujo de trabajo, dotándoles de una gramática. El objetivo es empezar con un lienzo en blanco e ir añadiendo capas a tu gráfico. La ventaja de {ggplot2} es poder mapear atributos estéticos (color, forma, tamaño) de objetos geométricos (puntos, barras, líneas) en función de los datos.
La documentación del paquete puedes consultarla en https://ggplot2-book.org/introduction.html
Un gráfico se podrá componer de capas
- Datos (data)
- Mapeado (aesthetics) de elementos estéticos: ejes, color, forma, etc (en función de los datos)
- Geometría (geom): puntos, líneas, barras, polígonos, etc.
- Componer gráficas (facet)
- Transformaciones (stat): ordenar, resumir, etc.
- Coordenadas (coord): coordenadas cartesianas, polares, grids, etc.
- Temas (theme): fuente, tamaño de letra, subtítulos, captions, leyenda, ejes, etc.
1.1 Primer intento: scatter plot
Ahora que sabemos importar archivos, vamos a importar el conjunto de datos gapminder: un fichero con datos de esperanzas de vida, poblaciones y renta per cápita de distintos países en distintos momentos temporales.
library(readr)
gapminder <- read_csv(file = "./datos/gapminder.csv")Rows: 1704 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): country, continent
dbl (4): year, lifeExp, pop, gdpPercap
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
gapminder# A tibble: 1,704 × 6
country continent year lifeExp pop gdpPercap
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Afghanistan Asia 1952 28.8 8425333 779.
2 Afghanistan Asia 1957 30.3 9240934 821.
3 Afghanistan Asia 1962 32.0 10267083 853.
4 Afghanistan Asia 1967 34.0 11537966 836.
5 Afghanistan Asia 1972 36.1 13079460 740.
6 Afghanistan Asia 1977 38.4 14880372 786.
7 Afghanistan Asia 1982 39.9 12881816 978.
8 Afghanistan Asia 1987 40.8 13867957 852.
9 Afghanistan Asia 1992 41.7 16317921 649.
10 Afghanistan Asia 1997 41.8 22227415 635.
# ℹ 1,694 more rows
El fichero consta de 1704 registros y 6 variables: country, continent, year, lifeExp (esperanza de vida), pop (población) y gdpPercap (renta per cápita).
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
glimpse(gapminder)Rows: 1,704
Columns: 6
$ country <chr> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", …
$ continent <chr> "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "Asi…
$ year <dbl> 1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992, 1997, …
$ lifeExp <dbl> 28.801, 30.332, 31.997, 34.020, 36.088, 38.438, 39.854, 40.8…
$ pop <dbl> 8425333, 9240934, 10267083, 11537966, 13079460, 14880372, 12…
$ gdpPercap <dbl> 779.4453, 820.8530, 853.1007, 836.1971, 739.9811, 786.1134, …
Para empezar con algo sencillo filtraremos solo los datos de 1997
gapminder_1997 <- gapminder[gapminder$year == 1997, ]Imagina que queremos dibujar un scatter plot (diagrama de dispersión de puntos, que enfrenta a una variable x con una variable y).
Si tuviéses que construir capa a capa el gráfico: ¿qué necesitarías?
1.1.1 Ingredientes: datos
¿Qué elementos necesitamos para realizar un diagrama de puntos? Para iniciar el lienzo VACÍO (de momento) necesitamos llamar una base de datos con ggplot(datos)
- Datos (data): conjunto
gapminder_1997.
ggplot(gapminder_1997)1.1.2 Ingredientes: mapeo (x, y)
Ya tenemos linkada la base de datos pero necesitamos indicarle que variables de la tabla queremos que relacione con el gráfico (en este caso necesita mínimo una x y otra y).
Datos (data): conjunto
gapminder_1997.Mapeado: indicar dentro de
aes()(aesthetics) las variables en cada coordenada. Todo dentro de aes() será mapeado de la base de datos
ggplot(gapminder_1997,
aes(x = gdpPercap, y = pop))1.1.3 Geometría: geom_point()
De momento sigue vacío ya que aún no le hemos indicado lo más importante: ¿qué tipo de gráfica queremos hacer?. Para eso usaremos las capas geométricas que empiezan por geom_xxx().
- Geometría (geom): optaremos por puntos usando
geom_point().
ggplot(gapminder_1997,
aes(x = gdpPercap, y = pop)) +
geom_point()1.1.4 Rol de los ejes: (x, y)
Vamos a profundizar en ese mapeado: ¿cómo cambiar el rol de los ejes (población en el eje X y renta per cápita en el eje Y)?
- Eje X: población (variable
pop) - Eje Y: renta per cápita (variable
gdpPercap)
ggplot(gapminder_1997,
aes(x = pop, y = gdpPercap)) +
geom_point() ¿Y un scatter plot con esperanza de vida en eje X frente a renta per cápita?
- Eje X: esperanza de vida (variable
lifeExp) - Eje Y: renta per cápita (variable
gdpPercap)
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point()1.1.5 Color, size, shape: fijos
Dentro de geom_point() tenemos varios parámetros estéticos a configurar:
na.rm = ...: si queremos que nos quite ausentes.color = ...: color (si tiene dimensión, color del contorno)fill = ...: color del relleno (si tiene dimensión)
Empezaremos por un color fijo, por ejemplo "red" (existen otros como "blue", "black", "yellow", etc)
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point(color = "red")size = ...: tamaño de la geometría (en este caso el tamaño de los puntos), cuanto mayor sea el número, mayor será el tamaño de la geometría.
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point(color = "red", size = 7) alpha = ...: grado de opacidad del color (1 totalmente opaco, 0 totalmente transparente)
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point(color = "red", size = 7,
alpha = 0.4)shape = ...: forma de la geometría, en este caso del «punto» (ver todas las opciones envignette("ggplot2-specs"))
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point(color = "red",
fill = "black",
size = 7,
alpha = 0.4,
shape = 23)stroke = ...: tamaño del contorno
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point(color = "red", size = 7,
alpha = 0.4, stroke = 3)Los colores también podemos asignárselos por su código hexadecimal, consultando en https://htmlcolorcodes.com/es/, eligiendo el color que queramos. El código hexadecimal siempre comenzará con #
# Color en hexadecimal
# https://htmlcolorcodes.com/es/
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp)) +
geom_point(color = "#A02B85",
alpha = 0.4, size = 7) 1.2 Mapeado estético: aes()
Hasta ahora los atributos estéticos se los hemos pasado fijos y constantes. Pero la verdadera potencia y versatilidad de ggplot es que podemos mapear los atributos estéticos en función de los datos en aes() para que dependan de variables de los datos.
. . .
Por ejemplo, vamos a asignar un color a cada dato en función de su continente con aes(color = continent)
# Tamaño fijo
# Color por continentes
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp,
color = continent)) +
geom_point(size = 5)Podemos combinarlo con lo que hemos hecho anteriormente:
color en función del continente.
tamaño en función de la población.
transparencia la fijamos constante del 50%.
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp,
color = continent, size = pop)) +
geom_point(alpha = 0.7)A este scatter plot particular se le conoce BUBBLE CHART
Reflexionemos sobre el gráfico anterior:
- color en función del continente.
- tamaño en función de la población
- transparencia fija del 50%
Usando los datos hemos conseguido dibujar en un gráfico bidimensional 4 variables: lifeExp y gdpPercap en los ejes , continent como color y pop como tamaño de la geometría, con muy pocas líneas de código.
1.3 Escalas (scale): ejes
Es importante entender que hasta ahora solo hemos indicado que un atribut estético A dependa de una variable B de los datos.
Por ejemplo, si aes(color = variable) le estoy diciendo que cada modalidad distinta de la variable adopte un color distinto pero…¿qué color?. Para ello usaremos una de las capas más importantes, las capas de escalas scale_xxx().
1.3.1 scale_x y scale_y
Hasta ahora dentro de aes() solo le indicábamos que variable mapeamos pero no sus ajustes. Por ejemplo, vamos a configurar el eje x para tener marcas personalizadas cada 10 unidades (scale_x_continuous(breaks = ...))
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente")1.3.2 scale_color y scale_fill
La misma idea la podemos aplicar a otro atríbuto como los colores con scale_color_...() y scale_fill_...(): hemos indicado que mapeé dicho atributo por continente pero…¿qué colores usar?
Con scale_color_manual() podemos indicar manualmente una paleta (puedes buscar en https://htmlcolorcodes.com/)
pal <- c("#A02B85", "#2DE86B", "#4FB2CA", "#E8DA2D", "#E84C2D")
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
scale_color_manual(values = pal) +
labs(x = "Esperanza de vida", y = "Renta per cápita",
title = "Primer ggplot", caption = "J. Álvarez Liébana",
color = "continente")Otra opción es elegir alguna de las paletas de colores diseñadas en el paquete {ggthemes}:
scale_color_colorblind(): paleta de colores basada en los colores de daltónicos/as.
library(ggthemes)
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
scale_color_colorblind() +
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente")Incluso cargar paletas de colores diseñadas en base a películas o arte
- películas: paquete
{harrypotter}(repositorio de Githubaljrico/harrypotter) usandoscale_color_hp_d().
library(harrypotter)
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
scale_color_hp_d(option = "ravenclaw")+
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente")- cuadros: paquete
{MetBrewer}(repositorio de GithubBlakeRMills/MetBrewer) usandoscale_colour_manual(values = met.brewer(...)).
library(MetBrewer)
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
scale_color_manual(values = met.brewer("Monet")) +
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente")- discos: paquete
{peRReo}(repositorio de Githubjbgb13/peRReo) usandoscale_colour_manual(values = latin_palette()).
library(peRReo)
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
scale_color_manual(values = latin_palette("rosalia")) +
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente")1.3.3 scale_xxx
Lo mismo que hemos hecho para los ejes o colores podemos hacer para el resto de atríbutos estéticos
Por ejemplo, vamos a indicarle que mapeé el tamaño en función de población pero indicándole el rango de valores (continuo en este caso) entre los que moverse con scale_size_continuous()
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
ggthemes::scale_color_colorblind() +
scale_size_continuous(range = c(3, 17)) +
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente")1.4 Etiquetas sencillas: labs()
Podemos también personalizar de manera sencilla haciendo uso de la capa labs():
title,subtitle: título/subtítulocaption: pie de gráficax, y: nombres de los ejessize, color, fill, ...: nombre en leyenda de las variables que codifiquen los atributos
ggplot(gapminder_1997,
aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
ggthemes::scale_color_colorblind() +
labs(x = "Esp. de vida",
y = "Renta per cápita",
title = "Primer ggplot",
caption = "J. Álvarez Liébana",
color = "continente",
size = "población")1.4.1 Eliminar de la leyenda
Podemos eliminar variables de la leyenda con guides(atributo = "none")
ggplot(gapminder_1997,
aes(y = gdpPercap,
x = lifeExp,
color = continent,
size = pop)) +
geom_point(alpha = 0.7) +
ggthemes::scale_color_colorblind() +
guides(size = "none") +
labs(x = "Esperanza de vida",
y = "Renta per cápita",
title = "Primer ggplot",
caption = "J. Álvarez Liébana",
color = "continente")1.5 Tema (básico)
Por último en este primer gráfico, vamos personalizar el tema con alguna de las capas theme_...(). Por ejemplo, vamos a usar theme_minimal() para tener un tema “austero” y minimalista (aprenderemos a definir cada detalle de nuestro tema).
ggplot(gapminder_1997, aes(y = gdpPercap, x = lifeExp, color = continent, size = pop)) +
geom_point(alpha = 0.7) +
scale_x_continuous(breaks = seq(35, 85, by = 10)) +
ggthemes::scale_color_colorblind() +
labs(x = "Esperanza de vida", y = "Renta per cápita", title = "Primer ggplot",
caption = "J. Álvarez Liébana", color = "continente") +
theme_minimal()2 Otros gráficos
El anterior ejemplo era un diagrama de dispersión (bivariante) que nos permite jugar mucho con los parámetros pero empezaremos aprendiendo a analizar una sola variable (estadística univariante).
Para ello algo fundamental será conocer la naturaleza de la variable ya que habrá cosas que podamos hacer con un tipo de variables y no con otras. Por ejemplo, vamos a tomar el fichero de datos starwars del paquete {dplyr} y vamos a empezar un ggplot
library(dplyr)
ggplot(starwars)Si quiésemos hacer un diagrama de dispersión sencillo como antes entre peso y estatura sería así
ggplot(starwars) +
geom_point(aes(x = mass, y = height)) +
theme_minimal()Warning: Removed 28 rows containing missing values or values outside the scale range
(`geom_point()`).
¿Qué línea habrá cambiar si en lugar de hacer un diagrama de dispersión queremos hacer un histograma de la estatura Lo que diferencia a un gráfico de otro es la capa geométrica, así que deberemos buscar un geom_xxx() distinto (en este caso geom_histogram())
2.1 Histogramas
Un histograma es una representación gráfica de la distribución de frecuencia de un conjunto de datos numéricos continuos. Consiste en un gráfico de barras PERO donde ahora la base de cada barra representa un intervalo de valores, y la altura de la barra indica la frecuencia o la densidad de datos dentro de ese intervalo: ahora la anchura de las barras sí es relevante (cuantifica la anchura del intervalo en el que estamos agrupando los datos).
Los histogramas son especialmente útiles para visualizar la forma y la dispersión de los datos aunque dependen de un parámetro crítico como es la cantidad de barras (o anchura de cada barra) de las que queramos disponer.

Fíjate que si lo cambiamos tal cual produce error. ¿Por qué?
ggplot(starwars) + geom_histogram(aes(x = mass, y = height))Error in `geom_histogram()`:
! Problem while computing stat.
ℹ Error occurred in the 1st layer.
Caused by error in `setup_params()`:
! `stat_bin()` must only have an x or y aesthetic.
La capa usada (histograma) solo admite una x o un y –> habrás gráficos bivariantes y gráficos univariantes
ggplot(starwars) +
geom_histogram(aes(x = height)) +
theme_minimal()`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Warning: Removed 6 rows containing non-finite outside the scale range
(`stat_bin()`).
Los histogramas dependen de una decisión crítica que cambiará por completo el gráfico: el número de barras (bins = ...).
Code
ggplot(starwars) +
geom_histogram(aes(x = height), bins = 8) +
theme_minimal()Warning: Removed 6 rows containing non-finite outside the scale range
(`stat_bin()`).
2.2 Gráfico de densidad
Como hemos comentado una de las decisiones a tomar en un histograma es la anchura de las barras ya que dicho valor va a cambiar nuestra percepción de la distribución de los datos.
Una de las alternativas más conocidas son los conocidos como gráficos de densidad, una especie de aproximación continua de dichas barras, proporcionando la curva que se intuye que define la forma de un histograma si hacemos las barras cada vez más finas.

Para realizar un gráfico de densidad debemos de usar simplemente geom_density() como capa geométrica
Code
ggplot(starwars) +
geom_density(aes(x = height)) +
theme_minimal()Warning: Removed 6 rows containing non-finite outside the scale range
(`stat_density()`).
Lo que hemo aprendido sobre los atributos estéticos de un gráfico podemos aplicarlo a cualquier capa. Por ejemplo, vamos a decirle que el color y relleno de la densidad dependa del sex (es decir, una densidad para cada uno).
Code
library(tidyverse)
ggplot(starwars |> drop_na(sex)) +
geom_density(aes(x = height, fill = sex, color = sex),
alpha = 0.3) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()El paquete {ggridges} y su función geom_density_ridges() nos permite visualizar densidades de distintos grupos en distintos niveles de altura: en lugar de tener todas una encima de otra, podremos indicarle una variable y
Code
library(ggridges)
ggplot(starwars |> drop_na(sex)) +
geom_density_ridges(aes(x = height, y = sex,
fill = sex, color = sex),
alpha = 0.3) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()2.3 Diagrama de sectores
Un gráfico de sectores, también conocido como gráfico circular o pie chart en inglés, es una representación visual de datos que muestra la proporción de cada categoría dentro de un conjunto de datos en forma de un círculo dividido en sectores. Cada sector representa una categoría y su tamaño angular es proporcional a la frecuencia o proporción de esa categoría en relación con el total.



2.4 Diagrama de barras
Utiliza barras rectangulares para mostrar la frecuencia, la magnitud o la proporción de diferentes categorías. Cada barra representa una categoría específica y su longitud es proporcional a la cantidad o frecuencia que representa. Es importante no confundir con un histograma: en un diagrama de barras la anchura de cada barra es una decisión meramente estética (incluso si dejas o no un hueco entre cada barra).
También pueden ser útiles para representar variables cuantitativas discretas (e.g., número de hijos).

2.5 Diagrama de cajas
Un diagrama de cajas (boxplots) es una representación gráfica que proporciona un resumen de varias características importantes de un conjunto de datos numéricos basado en medidas de posición.
El diagrama de cajas muestra la distribución de los datos a lo largo de un eje vertical, dividiendo el conjunto de datos en cuartiles y proporcionando información sobre la dispersión y la simetría de la distribución. Es importante tener en cuenta que en este gráfico, tanto la centralidad representada (mediana) como las medidas de posición (cuartiles) como los valores atípicos, se hace en relación a la mediana y no a la media.

Para realizarlos basta con usar geom_boxplot() como capa geométrica. Por ejemplo, vamos a realizar uno con la variable height
Code
ggplot(starwars |> drop_na(height)) +
geom_boxplot(aes(x = height)) +
theme_minimal()Podemos invertir la posición de los boxplots indicándole la variable y en lugar de x.
Code
ggplot(starwars |> drop_na(height)) +
geom_boxplot(aes(x = height)) +
theme_minimal()Podemos de nuevo incluir lo aprendido sobre atributos estéticos en estos gráficos. Por ejemplo, vamos a pintar un boxplot vertical (es decir y = height) por cada sexo (x = sex) distinguiendo los colores de cada uno.
Code
ggplot(starwars |> drop_na(height, sex)) +
geom_boxplot(aes(x = sex, y = height, fill = sex,
color = sex), alpha = 0.5) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()La función geom_boxplot() nos permite incluso distinguir outliers en color, forma y tamaño (empiezan todos los parámetros por outlier...)
Code
ggplot(starwars |> drop_na(height, sex)) +
geom_boxplot(aes(x = sex, y = height, fill = sex,
color = sex), alpha = 0.5,
outlier.alpha = 0.8, outlier.shape = 23,
outlier.size = 2, outlier.color = "#d72020",
outlier.fill = "#d72020") +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()Dichos gráficos podemos combinarlos con un gotelé de las observaciones haciendo uso de geom_jitter(), indicándole con width = ... la anchura del gotelé (a más valor, más disperso y confuso).
Code
ggplot(starwars |> drop_na(height, sex),
aes(x = sex, y = height, fill = sex, color = sex)) +
geom_boxplot(alpha = 0.5, outlier.alpha = 0) +
geom_jitter(width = 0.3) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()2.6 Gráficos de violín
Los gráficos de cajas y bigotes o boxplot son una alternativa que mejora los clásicos gráficos dinámita o error bar plots (ver incovenientes de boxplots), uno de los gráficos más habituales en artículos científicos en el ámbito de la bioinformática y bioestadística.
A pesar de que son una mejor alternativa que los error bar plots, en muchas ocasiones puede ser interesante acompañar a nuestros boxplot con lo que se conoce como gráficos de violín (algo parecido a dos gráficos de densidad, uno pegado al otro de manera simétrica)

Para el gráfico de violín basta con geom_violin()
Code
ggplot(starwars |> drop_na(height, sex),
aes(x = sex, y = height,
fill = sex, color = sex)) +
geom_violin(alpha = 0.5) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()Warning: Groups with fewer than two datapoints have been dropped.
ℹ Set `drop = FALSE` to consider such groups for position adjustment purposes.
Incluso puedes combinarlo con un boxplot
Code
ggplot(starwars |> drop_na(height, sex),
aes(x = sex, y = height,
fill = sex, color = sex)) +
geom_violin(alpha = 0.5) +
geom_boxplot(alpha = 0.2, width = 0.2,
outlier.alpha = 0.8) +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
theme_minimal()Warning: Groups with fewer than two datapoints have been dropped.
ℹ Set `drop = FALSE` to consider such groups for position adjustment purposes.
3 Recursos para visualización
4 💻 Tu turno
Intenta realizar los siguientes ejercicios sin mirar las soluciones
📝 Toma el conjunto ya conocido de starwars del paquete {dplyr}. Realiza un diagrama de barras para contar las modalidades de la variable sex (solo eso, sin más opciones) eliminando antes los ausentes.
Code
starwars |>
drop_na(sex) |>
ggplot() +
geom_bar(aes(x = sex))📝 Añade lo que consideres del gráfico anterior para hacer que el relleno dependa de cada valor de sex. Personaliza tú los colores.
Code
starwars |>
drop_na(sex) |>
ggplot() +
geom_bar(aes(x = sex, fill = sex), alpha = 0.7) +
scale_fill_manual(values = c("#3b9559", "#e29c4d", "#4265b0", "#b0428b"))📝 Añade lo que consideres del gráfico anterior para personalizar los títulos de los ejes, de la leyenda, poner un título al gráfico.
Code
starwars |>
drop_na(sex) |>
ggplot() +
geom_bar(aes(x = sex, fill = sex), alpha = 0.7) +
scale_fill_manual(values = c("#3b9559", "#e29c4d", "#4265b0", "#b0428b")) +
labs(x = "Sexo", y = "Frec. absoluta",
title = "Distribución de sexo en personajes\nde Starwars",
fill = "Sexo")📝 Añade lo que consideres del gráfico anterior para hacer que el eje y tenga una marca de 10 en 10 valores. Incluye un tema diferente al de por defecto
Code
starwars |>
drop_na(sex) |>
ggplot() +
geom_bar(aes(x = sex, fill = sex), alpha = 0.7) +
scale_fill_manual(values = c("#3b9559", "#e29c4d", "#4265b0", "#b0428b")) +
scale_y_continuous(breaks = seq(0, 60, by = 10)) +
labs(x = "Sexo", y = "Frec. absoluta",
title = "Distribución de sexo en personajes\nde Starwars",
fill = "Sexo") +
theme_minimal()📝 ¿Cómo podrías modificar el código anterior para que cada barra se divida en función de la variable género? Cada barra (para cada sexo) se dividirá en dos géneros: masculino y femenino.
Code
starwars |>
drop_na(sex) |>
ggplot() +
geom_bar(aes(x = sex, fill = gender), alpha = 0.7) +
scale_fill_manual(values = c("#e29c4d", "#4265b0")) +
scale_y_continuous(breaks = seq(0, 60, by = 10)) +
labs(x = "Sexo", y = "Frec. absoluta",
title = "Distribución de sexo y género\nen personajes de Starwars",
fill = "Género") +
theme_minimal()📝 Replica el gráfico del ejercicio 4 pero haciendo uso de las frecuencias relativas (cálculas antes para poder visualizarla)
Code
starwars |>
drop_na(sex) |>
count(sex) |>
mutate("frec_rel" = n/sum(n)) |>
ggplot() +
geom_col(aes(x = sex, y = frec_rel, fill = sex), alpha = 0.7) +
scale_fill_manual(values = c("#3b9559", "#e29c4d", "#4265b0", "#b0428b")) +
scale_y_continuous(breaks = seq(0, 0.9, by = 0.1)) +
labs(x = "Sexo", y = "Frec. absoluta",
title = "Distribución de sexo en\n personajes de Starwars",
fill = "Sexo") +
theme_minimal()📝 Visualiza un boxplot de la variable estatura distinguiendo por sexos
Code
starwars |>
drop_na(height, sex) |>
ggplot() + # le decimos que los outlier
geom_boxplot(aes(x = sex, y = height, color = sex, fill = sex), alpha = 0.5) +
scale_color_manual(values = c("#3b9559", "#e29c4d", "#4265b0", "#b0428b")) +
scale_fill_manual(values = c("#3b9559", "#e29c4d", "#4265b0", "#b0428b")) +
guides(color = "none") + # para eliminar color de leyenda
labs(x = "Sexo", y = "Estatura",
title = "Distribución de la estatura vs sexo en\n personajes de Starwars",
fill = "Sexo") +
theme_minimal()5 🐣 Caso práctico: visualización covid
Vamos a practicar la visualización con la base de datos completa de covid del ISCIII que vamos a cargar directamente desde la web: en lugar de poner la ruta del .csv de nuestro ordenador vamos a poder usar el link directamente (clickando con botón derecho del ratón en los archivos de https://cnecovid.isciii.es/covid19/#documentaci%C3%B3n-y-datos)
library(readr)
datos <- read_csv(file = "https://cnecovid.isciii.es/covid19/resources/casos_hosp_uci_def_sexo_edad_provres.csv")Rows: 1299030 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): provincia_iso, sexo, grupo_edad
dbl (4): num_casos, num_hosp, num_uci, num_def
date (1): fecha
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
datos# A tibble: 1,299,030 × 8
provincia_iso sexo grupo_edad fecha num_casos num_hosp num_uci num_def
<chr> <chr> <chr> <date> <dbl> <dbl> <dbl> <dbl>
1 A H 0-9 2020-01-01 0 0 0 0
2 A H 10-19 2020-01-01 0 0 0 0
3 A H 20-29 2020-01-01 0 0 0 0
4 A H 30-39 2020-01-01 0 0 0 0
5 A H 40-49 2020-01-01 0 0 0 0
6 A H 50-59 2020-01-01 0 0 0 0
7 A H 60-69 2020-01-01 0 0 0 0
8 A H 70-79 2020-01-01 0 0 0 0
9 A H 80+ 2020-01-01 0 0 0 0
10 A H NC 2020-01-01 0 0 0 0
# ℹ 1,299,020 more rows
5.1 Pregunta 1
Calcula en tidyverse un RESUMEN de tu tabla obteniendo el número de casos totales por fecha y sexo (es decir, sumando todos los casos para una fecha y un sexo dado, sin importar la provincia ni la edad)
Code
library(tidyverse)
resumen <-
datos |>
summarise("casos" = sum(num_casos), .by = c(fecha, sexo))5.2 Pregunta 2
Usando el resumen anterior crea otro de manera que tengas el total de casos por fecha (sin importar el sexo)
Code
resumen_total <-
resumen |>
summarise("casos" = sum(casos), .by = fecha)5.3 Pregunta 3
Con el dataset anterior, filtra entre 1 de marzo de 2020 y 30 de septiembre de 2020, y tras ello dibuja un diagrama de barras que nos visualice el número de casos por fecha
Code
resumen_total |>
filter(between(fecha, as_date("2020-03-01"), as_date("2020-09-30"))) |>
ggplot() +
geom_col(aes(x = fecha, y = casos))5.4 Pregunta 4
Personaliza el gráfico anterior para que las marcas del eje y vayan de 1000 en 1000 casos. Personaliza también las etiquetas de los eje, título, subtítulo y pie de figura. Añade un tema.
Code
resumen_total |>
filter(between(fecha, as_date("2020-03-01"), as_date("2020-09-30"))) |>
ggplot() +
geom_col(aes(x = fecha, y = casos)) +
scale_y_continuous(breaks = seq(0, 17000, by = 1000)) +
labs(x = "Fecha", y = "Casos totales notificados",
title = "Evolución del covid",
subtitle = "Fechas: desde el 1 de marzo hasta el 30 de septiembre de 2020",
caption = "Fuente: ISCIII") +
theme_minimal()5.5 Pregunta 5
Repite el gráfico anterior pero con el resumen inicial por sexo y fecha. Piensa como distinguir los casos notificados de cada sexo. Personaliza los colores que uses.
Code
resumen |>
filter(between(fecha, as_date("2020-03-01"), as_date("2020-09-30"))) |>
ggplot() +
geom_col(aes(x = fecha, y = casos, fill = sexo),
alpha = 0.5) +
scale_y_continuous(breaks = seq(0, 17000, by = 1000)) +
ggthemes::scale_fill_colorblind() +
labs(x = "Fecha", y = "Casos totales notificados",
title = "Evolución del covid",
subtitle = "Fechas: desde el 1 de marzo hasta el 30 de septiembre de 2020",
caption = "Fuente: ISCIII",
fill = "sexo") +
theme_minimal()5.6 Pregunta 6
Guarda la gráfica anterior en una variable. Con la capa
theme()podemos, con una gráfica ya hecha, modificar cada elemento de su tema. Por ejemplo, investigatheme(legend.position = ...)para poner la leyenda debajo de la gráfica en lugar de la derecha.
Code
grafica <-
resumen |>
filter(between(fecha, as_date("2020-03-01"), as_date("2020-09-30"))) |>
ggplot() +
geom_col(aes(x = fecha, y = casos, fill = sexo),
alpha = 0.5) +
scale_y_continuous(breaks = seq(0, 17000, by = 1000)) +
ggthemes::scale_fill_colorblind() +
labs(x = "Fecha", y = "Casos totales notificados",
title = "Evolución del covid",
subtitle = "Fechas: desde el 1 de marzo hasta el 30 de septiembre de 2020",
caption = "Fuente: ISCIII",
fill = "sexo") +
theme_minimal()
grafica +
theme(legend.position = "bottom")5.7 Pregunta 7
Convierte la gráfica anterior a gráfica interactiva con el paquete
{plotly}
Code
plotly::ggplotly(grafica)5.8 Pregunta 8
Con el resumen por fecha y sexo, visualiza la distribución de casos diarios mediante un boxplot (uno por cada sexo). Marca los outliers de manera diferenciada.
Code
resumen |>
filter(between(fecha, as_date("2020-03-01"), as_date("2020-09-30"))) |>
ggplot() +
geom_boxplot(aes(x = sexo, y = casos, color = sexo, fill = sexo),
alpha = 0.5, outlier.alpha = 0.9, outlier.shape = 23,
outlier.size = 2.5, outlier.fill = "#900000") +
ggthemes::scale_color_colorblind() +
ggthemes::scale_fill_colorblind() +
labs(x = "Sexo", y = "Casos diarios notificados",
title = "Evolución del covid",
subtitle = "Fechas: desde el 1 de marzo hasta el 30 de septiembre de 2020",
caption = "Fuente: ISCIII") +
theme_minimal()