En este tema abordaremos diferentes formas de presentar los datos con recursos gráficos
El material fue concebido partiendo de un enfoque más simple al más complejo
La idea es que usuarios principiantes puedan producir todos los gráficos
Para la construcción de este material fueron adaptados los ejemplos disponibles en: Simple Gantt charts in R with ggplot2 and Microsoft Excel - Cédric Scherer
El ggplot2 es un paquete del lenguaje de programación estadística R
Es una herramienta robusta y llena de funcionalidades, construida para visualización de datos
R es un lenguaje de programación muy poderoso y ampliamente utilizado para análisis de datos.
Sin embargo, la mayor parte de sus funcionalidades avanzadas están disponibles a través de paquetes.
Los paquetes en R, como “ggplot2”, son colecciones de funciones, datos y documentación que amplían las capacidades básicas de R.
No es necesario descargar e instalar más de una vez los paquetes en R. Sin embargo, cada vez que R se reinicia es necesario cargar los paquetes que serán utilizados en los análisis.
# En esta mentoría, usamos los paquetes "tidyverse" y "ggplot2"
# Instalar:
# install.packages("tidyverse") # remover el comentario (#) si necesita instalar
# install.packages("ggplot2")
# Cargar:
library("tidyverse")
En este ejemplo vamos a usar los datos del Estudio Nacional de Morbilidad y Mortalidad sobre Contaminación del Aire de Estados Unidos (National Morbidity and Mortality Air Pollution Study - NMMAPS).
Para fines didácticos los datos fueron restringidos para Chicago entre los años 1997 y 2000.
La matriz está en formato .csv y hospedada en un directorio online. Basta seguir el código para importar automáticamente.
chic <- readr::read_csv("https://avilaf.github.io/dados/chicago-nmmaps-custom.csv")
## Rows: 1461 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): city, season, month
## dbl (6): temp, o3, dewpoint, pm10, yday, year
## date (1): date
##
## ℹ 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.
# al usar "::namespace" (no es necesario cargar el paquete)
# es una función interesante cuando usamos muchos paquetes en un único script
# o un paquete es utilizado solamente para una función puntual
tibble::glimpse(chic) # para transponer y visualizar los datos
## Rows: 1,461
## Columns: 10
## $ city <chr> "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic…
## $ date <date> 1997-01-01, 1997-01-02, 1997-01-03, 1997-01-04, 1997-01-05, …
## $ temp <dbl> 36.0, 45.0, 40.0, 51.5, 27.0, 17.0, 16.0, 19.0, 26.0, 16.0, 1…
## $ o3 <dbl> 5.659256, 5.525417, 6.288548, 7.537758, 20.760798, 14.940874,…
## $ dewpoint <dbl> 37.500, 47.250, 38.000, 45.500, 11.250, 5.750, 7.000, 17.750,…
## $ pm10 <dbl> 13.052268, 41.948600, 27.041751, 25.072573, 15.343121, 9.3646…
## $ season <chr> "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "…
## $ yday <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18…
## $ month <chr> "Jan", "Jan", "Jan", "Jan", "Jan", "Jan", "Jan", "Jan", "Jan"…
## $ year <dbl> 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1…
class(chic) # ¿cuál es la clase del objeto "chic"?
## [1] "spec_tbl_df" "tbl_df" "tbl" "data.frame"
head(chic, 10) # visualizar el encabezado
## # A tibble: 10 × 10
## city date temp o3 dewpoint pm10 season yday month year
## <chr> <date> <dbl> <dbl> <dbl> <dbl> <chr> <dbl> <chr> <dbl>
## 1 chic 1997-01-01 36 5.66 37.5 13.1 Winter 1 Jan 1997
## 2 chic 1997-01-02 45 5.53 47.2 41.9 Winter 2 Jan 1997
## 3 chic 1997-01-03 40 6.29 38 27.0 Winter 3 Jan 1997
## 4 chic 1997-01-04 51.5 7.54 45.5 25.1 Winter 4 Jan 1997
## 5 chic 1997-01-05 27 20.8 11.2 15.3 Winter 5 Jan 1997
## 6 chic 1997-01-06 17 14.9 5.75 9.36 Winter 6 Jan 1997
## 7 chic 1997-01-07 16 11.9 7 20.2 Winter 7 Jan 1997
## 8 chic 1997-01-08 19 8.68 17.8 33.1 Winter 8 Jan 1997
## 9 chic 1997-01-09 26 13.4 24 12.1 Winter 9 Jan 1997
## 10 chic 1997-01-10 16 10.4 5.38 24.8 Winter 10 Jan 1997
# Note que tenemos muchos tipos de variables: categóricas, numéricas, discretas, continuas...
Antes de continuar…
El ggplot2 usa una sintaxis de capas que permite construir gráficos de forma incremental y modular. Cada capa añade un elemento al gráfico, como los datos, mapeos estéticos (colores, tamaños, etc.) y geometrías (puntos, barras, líneas, etc.). Esto hace el código más legible y fácil de modificar.
1 - Data: Los datos brutos que desea graficar.
2 - Geometries ‘geom_’: Las formas geométricas que representarán los datos.
3 - Aesthetics ‘aes()’: Estética de los objetos geométricos y estadísticos, como posición, color, tamaño, forma y transparencia
4 - Scales ‘scale_’: Relacionar los datos con las dimensiones estéticas, como rango de datos para ancho del gráfico o valores de factor para colores.
5 - Statistical transformations ‘stat_’: Resumir estadísticamente los datos, como calcular cuantiles, curvas ajustadas y sumas.
6 - Coordinate system ‘coord_’: Transformación usada para mapear coordenadas de datos en el espacio de graficación de datos.
7 - Facets ‘facet_’: La disposición de los datos en una grilla de gráficos.
8 - Visual themes ‘theme()’: Los patrones visuales generales de un gráfico, como fondo, grillas, ejes, fuente predeterminada, tamaños y colores.
# el primer paso es definir el conjunto de datos (data) y los ejes
# en la función siguiente tenemos los datos + argumento 'aes' posicionales (x e y)
ggplot(data = chic,
aes(x = date,
y = temp))
Note que no fue definida una capa con la graficación de los datos propiamente dichos.
# también es posible atribuir la graficación a un ggobject ('g'<-)
(g <- ggplot(chic, aes(x = date, y = temp))) # base
# y usar ese objeto para agregar capas en la graficación:
g + geom_point() # gráfico de dispersión de puntos
g + geom_line() # gráfico de líneas
g + geom_line() + geom_point() # líneas y puntos
Podemos hacer algunas ediciones estéticas en la propiedad “geom”, como alterar colores y formas.
# para alterar los colores:
g + geom_point(color = "firebrick",
shape = "diamond",
size = 2)
# Para más opciones de colores:
# http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf
# paletas de colores: RColorBrewer::display.brewer.all()
# RColorBrewer::brewer.pal(n = 3, name = "Set1")
# con superposición de capas es solo mantener el patrón:
g + geom_point(color = "firebrick",
shape = "diamond",
size = 2) +
geom_line(color = "firebrick",
linetype = "dotted",
size = .3)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Ajustar el tema también altera el visual del gráfico. Existen muchas opciones de temas disponibles.
# ajustar el tema para bw
theme_set(theme_bw())
g + geom_point(color = "firebrick")
Existen algunos paquetes con temas listos, como “ggthemes” y “hrbrthemes”.
Además, cada capa puede utilizar un color independiente.
# cambiar el color de las líneas y puntos:
ggplot(chic, aes(x = date, y = o3)) +
geom_line(color = "gray") +
geom_point(color = "darkorange2") +
labs(x = "Año", y = "Ozono")
# Dos grafías diferentes para los mismos resultados:
# 1
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)")
# 2
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
xlab("Año") +
ylab("Temperatura (°F)")
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año",
y = expression
(paste("Temperatura (", degree ~ F, ")"^"(El ejemplo es norteamericano, por eso no usamos grados Celsius!)")))
# dentro de 'theme()'
# modificar el elemento 'axis.title = ' o 'axis.title.x' y 'axis.title.y'
# dentro de 'element_text = ':
# size
# color
# face (bold, italic, bold.italic)
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(axis.title = element_text(size = 15, color = "firebrick",
face = "italic"))
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(axis.title.x = element_text(color = "sienna", size = 15),
axis.title.y = element_text(color = "orangered", size = 15))
# ('axis.title = ' + 'axis.title.y')
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(axis.title = element_text(color = "sienna", size = 15, face = "bold"),
axis.title.y = element_text(face = "bold.italic"))
Esta parte es similar al tema anterior, pero con el argumento ‘axis.text’ o ‘axis.text.x’ y ‘axis.text.y’
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (ºF)") +
theme(axis.text = element_text(color = "dodgerblue", size = 12),
axis.text.x = element_text(face = "italic"))
# 'angle' dentro de 'theme(axis.text = (angle = ))'
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(axis.text.x = element_text(angle = 50, vjust = 1, hjust = 1, size = 12))
# argumento labs()
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = NULL, y = "")
# Observe que NULL remueve el elemento (similarmente a element_blank()) mientras que comillas vacías "" mantendrán el espaciado para el título del eje y simplemente no imprimirán nada.
# con la capa theme()
# argumento vjust (alineación vertical)
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(axis.title.x = element_text(vjust = 0, size = 15),
axis.title.y = element_text(vjust = 2, size = 15))
“top”, “right”, “bottom” y “left” son argumentos que pueden ser usados en la función “theme()” del paquete ggplot2 para controlar la posición de los títulos, etiquetas y leyendas en un gráfico. Específicamente:
Los argumentos están dispuestos en orden top, right, bottom, left es decir: margin(t, r, b, l). Para recordar esta secuencia usamos la palabra t-r-oub-l-e.
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(axis.title.x = element_text(margin = margin(t = 10), size = 15),
axis.title.y = element_text(margin = margin(r = 10), size = 15))
Con subsetting
# 'subsetting': (realiza un subconjunto de los datos primero)
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
ylim(c(0, 50))
## Warning: Removed 777 rows containing missing values or values outside the scale range
## (`geom_point()`).
Otra opción (zooming):
# zooming: (sin espacio)
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
coord_cartesian(ylim = c(0, 50))
Un ejemplo con gráfico boxplot:
Opción subsetting
# zoom
ggplot(chic, aes(x = factor(year), y = temp)) +
geom_boxplot(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
coord_cartesian(ylim = c(0, 50))
Otra opción (zooming):
# subset (recorta los datos antes de la graficación)
ggplot(chic, aes(x = factor(year), y = temp)) +
geom_boxplot(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
ylim(c(0, 50))
## Warning: Removed 777 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
g +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
ggtitle("Temperaturas en Chicago")
Para agregar más argumentos use la función labs()
# labs() Para agregar más argumentos:
g +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)",
title = "Temperaturas en Chicago",
subtitle = "Patrón estacional de temperaturas diarias de 1997 a 2001",
caption = "Datos: NMMAPS",
tag = "Fig. 1")
La función theme() funciona para: plot.subtitle, plot.caption, plot.caption, legend.title, legend.text, y axis.title y axis.text
g +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)",
title = "Temperaturas en Chicago") +
theme(plot.title = element_text(face = "bold",
margin = margin(10, 0, 10, 0),
size = 14))
Aquí usamos la función hjust()
# hjust
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = NULL,
title = "Temperaturas en Chicago",
caption = "Datos: NMMAPS") +
theme(plot.title = element_text(hjust = 1, size = 16, face = "bold.italic"))
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
ggtitle("Temperaturas en Chicago\nde 1997 a 2001") +
theme(plot.title = element_text(lineheight = .8, size = 16))
Una opción para atribuir leyendas es el argumento color()
# color = season
ggplot(chic,
aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)")
Puede ser realizado con la función theme() definida como theme(legend.position = “none”)
ggplot(chic,
aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.position = "none")
# Sin ninguna leyenda
Aquí vamos a remover la leyenda para los colores y mantener la leyenda para las formas ajustando guides(color = “none”)
ggplot(chic,
aes(x = date, y = temp,
color = season, shape = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
guides(color = "none")
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.title = element_blank())
Tenemos algunas opciones:
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.position = "top")
También es posible posicionar la leyenda dentro del gráfico
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)",
color = NULL) +
theme(legend.position.inside = c(.15, .15),
legend.background = element_rect(fill = "transparent"))
En el siguiente ejemplo dejamos la leyenda en dirección horizontal
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.position = "inside",
legend.position.inside = c(.5, .97),
legend.direction = "horizontal",
legend.background = element_rect(fill = "transparent"))
Para alterar el estilo del título de la leyenda agregamos el argumento legend.title en theme()
# theme(legend.title = ())
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = "bold"))
Además es posible cambiar el texto del título de la leyenda
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)",
color = "Estaciones\nindicadas\npor colores:") +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = "bold"))
# aquí \n es usado para quiebre de texto
# determinar el orden de los niveles antes de la graficación
chic$season <-
factor(chic$season,
levels = c("Winter", "Spring", "Summer", "Autumn"))
# graficar
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)")
En caso de que quiera definir colores específicos para los niveles.
# scale_color_discrete()
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
scale_color_discrete(
name = "Estaciones:",
labels = c("Dic-Feb", "Mar-May", "Jun-Ago", "Sep-Nov" )
) +
theme(legend.background = element_rect(fill = "transparent"),
legend.title = element_text(color = "chocolate",
size = 14,
face = 2)
)
Como opción estética, puede poner colores de relleno en los ítems de la leyenda
# legend.key()
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.key = element_rect(fill = "darkgoldenrod1"),
legend.title = element_text(color = "chocolate",
size = 14, face = 2)) +
scale_color_discrete("Estaciones:")
O remover el relleno
# sin relleno:
# fill = NA or fill = "transparent"
# alterar el tamaño de los símbolos de la leyenda:
ggplot(chic, aes(x = date, y = temp, color = season)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)") +
theme(legend.key = element_rect(fill = NA),
legend.title = element_text(color = "chocolate",
size = 14, face = 2)) +
scale_color_discrete("Estaciones:") +
guides(color = guide_legend(override.aes = list(size = 6)))
Cuando estamos mapeando una variable continua, ggplot por defecto determina un gradiente
ggplot(chic,
aes(x = date, y = temp, color = temp)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)", color = "Temperatura (°F)")
Pero podemos forzar la leyenda a mostrar valores discretos con guide_legend()
ggplot(chic,
aes(x = date, y = temp, color = temp)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)", color = "Temperatura (°F)") +
guides(color = guide_legend())
También podemos limitar las escalas
ggplot(chic,
aes(x = date, y = temp, color = temp)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)", color = "Temperatura (°F)") +
guides(color = guide_bins())
O utilizar una escala de colores discretas:
ggplot(chic,
aes(x = date, y = temp, color = temp)) +
geom_point() +
labs(x = "Año", y = "Temperatura (°F)", color = "Temperatura (°F)") +
guides(color = guide_colorsteps())
Fondos y líneas pueden ser alterados dentro de la función theme()
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "#1D8565", size = 2) +
labs(x = "Año", y = "Temperatura (°F)") +
theme(panel.background = element_rect(
fill = "#64D2AA", color = "#64D2AA", linewidth = 2)
)
Observe que el color verdadero - el contorno del fondo del panel - no va a cambiar en este ejemplo, aún cuando lo hayamos especificado. Esto ocurre porque hay una capa encima de panel.background, o sea, panel.border
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "#1D8565", size = 2) +
labs(x = "Año", y = "Temperatura (°F)") +
theme(panel.border = element_rect(
fill = "#64D2AA99", color = "#64D2AA", size = 2)
)
## Warning: The `size` argument of `element_rect()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Para alterar las líneas usamos panel.grid() o, para cada conjunto de líneas separadamente: panel.grid.major() y panel.grid.minor()
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(panel.grid.major = element_line(color = "gray10", linewidth = .5),
panel.grid.minor = element_line(color = "gray70", linewidth = .25))
Podemos también detallar más
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(panel.grid.major = element_line(size = .5, linetype = "dashed"),
panel.grid.minor = element_line(size = .25, linetype = "dotted"),
panel.grid.major.x = element_line(color = "red1"),
panel.grid.major.y = element_line(color = "blue1"),
panel.grid.minor.x = element_line(color = "red4"),
panel.grid.minor.y = element_line(color = "blue4"))
## Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Podemos también remover las líneas
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(panel.grid.minor = element_blank())
Todas las líneas
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (ºF)") +
theme(panel.grid = element_blank())
# o theme_minimal()
Podemos modificar con panel.background() y plot.backgroun()
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Ano", y = "Temperatura (°F)") +
theme(panel.background = element_rect(fill = NA),
plot.background = element_rect(fill = "gray60",
color = "gray30", size = 2))
Un ejemplo más
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Año", y = "Temperatura (°F)") +
theme(plot.background = element_rect(fill = "gray60"),
plot.margin = margin(t = 1, r = 3, b = 1, l = 8, unit = "cm"))
Ahora que conoces ggplot puedes aventurarte un poco y practicar algunos comandos con los ejercicios de esta etapa.
Una vez corregidos los ejercicios con la clase, trabajaremos con gráficos interactivos.
Espero que este material haya ayudado de alguna forma y quedo a disposición para aclarar lo que sea necesario.
Dra. Fernanda Rodrigues de Avila