Gráficas con ggplot2

Parte 1: Fundamentos de graficación en R

Autores

Rodrigo Zepeda-Tello y Rossana Torres

Última actualización

October 7, 2022

Resumen
Mostramos cómo funciona ggplot2 para elaborar gráficas de puntos, de barras y de trayectorias. Utilizamos funciones de suavizamiento y algunas opciones de personalización mediante theme.
Note

Los datos están disponibles en el Github y en Dropbox

Warning

Si aún no cuentas con una instalación de ggplot2 dentro de R ve a la sección de instalación de paquetes o bien corre la siguiente instrucción:

install.packages("ggplot2")

1 ¿Qué es ggplot2?

R cuenta con su propia forma de hacer gráficas mediante el comando plot. Sin embargo, las gráficas que puedes hacer con plot son, salvo en el caso de regresiones, mucho más sencillas que las producidas por el paquete ggplot. Dicho paquete fue desarrollado inicialmente por Hadley Wickham y actualmente continúa en desarrollo por más de 198 colaboradores distintos. Por su belleza y facilidad, nosotros nos enfocaremos en gráficas con ggplot2.

Note

Algunas de las referencias que vale la pena tengas en mente para graficar con ggplot2 son:

Wickham, Hadley, and Garrett Grolemund. 2016. R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. " O’Reilly Media, Inc.".
Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.

ggplot2 es el mejor paquete para graficar.

Aprovecharemos para instalar dos paquetes que se encargan de leer bases de datos así como uno que usaremos más adelante para suavizar tendencias:

install.packages("readxl")    #Para leer archivos de excel
install.packages("readr")     #Para leer archivos en csv 
install.packages("ggformula") #Para suavizar datos en gráficas (splines)

(No olvides limpiar todo tu ambiente de R con rm(list = ls()) antes de iniciar; tampoco olvides que estaremos trabajando un nuevo script con Ctrl+Shift+N si estás en RStudio o File > New File > RScript).

Para ello, llama al paquete utilizando el comando library:

#Librería para graficar
library(ggplot2)

#Librería para leer los datos en csv
library(readr)

Hadley Wickham, el creador de ggplot2.

ggplot trabaja con tibbles; los tibbles (pronunciados tíblz) son el formato preferido para tener tablas de datos. Probemos leer los datos de diabetes los cuales consisten en una muestra obtenida en Virginia EEUU en población afroamericana con el objetivo de determinar las prevalencias de obesidad, diabetes y otros factores de riesgo cardiovascular y proviene de la colección de bases de datos de bioestadística de Vanderbilt.

Para ello, leeremos el archivo.

Hay dos formas:

  1. Si estás en RStudio puedes irte al panel derecho superior e Import Dataset > From text (readr) Eso te escribirá un código como el siguiente:
setwd("tu/directorio")
datos_diabetes <- read_csv("datasets/diabetes.csv")
  1. la segunda forma es aprendiendo directamente que el comando es read_csv seguido del nombre del archivo. ¡Siempre puedes guardar cualquier archivo de Excel en .csv y leerlo con R así!

Para guardar un archivo de Excel en formato csv puedes utilizar F12 (Shift+Command+S en Mac) o bien, ir a File > Save As... y luego seleccionar File Format.

La base de datos se ve más o menos así:

id chol stab.glu hdl ratio glyhb location age gender height weight frame bp.1s bp.1d bp.2s bp.2d waist hip time.ppn
1000 203 82 56 3.6 4.31 Buckingham 46 female 62 121 medium 118 59 NA NA 29 38 720
1001 165 97 24 6.9 4.44 Buckingham 29 female 64 218 large 112 68 NA NA 46 48 360
1002 228 92 37 6.2 4.64 Buckingham 58 female 61 256 large 190 92 185 92 49 57 180
1003 78 93 12 6.5 4.63 Buckingham 67 male 67 119 large 110 50 NA NA 33 38 480
1005 249 90 28 8.9 7.72 Buckingham 64 male 68 183 medium 138 80 NA NA 44 41 300
1008 248 94 69 3.6 4.81 Buckingham 34 male 71 190 large 132 86 NA NA 36 42 195

Por ahora nos enfocaremos en los niveles de colesterol chol y la edad age de las personas (cada id es un individuo distinto).

2 Gráfica de puntos

Para graficar el comando ggplot(tus_datos) coloca la capa inicial el cual es un lienzo vacío:

#Creación de un lienzo de puntos
ggplot(datos_diabetes)

Probemos agregar puntos con geom_point especificando mediante el comando aes las variables de la base que vamos a graficar en cada uno de los ejes.

#Gráfica de puntos
ggplot(datos_diabetes) + 
  geom_point(aes(x = age, y = chol))
Warning: Removed 1 rows containing missing values (geom_point).

Warning

Te darás cuenta que R arroja un warning indicando que quitó una fila por valores faltantes. Esto es porque en la base de datos el id = 1281 no cuenta con mediciones de colesterol por lo cual esa fila se remueve de la gráfica (de otra forma ¿cómo graficar algo que no medimos?).

¡No olvides el +! Podemos agregar color a los geom_point con el comando color:

#Gráfica de la base de datos de diabetes
ggplot(datos_diabetes) + 
  geom_point(aes(x = age, y = chol), color = "tomato3")

Una lista completa de los colores posibles está aquí.. También puedes usar colores RGB o en formato HEX. Por ejemplo el Manual de Identidad Gráfica del Gobierno de México establece que el tono de verde institucional es el #235B4E el cual se puede colocar tal cual.

#Gráfica de la base de datos de diabetes
ggplot(datos_diabetes) + 
  geom_point(aes(x = age, y = chol), color = "#235B4E")

Podemos cambiar los títulos (title) de los ejes, el subtítulo (subtitle) y el pie de figura (caption) mediante labs:

#Agregamos etiquetas
ggplot(datos_diabetes) + 
  geom_point(aes(x = age, y = chol), color = "#235B4E") +
  labs(
    x        = "Edad (años)",
    y        = "Niveles de colesterol (mg/dl)",
    title    = "Edad contra niveles de colesterol en la población afroamericana de Virginia",
    subtitle = "University of Virginia School of Medicine.",
    caption  = "Fuente: https://hbiostat.org/data/"
  )

Las gráficas cuentan con varios temas (themes) con diseños predefinidos para cambiar su imagen. Prueba los distintos: theme_classic, theme_bw, theme_gray, theme_linedraw, theme_light, theme_minimal, theme_dark y theme_void.1

  • 1 Puedes tener aún más temas si descargas el paquete (ggthemes)[https://yutannihilation.github.io/allYourFigureAreBelongToUs/ggthemes/].

  • ggplot(datos_diabetes) + 
      geom_point(aes(x = age, y = chol), color = "#235B4E") +
      labs(
        x        = "Edad (años)",
        y        = "Niveles de colesterol (mg/dl)",
        title    = "Edad contra niveles de colesterol en la población afroamericana de Virginia",
        subtitle = "University of Virginia School of Medicine.",
        caption  = "Fuente: https://hbiostat.org/data/"
      ) + 
      theme_minimal() #Agrega un tema

    Para incrementar el tamaño de los puntos podemos usar el comando size dentro de geom_point:

    #Agregamos etiquetas
    ggplot(datos_diabetes) + 
      geom_point(aes(x = age, y = chol), color = "#235B4E", size = 2.5) +
      labs(
        x        = "Edad (años)",
        y        = "Niveles de colesterol (mg/dl)",
        title    = "Edad contra niveles de colesterol en la población afroamericana de Virginia",
        subtitle = "University of Virginia School of Medicine.",
        caption  = "Fuente: https://hbiostat.org/data/"
      ) + 
      theme_minimal() #Agrega un tema

    Y si se empalman podemos hacer unos más transparentes que otros usando alpha

    #Agregamos etiquetas
    ggplot(datos_diabetes) + 
      geom_point(aes(x = age, y = chol), color = "#235B4E", 
                 size = 2.5, alpha = 0.5) +
      labs(
        x        = "Edad (años)",
        y        = "Niveles de colesterol (mg/dl)",
        title    = "Edad contra niveles de colesterol en la población afroamericana de Virginia",
        subtitle = "University of Virginia School of Medicine.",
        caption  = "Fuente: https://hbiostat.org/data/"
      ) + 
      theme_minimal()

    Finalmente, para guardar tu gráfica escribe ggsave con el nombre (sea en pdf o en png y las medidas de ancho (width) y alto (height) deseadas en pulgadas)

    #width: ancho
    #height: alto
    ggsave("Edad_vs_colesterol.pdf", width = 8, height = 5)

    El código completo para la gráfica es entonces:

    #Librerías a usar
    library(readr)   #Leer archivos .csv
    library(ggplot2) #Graficar
    
    #Lectura de la base de datos de Virginia
    datos_diabetes <- read_csv("datasets/diabetes.csv")
    
    #Realización de la gráfica
    ggplot(datos_diabetes) + 
      geom_point(aes(x = age, y = chol), color = "#235B4E", 
                 size = 2.5, alpha = 0.5) +
      labs(
        x        = "Edad (años)",
        y        = "Niveles de colesterol (mg/dl)",
        title    = "Edad contra niveles de colesterol en la población afroamericana de Virginia",
        subtitle = "University of Virginia School of Medicine.",
        caption  = "Fuente: https://hbiostat.org/data/"
      ) + 
      theme_minimal()
    
    #La guardamos en formato de 8 x 5 pulgadas
    ggsave("Edad_vs_colesterol.pdf", width = 8, height = 5)

    2.1 Versión con esquisse

    La librería esquisse provee una interfaz más amigable para generar las gráficas y puede serte de utilidad. ¡Veámosla!

    library("esquisse") #Llamamos a la librería
    set_i18n("es")      #Le decimos que opere en idioma español
    esquisser()         #Corremos el código!

    Una vez hayas empezado a correr el código obtendrás una pantalla como esta:

    Cuando comiensas a usar esquisse se abre una pantalla

    En ella selecciona la base de datos que estamos usando (datos_diabetes) y selecciona Importar Datos

    Selecciona tu base de datos

    Dentro de apariencia establece el color adecuado (#235B4E) y el tema minimal.

    Selecciona tu base de datos

    En Etiquetas & Título elige los títulos adecuados

    Selecciona tu base de datos

    En Opciones de Gráfico cambia el tamaño de los puntos a 2.5

    Selecciona tu base de datos

    Finalmente, ve a código y copia en tu script el código correspondiente

    Selecciona tu base de datos

    Nota que no es exactamente igual al código de la sección anterior pero es una buena aproximación para tener una gráfica con la cual empezar.

    2.2 R Básico

    1. Imita la siguiente gráfica de altura (height) contra peso (weight) de la base de datos de diabetes. En esta usamos otro tema distinto (classic) y los puntos son naranjas (orange) de tamaño \(0.5\):

    1. Dentro del aes puedes también aplicar funciones a las variables. Por ejemplo si queremos graficar índice de masa corporal (\(\text{peso (kg)} / (\text{altura (m)}^2)\)) podemos calcular el IMC en el mismo aes haciendo: ... aes(x = (weight * 0.453592) /(height * 0.0254)^2, ...) .... Donde el factor 0.453592 es para convertir de libras a kilos y 0.0254 de pulgadas a metros. Grafica en el eje x el índice de masa corporal (IMC) y en y el radio de colesterol definido como el nivel de colesterol chol entre el colesterol de alta densidad hdl. Obtén una gráfica como esta de color púrpura (purple), tamaño 0.5 y tema bw:

    1. Descarga y lee las bases de datasets/IMSS_BCG_2019.csv y datasets/IMSS_BCG_2020.csv las cuales contiene información de las dosis aplicadas de B.C.G (Vacuna contra la tuberculosis) contra los casos de tuberculosis detectados en el IMSS por delegación en el mismo año (2019 y 2020 respectivamente). Replica las siguientes dos gráficas con color deepskyblue3, size = 1.5. Para ello requieres instalar la librería ggrepel y usar geom_text_repel. Tu código debe tener una estructura similar a esto:
    #Lectura de datos
    #...
    
    #Gráfica
    ggplot(...) + 
      geom_point(...) + 
      geom_text_repel(aes(x = `Dosis BCG`,                     #Así se ponen las
                          y = `Casos detectados tuberculosis`, #etiquetas
                          label = Del), size = 2) +            #de entidad
      labs(...) +
      ...

    2.3 R Intermedio

    En la base de diabetes, utiliza scale_y_continuous en particular la opción de sec.axis para agregar un segundo eje y del lado derecho donde la altura esté en metros (no pulgadas). Repite el proceso con scale_x_continuous para agregar un eje x en la parte superior con el peso en kilogramos.

    3 Gráficas de columnas (barras)

    3.1 Una tranquila (BCG en IMSS)

    La base de datos IMSS_BCG_2019.csv contiene las dosis de B.C.G que se han aplicado en el IMSS por Delegación. Generaremos una gráfica de barras con ellas. Para eso leemos la base:

    bcg <- read_csv("datasets/IMSS_BCG_2020.csv")

    Ésta se ve más o menos así:

    Del Dosis BCG Casos detectados tuberculosis
    AGS 7945 1733
    BC 10984 17618
    BCS 4064 2485
    CAM 2242 170
    COAH 17850 5366
    COL 2326 896

    Graficaremos la columna de Dosis BCG por delegación Del. Para ello ponemos nuestro lienzo con ggplot y agregamos un geom_col:

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`))

    Nota que aquí a la variable hubo que llamarle Dosis BCG con los acentos graves `

    Esto porque de otra forma genera error pues piensa que Dosis y BCG son dos palabras distintas:

    ggplot(bcg) +
      geom_col(aes(x = Del, y = Dosis BCG))
    Error: <text>:2:35: unexpected symbol
    1: ggplot(bcg) +
    2:   geom_col(aes(x = Del, y = Dosis BCG
                                         ^

    Para darle color usaremos tanto color como fill. Nota que el color cambia la orilla:

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`), color = "red")

    mientras que fill cambia el contenido:

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`), color = "red",
               fill = "blue")

    Cambiaré los colores por unos más bellos, y agregaré título y etiquetas a los ejes. En este caso no deseo etiqueta en el eje x por lo cual lo dejaré como comillas vacías: "".

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`), 
               color = "red", fill = "blue") +
      labs(
        x        = "",
        y        = "Dosis BCG aplicadas",
        title    = "Dosis de B.C.G. aplicadas en el IMSS",
        subtitle = "Año 2020"
      )

    Voy a agregar comas a los números del eje y con scale_y_continuous. El scale_y_continuous manipula lo que sea del eje y. En mi caso deseo sólo que los números les ponga comas (otra opción es para porcentajes usar percent en lugar de comma):

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`), 
               color = "red", fill = "blue") +
      labs(
        x        = "",
        y        = "Dosis BCG aplicadas",
        title    = "Dosis de B.C.G. aplicadas en el IMSS",
        subtitle = "Año 2020"
      ) +
      scale_y_continuous(labels = scales::comma)

    Finalmente usaremos theme para cambiar la orientación de las etiquetas del eje x a vertical (i.e con un ángulo de 90º) para que se vean mejor:

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`), 
               color = "red", fill = "blue") +
      labs(
        x        = "",
        y        = "Dosis BCG aplicadas",
        title    = "Dosis de B.C.G. aplicadas en el IMSS",
        subtitle = "Año 2020"
      ) +
      scale_y_continuous(labels = scales::comma) +
      theme(axis.text.x = element_text(angle = 90, 
                                       hjust = 1, vjust = 0.5))

    Seguro en este punto te estarás preguntando ¿y cómo Rod sabe cuál es el código para cada opción? La respuesta es que pasé mucho tiempo (¡demasiado!) en Google encontrándola pero que una vez encontré el cómo rotar las etiquetas guardé el código en mi cuaderno y ahora cada que se ofrece ¡ya sé qué poner!

    Finalmente agregaré colores más lindos y un theme_linedraw

    ggplot(bcg) +
      geom_col(aes(x = Del, y = `Dosis BCG`), 
               color = "black", fill = "tomato3") +
      labs(
        x        = "",
        y        = "Dosis BCG aplicadas",
        title    = "Dosis de B.C.G. aplicadas en el IMSS",
        subtitle = "Año 2020"
      ) +
      scale_y_continuous(labels = scales::comma) +
      theme_linedraw() +  #Nota que se agrega antes porque
                          #si se pone después desconfigura la rotada
      theme(axis.text.x = element_text(angle = 90, 
                                       hjust = 1, vjust = 0.5)) 

    3.2 Ejercicio

    Utiliza la base de datos IMSS_BCG_2019.csv y genera la siguiente gráfica con color de la orilla white y relleno (fill) de color forestgreen. El tema es el bw y el texto del eje x está a 45 grados:

    3.4 Ejercicio

    1. El siguiente código genera una base de datos de nombre vacunacion con la información de cuántos niños menores de uno o dos años tienen el esquema completo de cuatro vacunas de acuerdo con las distintas Encuestas Nacionales de Salud ENSA/ENSANUT.
    Encuesta   <- rep(c("2000","2006","2012","2018-19","2021"), 2)
    vacperc    <- c(c(0.265, 0.784, 0.742, 0.199, 0.311), c(0.5, 0.847, 0.779, 0.353, 0.358))
    clase      <- c(rep("1 año cumplido", 5), rep("2 años cumplidos", 5))
    
    vacunacion           <- data.frame(Encuesta, vacperc, clase) 
    colnames(vacunacion) <- c("ENSANUT", "Porcentaje vacunado", "Edad de los niños")

    Corre el código tal cual y una vez lo hayas corrido, grafica los datos con columnas eligiendo colores y texto adecuados.

    1. Utiliza la base IMSS_BCG_2019.csv para realizar una gráfica de barras identica a la que sigue (el fill es deepskyblue4 y no tiene color). Para agregar los numeritos en las barras se usó geom_text con size = 2, hjust = 0, color = "white" y angle = 90. El tema es el bw.

    4 Histogramas con ggplot2

    4.1 Un histograma es una gráfica de barras especial

    El comando geom_histogram sirve para crear histogramas. Un histograma es un tipo de gráfico de barras que acumula en cada barra conteos de cuántos cayeron en ese sitio. Para entender mejor, veamos un ejemplo. Para ello copia el siguiente código el cual genera una base de datos expuesta a continuación:

    datos_histograma <- tibble(
      estaturas = c(1.42, 1.45, 1.65, 1.55, 1.32, 1.44, 1.50, 1.51, 1.62, 1.55)
    )
    estaturas
    1.42
    1.45
    1.65
    1.55
    1.32
    1.44
    1.50
    1.51
    1.62
    1.55

    Viendo la base de datos notamos que puede resumirse según fueron cayendo en distintos intervalos:

    Intervalo n
    1.3 - 1.4 1
    1.4 - 1.5 4
    1.5 - 1.6 3
    1.6 - 1.7 2

    Podemos elaborar fácilmente una gráfica de barras para ese conteo:

    donde, de nuevo, la altura de la barra corresponde al conteo de cuántos cayeron en ese intervalo.

    Podemos también hacer una gráfica de barras donde no pongamos el conteo absoluto sino el porcentaje (sabemos que hay 10 mediciones en total) y esto se vería así:

    Un histograma representa la misma idea que estas gráficas de barras de manera simplificada. Usando los datos asignados previamente puedo construir un histograma como sigue:

    ggplot(datos_histograma) +
      geom_histogram(aes(x = estaturas), color = "white",
                     breaks = c(1.3, 1.4, 1.5, 1.6, 1.7, 1.8))

    donde los breaks indican a R dónde hacer los cortes (volveremos más adelante).

    Si quisiéramos verlo como porcentaje y no cómo conteo basta con agregar una opción (muy específica que a nadie se le va a ocurrir sin googlearlo) de y = (..count..)/sum(..count..) en el aes como sigue:

    ggplot(datos_histograma) +
      geom_histogram(aes(x = estaturas, y = (..count..)/sum(..count..)), 
                     color = "white",
                     breaks = c(1.3, 1.4, 1.5, 1.6, 1.7, 1.8))

    ¡Hagamos entonces nuestro primer histograma!

    4.2 Histograma de colesterol

    Tomaremos de nuevo la base de diabetes que usamos en la sección anterior. Para ello la leemos:

    datos_diabetes <- read_csv("datasets/diabetes.csv")

    Para armar el histograma es sólo necesario especificar una variable en el aes:

    #Graficación de un histograma
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol))

    Date cuenta que solito R decide cuántas barras poner.

    Note

    Según Ioannidis histograma viene del griego histos (mástil) y gram-ma (algo escrito). Por lo que literalmente sería algo escrito en mástiles. A pesar de que éstos se atribuyen a Karl Pearson, los histogramas fueron inventados desde antes. Él fue quien les puso nombre.

    Para especificar el número de barras hay dos formas: utilizando el comando bins lo que le dice a R cuántas barras poner:

    #Graficación de un histograma con 50 barras
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol), bins = 50)

    O bien especificando el ancho de cada barra y dejando a R decidir:

    #Graficación con barras de ancho 10
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol), binwidth = 10)

    o bien especificando de dónde a dónde van los puntos de corte de cada barra:

    #Graficación con barras de ancho 10
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol), 
                     breaks = c(50, 100, 150, 200, 250, 300, 350))

    El comando fill cambia el color interno de las barras.

    #El comando fill cambia el color
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol), bins = 50, fill = "#cef0ff")

    Mientras que el comando color cambia el color del borde de la misma:

    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol), bins = 50, 
                     fill = "#cef0ff",  color = "#1D1B1B")

    FInalmente, podemos hacer que el histograma muestre no el número de casos totales en la base sino la proporción de los casos mediante y = ..density... La diferencia entre ..density.. y (..count..)/sum(..count..) es que `..density.. está hecho para que la suma de las áreas de los rectángulos dé \(1\) mientras que en (..count..)/sum(..count..) la suma de las alturas de los rectángulos es la que da \(1\).

    #..density.. nos da el % de casos de manera normalizada
    #para que los rectángulos sumen sus áreas a área 1
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), 
                     bins = 50, fill = "#cef0ff",  color = "#1D1B1B")

    Podemos agregar, además, una densidad kernel que nos dé una idea de cómo se ve la distribución ajustada. Como veremos más adelante, la densidad kernel (aunque puede ser manipulable) es más fácil que no nos dé errores de distribución incorrecta.

    #Gráfica de histograma con densidad kernel
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), 
                     bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol))

    Ojo ggplot2 funciona por capas por lo cual el orden en el que se agrega cada capa (geom) sí afecta el cómo se ve. Si ponemos el geom_density antes del geom_histogram nos queda la línea detrás del histograma:

    #Gráfica de histograma con densidad kernel
    ggplot(datos_diabetes) + 
      geom_density(aes(x = chol)) +
      geom_histogram(aes(x = chol, y = ..density..), 
                     bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B")  

    Continuando con la edición podemos cambiar los parámetros de color y size de la distribución para ajustar su color y tamaño. Así mismo, linetype nos da una línea discontinua:

    #Cambio de color y tipo de línea a la densidad
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), 
                     bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol), color = "deepskyblue4",
                   linetype = "dotted", size = 1)

    Finalmente, modificamos los temas:

    #Graficación con barras de ancho 0.05
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), 
                     bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol), color = "deepskyblue4",
                   linetype = "dotted", size = 1) +
      labs(
        x        = "Colesterol",
        y        = "",
        title    = "Distribución observada de los niveles de colesterol",
        subtitle = "Población afroamericana de Virginia"
      ) + 
      theme_bw()

    La función mean calcula la media de una columna dentro de una base de datos. Podemos calcular la media de la columna de chol dentro de datos_diabetes:

    #Media de la columna de colesterol
    #la opción na.rm = T es para no considerar los valores missing
    
    promedio_colesterol <- mean(datos_diabetes$chol) #No funciona pues tiene un missing
    promedio_colesterol
    [1] NA
    #Acá le decimos que ignore el missing con na.rm = T
    promedio_colesterol <- mean(datos_diabetes$chol, na.rm = T)
    promedio_colesterol
    [1] 207.8458

    Y agregamos una línea vertical a la gráfica exactamente en la media:

    #Agregamos indicadora del promedio
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol), color = "deepskyblue4",
                   linetype = "dotted", size = 1) +
      labs(
        x        = "Colesterol",
        y        = "",
        title    = "Distribución observada de los niveles de colesterol",
        subtitle = "Población afroamericana de Virginia"
      ) + 
      theme_bw() +
      geom_vline(aes(xintercept = promedio_colesterol))

    Podemos cambiar el color de la línea así como el tipo:

    #Agregamos indicadora del promedio
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol), color = "deepskyblue4",
                   linetype = "dotted", size = 1) +
      labs(
        x        = "Colesterol",
        y        = "",
        title    = "Distribución observada de los niveles de colesterol",
        subtitle = "Población afroamericana de Virginia"
      ) + 
      theme_bw() +
      geom_vline(aes(xintercept = promedio_colesterol),
                 color = "tomato3", linetype = "dashed", size = 1)

    Finalmente, podemos agregar una anotación junto a la media que nos indique que dicha es la media. Para ello usamos el comando annotate indicando que agregaremos un texto ("text") y las coordenadas del mismo.

    #Agregamos indicadora del promedio
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol), color = "deepskyblue4",
                   linetype = "dotted", size = 1) +
      labs(
        x        = "Colesterol",
        y        = "",
        title    = "Distribución observada de los niveles de colesterol",
        subtitle = "Población afroamericana de Virginia"
      ) + 
      theme_bw() +
      geom_vline(aes(xintercept = promedio_colesterol),
                 color = "tomato3", linetype = "dashed", size = 1) +
      annotate("label", x = promedio_colesterol, 
               y = 0.0001, label = "Media = 208", color = "tomato3")

    La función de scale_y_continuous permite agregar etiquetas al eje vertical (scale_x_continuous si fuera el horizontal). En este caso podemos usar porcentajes para mejor representar los datos:

    #Agregamos indicadora del promedio
    ggplot(datos_diabetes) + 
      geom_histogram(aes(x = chol, y = ..density..), bins = 50,
                     fill = "#cef0ff",  color = "#1D1B1B") + 
      geom_density(aes(x = chol), color = "deepskyblue4",
                   linetype = "dotted", size = 1) +
      labs(
        x        = "Colesterol",
        y        = "",
        title    = "Distribución observada de los niveles de colesterol",
        subtitle = "Población afroamericana de Virginia"
      ) + 
      theme_bw() +
      geom_vline(aes(xintercept = promedio_colesterol),
                 color = "tomato3", linetype = "dashed", size = 1) +
      annotate("label", x = promedio_colesterol, 
               y = 0.0001, label = "Media = 208",  color = "tomato3") +
      scale_y_continuous(labels = scales::percent)

    4.3 Ejercicios

    1. Utiliza la función quantile (con la opción na.rm = T) para calcular los cuantiles 0.975 y 0.025 y agrega dos líneas verticales a la gráfica anterior indicando los valores de los cuantiles junto con sus etiquetas:

    1. Imita la siguiente gráfica de altura en pulgadas (height) con color red donde se usó el comando fill para colorear el interior de la densidad en azul (deepskyblue4) y el tema theme_linedraw.

    Nota quizá necesites modificar la transparencia con alpha.

    1. Considera la siguiente base de datos:
    mis.datos <- data.frame(
      x = c(1.03, 1.24, 1.47, 1.52, 1.92, 1.93, 1.94, 1.95, 1.96, 1.97,
           1.98, 1.99, 2.72, 2.75, 2.78, 2.81, 2.84, 2.87, 2.90, 2.93,
           2.96, 2.99, 3.60, 3.64, 3.66, 3.72, 3.77, 3.88, 3.91, 4.14,
           4.54, 4.77, 4.81, 5.62)
    )

    Realiza un histograma de la variable x dentro de mis.datos con binwidth a 0.75:

    1. ¿Podemos concluir la forma de la distribución a partir del histograma? Es decir ¿está centrada?
    Tip

    Minitab tiene un blog sobre cuándo usar histogramas. ¿Puedes descubrir todos sus errores?

    1. Realiza el mismo histograma pero ahora con un ancho de banda de 1.2. ¿Y ahora?
    1. Considera la siguiente base de datos:
    mis.datos <- data.frame(
      A =  c(3.15, 5.46, 3.28, 4.20, 1.98, 2.28, 3.12, 4.10, 3.42, 3.91, 
             2.06, 5.53, 5.19, 2.39, 1.88, 3.43, 5.51, 2.54, 3.64, 4.33, 
             4.85, 5.56, 1.89, 4.84, 5.74, 3.22, 5.52, 1.84, 4.31, 2.01, 
             4.01, 5.31, 2.56, 5.11, 2.58, 4.43, 4.96, 1.90, 5.60, 1.92),
      B =  c(2.90, 5.21, 3.03, 3.95, 1.73, 2.03, 2.87, 3.85, 3.17, 3.66,
             1.81, 5.28, 4.94, 2.14, 1.63, 3.18, 5.26, 2.29, 3.39, 4.08,
             4.60, 5.31, 1.64, 4.59, 5.49, 2.97, 5.27, 1.59, 4.06, 1.76, 
             3.76, 5.06, 2.31, 4.86, 2.33, 4.18, 4.71, 1.65, 5.35, 1.67),
      C =  c(2.65, 4.96, 2.78, 3.70, 1.48, 1.78, 2.62, 3.60, 2.92, 3.41,
             1.56, 5.03, 4.69, 1.89, 1.38, 2.93, 5.01, 2.04, 3.14, 3.83,
             4.35, 5.06, 1.39, 4.34, 5.24, 2.72, 5.02, 1.34, 3.81, 1.51, 
             3.51, 4.81, 2.06, 4.61, 2.08, 3.93, 4.46, 1.4, 5.1, 1.42),
      D =  c(2.40, 4.71, 2.53, 3.45, 1.23, 1.53, 2.37, 3.35, 2.67, 3.16,
             1.31, 4.78, 4.44, 1.64, 1.13, 2.68, 4.76, 1.79, 2.89, 3.58,
             4.10, 4.81, 1.14, 4.09, 4.99, 2.47, 4.77, 1.09, 3.56, 1.26, 
             3.26, 4.56, 1.81, 4.36, 1.83, 3.68, 4.21, 1.15, 4.85, 1.17)
    )

    Grafica un histograma de las variables A, B, C y D de dicha base con un ancho de banda (binwidth) igual a 1:

    ¿Podemos concluir la forma de la distribución a partir del histograma? Es decir ¿hay distribuciones sesgadas a la izquierda, a la derecha, uniformes, centradas o con colas pesadas?

    Realiza el mismo histograma pero ahora con un ancho de banda de 0.25 ¿por qué hubo cambios? Analiza la base de datos (los valores en función de la columna A) y concluye.

    5 Gráficas de trayectorias

    En ggplot2 puedes graficar lo que quieras. Hasta puedes declarar tu amor. Este próximo 14 de febrero usa ggplot2.

    La base de datos casos_covid_agosto_2022.csv contiene datos sobre la cantidad de casos reportados en el Sistema Nacional de Vigilancia Epidemiológica (SINAVE) por covid, sospecha de covid u otra enfermedad respiratoria. Leamos la base:

    Grafiquemos la cantidad de casos totales en México como puntos

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") 

    podemos agregar una línea que una los puntos pero como hay tantos no se ve muy bien:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_line(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d") 

    podemos mejor usar la función geom_spline del paquete ggformula para usar una línea que se encargue de eliminar el ruido de los datos y descubrir la forma inherente:

    library(ggformula)
    
    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d") 

    nota que el suavizamiento ahora es mucho mejor. Podemos controlar el nivel de suavizamiento con los grados de libertad del spline df:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n, color = "df 900"), df = 900) +
      geom_spline(aes(x = FECHA_SINTOMAS, y = n, color = "df 45"), df = 45) +
      geom_spline(aes(x = FECHA_SINTOMAS, y = n, color = "df 20"), df = 15)  +
      geom_spline(aes(x = FECHA_SINTOMAS, y = n, color = "df 5"), df = 10) 

    Hay un equlibrio en el nivel de suavizamiento: poner demasiado poco rompe la forma df = 10 mientras que suavizamiento alto sigue la tendencia de los datos tal cual df = 900. Me quedaré con df = 45 porque me gusta cómo se ve a ese nivel.

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) 

    Lo que sigue es personalizar la gráfica poniendo los títulos, el tema y cambiando los ejes a tener notación con comas. Todo esto lo hemos hecho antes:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) +
      labs(
        x        = "",
        y        = "Casos incidentes",
        title    = "Enfermedades Respiratorias",
        subtitle = "Registros del Sistema Nacional de Vigilancia Epidemiológica (SINAVE)",
        caption  = "Datos Abiertos de la Dirección General de Epidemiología"
      ) +
      scale_y_continuous(labels = scales::label_comma())

    Agregaré un scale_x_date para elegir tener cortes en el eje x cada 6 meses y:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) +
      labs(
        x        = "",
        y        = "Casos incidentes",
        title    = "Enfermedades Respiratorias",
        subtitle = "Registros del Sistema Nacional de Vigilancia Epidemiológica (SINAVE)",
        caption  = "Datos Abiertos de la Dirección General de Epidemiología"
      ) +
      scale_y_continuous(labels = scales::label_comma()) +
      scale_x_date(date_breaks = "6 months", date_minor_breaks = "3 months",
                   date_labels = "%b/%Y") +
      theme_bw()

    Utilizaremos theme para realizar cambios a cada parte de la gráfica comenzando por cambiar el color de fondo:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) +
      labs(
        x        = "",
        y        = "Casos incidentes",
        title    = "Enfermedades Respiratorias",
        subtitle = "Registros del Sistema Nacional de Vigilancia Epidemiológica (SINAVE)",
        caption  = "Datos Abiertos de la Dirección General de Epidemiología"
      ) +
      scale_y_continuous(labels = scales::label_comma()) +
      scale_x_date(date_breaks = "6 months", date_minor_breaks = "3 months",
                   date_labels = "%b/%Y") +
      theme_classic() +
      theme(
        panel.background = element_rect(fill = "#320d3e")
      )

    theme nos permite cambiar las características de cualquier parte del plot. Por ejemplo haciendo una mezcla de colores horribles podemos hacer la gráfica más fea que hayas visto:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#f162ff") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) +
      labs(
        x        = "",
        y        = "Casos incidentes",
        title    = "Enfermedades Respiratorias",
        subtitle = "Registros del Sistema Nacional de Vigilancia Epidemiológica (SINAVE)",
        caption  = "Datos Abiertos de la Dirección General de Epidemiología"
      ) +
      scale_y_continuous(labels = scales::label_comma()) +
      scale_x_date(date_breaks = "6 months", date_minor_breaks = "3 months",
                   date_labels = "%b/%Y") +
      theme_classic() +
      theme(
        panel.background = element_rect(fill = "#320d3e"),                  #Fondo de la gráfica
        plot.background  = element_rect(fill = "green"),                    #Fondo de los títulos
        axis.text.x      = element_text(color = "red", size = 5),           #Letras de los ejes
        axis.text.y      = element_text(color = "forestgreen"),             #Letras de los ejes
        axis.ticks       = element_line(color = "red", size = 2),           #Los | abajo de los ejes
        axis.line.x      = element_line(color = "orange", size = 2),        #Línea del eje
        axis.line.y      = element_line(color = "yellow", size = 3),        #Otra línea del eje
        plot.title       = element_text(color = "blue", size = 20),         #Título
        plot.subtitle    = element_text(color = "gray25", face = "italic"), #Subtítulo
        plot.caption     = element_text(color = "purple"),                  #Caption
        axis.title.y     = element_text(color = "pink"),                    #Lo que dice el eje y
      )

    La cual podemos arreglar rápidamente con una mezcla amigable de colores:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#007677") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) +
      labs(
        x        = "",
        y        = "Casos incidentes",
        title    = "Enfermedades Respiratorias",
        subtitle = "Registros del Sistema Nacional de Vigilancia Epidemiológica (SINAVE)",
        caption  = "Datos Abiertos de la Dirección General de Epidemiología"
      ) +
      scale_y_continuous(labels = scales::label_comma()) +
      scale_x_date(date_breaks = "6 months", date_minor_breaks = "3 months",
                   date_labels = "%b/%Y") +
      theme_classic() +
      theme(
        panel.background = element_rect(fill = "#003f5c"),                   #Fondo de la gráfica
        plot.background  = element_rect(fill = "#003f5c", color = "black"),  #Fondo de los títulos
        axis.text.x      = element_text(color = "gray75"),                   #Letras de los ejes
        axis.text.y      = element_text(color = "gray75"),                   #Letras de los ejes
        axis.ticks       = element_line(color = "gray75"),                   #Los | abajo de los ejes
        axis.line.x      = element_line(color = "gray75"),                   #Línea del eje
        axis.line.y      = element_line(color = "gray75"),                   #Otra línea del eje
        plot.title       = element_text(color = "gray75", size = 25),        #Título
        plot.subtitle    = element_text(color = "#62a757", face = "italic"), #Subtítulo
        plot.caption     = element_text(color = "#62a757"),                  #Caption
        axis.title.y     = element_text(color = "gray75"),                   #Lo que dice el eje y
      )

    y finalmente podemos agregar anotaciones:

    ggplot(sinave) + 
      geom_point(aes(x = FECHA_SINTOMAS, y = n), color = "#007677") + 
      geom_spline(aes(x = FECHA_SINTOMAS, y = n), color = "#ffd79d", df = 45) +
      labs(
        x        = "",
        y        = "Casos incidentes",
        title    = "Enfermedades Respiratorias",
        subtitle = "Registros del Sistema Nacional de Vigilancia Epidemiológica (SINAVE)",
        caption  = "Datos Abiertos de la Dirección General de Epidemiología"
      ) +
      scale_y_continuous(labels = scales::label_comma()) +
      scale_x_date(date_breaks = "6 months", date_minor_breaks = "3 months",
               date_labels = "%b/%Y") +
      theme_classic() +
      theme(
        panel.background = element_rect(fill = "#003f5c"),                   #Fondo de la gráfica
        plot.background  = element_rect(fill = "#003f5c", color = "black"),  #Fondo de los títulos
        axis.text.x      = element_text(color = "gray75"),                   #Letras de los ejes
        axis.text.y      = element_text(color = "gray75"),                   #Letras de los ejes
        axis.ticks       = element_line(color = "gray75"),                   #Los | abajo de los ejes
        axis.line.x      = element_line(color = "gray75"),                   #Línea del eje
        axis.line.y      = element_line(color = "gray75"),                   #Otra línea del eje
        plot.title       = element_text(color = "gray75", size = 25),        #Título
        plot.subtitle    = element_text(color = "#62a757", face = "italic"), #Subtítulo
        plot.caption     = element_text(color = "#62a757"),                  #Caption
        axis.title.y     = element_text(color = "gray75"),                   #Lo que dice el eje y
      ) +
      #Anotaciones
      geom_point(aes(x = as.Date("2020/02/28"), y = 1), color = "gray75", data = NULL, size = 2) +
      geom_segment(aes(x = as.Date("2020/02/28"), xend = as.Date("2020/02/28"), y = 1,
                       yend = 75000), color = "gray75") +
      geom_point(aes(x = as.Date("2020/02/28"), y = 75000), color = "gray75", data = NULL, size = 2) +
      annotate("text", x = as.Date("2020/03/15"), y = 75000, hjust = 0,
               label = "Primer caso de COVID-19", color = "gray75")

    5.1 Ejercicios

    1. Agrega a la gráfica anterior una anotación el 24 de diciembre del 2022 indicando que ese día ocurrió la primer vacuna.

    2. Cambia el tema de la gráfica anterior por cualquier otra combinación de cuatro colores (en lugar del verde, azul, amarillo y gris)

    3. La base de datos dosis_antihep_jalisco.csv contiene la cantidad de dosis aplicadas de producto biológico Antihepatitis b en el IMSS el 2000 al 2020. Replica la siguiente gráfica lo más cercano posible. Los colores usados son "#2C3333" para el fondo, "#A5C9CA" y "#ADADFF" para puntos, texto del eje, títulos y spline y "#395B64" para los ejes.

    6 Ejercicio de cierre de la sección

    Para este ejercicio puedes usar cualquier base(s) de datos que tú desees. La única petición es que no haya que limpiar los datos: si necesitas hacerlo por ahorita hazlo en Excel o elige una base distinta que no lo requiera.

    El ejercicio consiste en realizar dos gráficas de distinto tipo (ej una de barras y una de tendencia) analizando elementos de tu base de datos.

    Tip

    Si no tienes datos para usar te recomiendo vacunacion_puebla_menores_1_anio.csv para una gráfica de barras (contiene la información de vacunas apliadas a menores de 1 año por jurisdicción en Puebla), polio-number-unvaccinated.csv para una gráfica de tendencias donde muestres cómo ha evolucionado la cantidad de niños en México que no recibieron vacuna contra la polio o bien OCDE_DTP_MEASLES_2008.csv para una gráfica de puntos donde cada punto es un país de la OCDE en 2008 y se grafican las tasas de vacunación con DTP y contra sarampión.

    7 Para saber más

    El libro de ggplot2 es una excelente referencia para la parte de graficación así como las notas en español de rafalab. Por otro lado el libro de Fundamentals of Data Visualization analiza más a fondo cómo presentar datos de formas que convenzan al público. Para armar historias a partir de los datos ve el libro de Story-telling with data

    8 Continuación

    ¡Felicidades! Ya terminaste esta sección. Puedes ir a:

    9 Sistema

    sessioninfo::session_info()
    ─ Session info ───────────────────────────────────────────────────────────────
     setting  value
     version  R version 4.2.1 (2022-06-23)
     os       macOS Big Sur ... 10.16
     system   x86_64, darwin17.0
     ui       X11
     language (EN)
     collate  en_US.UTF-8
     ctype    en_US.UTF-8
     tz       America/Mexico_City
     date     2022-10-07
     pandoc   2.19.2 @ /Applications/RStudio.app/Contents/MacOS/quarto/bin/tools/ (via rmarkdown)
    
    ─ Packages ───────────────────────────────────────────────────────────────────
     package       * version  date (UTC) lib source
     assertthat      0.2.1    2019-03-21 [1] CRAN (R 4.2.0)
     backports       1.4.1    2021-12-13 [1] CRAN (R 4.2.0)
     bit             4.0.4    2020-08-04 [1] CRAN (R 4.2.0)
     bit64           4.0.5    2020-08-30 [1] CRAN (R 4.2.0)
     broom           1.0.1    2022-08-29 [1] CRAN (R 4.2.0)
     cellranger      1.1.0    2016-07-27 [1] CRAN (R 4.2.0)
     cli             3.4.1    2022-09-23 [1] CRAN (R 4.2.0)
     colorspace      2.0-3    2022-02-21 [1] CRAN (R 4.2.0)
     cowplot       * 1.1.1    2020-12-30 [1] CRAN (R 4.2.0)
     crayon          1.5.2    2022-09-29 [1] CRAN (R 4.2.0)
     DBI             1.1.3    2022-06-18 [1] CRAN (R 4.2.0)
     dbplyr          2.2.1    2022-06-27 [1] CRAN (R 4.2.0)
     digest          0.6.29   2021-12-01 [1] CRAN (R 4.2.0)
     dplyr         * 1.0.10   2022-09-01 [1] CRAN (R 4.2.0)
     ellipsis        0.3.2    2021-04-29 [1] CRAN (R 4.2.0)
     evaluate        0.16     2022-08-09 [1] CRAN (R 4.2.0)
     fansi           1.0.3    2022-03-24 [1] CRAN (R 4.2.0)
     farver          2.1.1    2022-07-06 [1] CRAN (R 4.2.0)
     fastmap         1.1.0    2021-01-25 [1] CRAN (R 4.2.0)
     forcats       * 0.5.2    2022-08-19 [1] CRAN (R 4.2.0)
     fs              1.5.2    2021-12-08 [1] CRAN (R 4.2.0)
     gargle          1.2.1    2022-09-08 [1] CRAN (R 4.2.0)
     generics        0.1.3    2022-07-05 [1] CRAN (R 4.2.0)
     ggforce         0.4.1    2022-10-04 [1] CRAN (R 4.2.1)
     ggformula     * 0.10.2   2022-09-01 [1] CRAN (R 4.2.0)
     ggplot2       * 3.3.6    2022-05-03 [1] CRAN (R 4.2.0)
     ggrepel       * 0.9.1    2021-01-15 [1] CRAN (R 4.2.0)
     ggridges      * 0.5.4    2022-09-26 [1] CRAN (R 4.2.0)
     ggstance      * 0.3.5    2020-12-17 [1] CRAN (R 4.2.0)
     glue            1.6.2    2022-02-24 [1] CRAN (R 4.2.0)
     googledrive     2.0.0    2021-07-08 [1] CRAN (R 4.2.0)
     googlesheets4   1.0.1    2022-08-13 [1] CRAN (R 4.2.0)
     gridExtra     * 2.3      2017-09-09 [1] CRAN (R 4.2.0)
     gtable          0.3.1    2022-09-01 [1] CRAN (R 4.2.0)
     haven           2.5.1    2022-08-22 [1] CRAN (R 4.2.0)
     highr           0.9      2021-04-16 [1] CRAN (R 4.2.0)
     hms             1.1.2    2022-08-19 [1] CRAN (R 4.2.0)
     htmltools       0.5.3    2022-07-18 [1] CRAN (R 4.2.0)
     htmlwidgets     1.5.4    2021-09-08 [1] CRAN (R 4.2.0)
     httr            1.4.4    2022-08-17 [1] CRAN (R 4.2.0)
     jsonlite        1.8.2    2022-10-02 [1] CRAN (R 4.2.0)
     kableExtra    * 1.3.4    2021-02-20 [1] CRAN (R 4.2.0)
     knitr           1.40     2022-08-24 [1] CRAN (R 4.2.0)
     labeling        0.4.2    2020-10-20 [1] CRAN (R 4.2.0)
     labelled        2.10.0   2022-09-14 [1] CRAN (R 4.2.0)
     lifecycle       1.0.3    2022-10-07 [1] CRAN (R 4.2.1)
     lubridate       1.8.0    2021-10-07 [1] CRAN (R 4.2.0)
     magrittr        2.0.3    2022-03-30 [1] CRAN (R 4.2.0)
     MASS            7.3-58.1 2022-08-03 [1] CRAN (R 4.2.0)
     modelr          0.1.9    2022-08-19 [1] CRAN (R 4.2.0)
     mosaicCore      0.9.2.1  2022-09-22 [1] CRAN (R 4.2.0)
     munsell         0.5.0    2018-06-12 [1] CRAN (R 4.2.0)
     pillar          1.8.1    2022-08-19 [1] CRAN (R 4.2.0)
     pkgconfig       2.0.3    2019-09-22 [1] CRAN (R 4.2.0)
     png             0.1-7    2013-12-03 [1] CRAN (R 4.2.0)
     polyclip        1.10-0   2019-03-14 [1] CRAN (R 4.2.0)
     purrr         * 0.3.5    2022-10-06 [1] CRAN (R 4.2.1)
     R6              2.5.1    2021-08-19 [1] CRAN (R 4.2.0)
     Rcpp            1.0.9    2022-07-08 [1] CRAN (R 4.2.0)
     readr         * 2.1.3    2022-10-01 [1] CRAN (R 4.2.0)
     readxl          1.4.1    2022-08-17 [1] CRAN (R 4.2.0)
     reprex          2.0.2    2022-08-17 [1] CRAN (R 4.2.0)
     rlang           1.0.6    2022-09-24 [1] CRAN (R 4.2.0)
     rmarkdown       2.16     2022-08-24 [1] CRAN (R 4.2.0)
     rstudioapi      0.14     2022-08-22 [1] CRAN (R 4.2.0)
     rvest           1.0.3    2022-08-19 [1] CRAN (R 4.2.0)
     scales        * 1.2.1    2022-08-20 [1] CRAN (R 4.2.0)
     sessioninfo     1.2.2    2021-12-06 [1] CRAN (R 4.2.0)
     stringi         1.7.8    2022-07-11 [1] CRAN (R 4.2.0)
     stringr       * 1.4.1    2022-08-20 [1] CRAN (R 4.2.0)
     svglite         2.1.0    2022-02-03 [1] CRAN (R 4.2.0)
     systemfonts     1.0.4    2022-02-11 [1] CRAN (R 4.2.0)
     tibble        * 3.1.8    2022-07-22 [1] CRAN (R 4.2.0)
     tidyr         * 1.2.1    2022-09-08 [1] CRAN (R 4.2.0)
     tidyselect      1.1.2    2022-02-21 [1] CRAN (R 4.2.0)
     tidyverse     * 1.3.2    2022-07-18 [1] CRAN (R 4.2.0)
     tweenr          2.0.2    2022-09-06 [1] CRAN (R 4.2.0)
     tzdb            0.3.0    2022-03-28 [1] CRAN (R 4.2.0)
     utf8            1.2.2    2021-07-24 [1] CRAN (R 4.2.0)
     vctrs           0.4.2    2022-09-29 [1] CRAN (R 4.2.0)
     viridisLite     0.4.1    2022-08-22 [1] CRAN (R 4.2.0)
     vroom           1.6.0    2022-09-30 [1] CRAN (R 4.2.0)
     webshot         0.5.4    2022-09-26 [1] CRAN (R 4.2.0)
     withr           2.5.0    2022-03-03 [1] CRAN (R 4.2.0)
     xfun            0.33     2022-09-12 [1] CRAN (R 4.2.0)
     xml2            1.3.3    2021-11-30 [1] CRAN (R 4.2.0)
     yaml            2.3.5    2022-02-21 [1] CRAN (R 4.2.0)
    
     [1] /Library/Frameworks/R.framework/Versions/4.2/Resources/library
    
    ──────────────────────────────────────────────────────────────────────────────