Aunque hay muchos parámetros y conclusiones que se pueden obtener al analizar un histograma, esta guía sólo pretende, más bien, mostrar como construir un histograma y generar su tabla de frecuencia en R. Para esto se emplearon las siguientes liberías que contienen los paquetes y datos necesariso para el ejercicio.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(moderndive)

Evaluación de enseñanza en UT Austin University

evals es un data frame con 463 observaciones correspondientes a un curso. Esta contiene 13 variables, de las cuales, para este ejemplo, se tomará solamente score.

Variable Explicación
ID Variable de identificación
prof_ID Variable de identificación para el profesor
score Puntuación promedio de evaluación del profesor
age Edad del profesor
bty_avg Puntuación promedio de belleza
gender Genero del profesor
ethnicity Etnicidad del profesor: no minoría, minoría
language Idioma de la escuela: inglés, no inglés
rank Rango del profesor: enseñanza, tenure track, titular
pic_outfit Atuendo del profesor en la foto: forma, no formal
pic_color Color de la foto del profesor: color, blanco y negro.
cls_did_eval Número de estudiantes en clase que completaron la eva.
cls_students Total de estudiantes en la clase
cls_level Nivel de la clase: inferior, superior

Tabla de frecuencias

Con la función de summarise() se calcula el mínimo, el máximo, el total de datos, los intervalos (bins) y el ancho de de cada uno (binwidth).

evals %>% 
  summarise(
    minimo = min(score), 
    maximo = max(score), 
    total = n(), 
    bins = ceiling(1 + log(total, 2)), 
    binwidth = (maximo - minimo)/bins
  )
## # A tibble: 1 × 5
##   minimo maximo total  bins binwidth
##    <dbl>  <dbl> <int> <dbl>    <dbl>
## 1    2.3      5   463    10     0.27

A partir de los datos anteriores se crea la tabla de frecuencia generando cortes (cut) con una serie de intervalos que irán desde el mínimo (2.3) hasta el máximo (5) con espacios correspondientes al binwidth (0.27). Agrupando estos intervalos se puede obtener la fecuencia. Después, se calcula la frecuencia acumulada y la frecuencia porcentual.

evals %>%
  mutate(bins = cut(score,
                   breaks = seq(2.3, 5, by = 0.27),
                   include.lowest = TRUE)) %>%
  group_by(bins) %>%
  summarize(frecuencia = n()) %>%
  ungroup() %>% 
  mutate(
    freq_acumulada = cumsum(frecuencia), 
    freq_porcentual = round((frecuencia/463)*100,3)
  ) 
## # A tibble: 10 × 4
##    bins        frecuencia freq_acumulada freq_porcentual
##    <fct>            <int>          <int>           <dbl>
##  1 [2.3,2.57]           4              4           0.864
##  2 (2.57,2.84]          5              9           1.08 
##  3 (2.84,3.11]         13             22           2.81 
##  4 (3.11,3.38]         15             37           3.24 
##  5 (3.38,3.65]         48             85          10.4  
##  6 (3.65,3.92]         64            149          13.8  
##  7 (3.92,4.19]         52            201          11.2  
##  8 (4.19,4.46]         91            292          19.7  
##  9 (4.46,4.73]        100            392          21.6  
## 10 (4.73,5]            71            463          15.3

Histograma con geom_histogram()

Para que la tabla de frecuencia sea congruente con el histograma en la función ggplot_histogram() se colocan como argumentos:

Adicionalmente, para que los ejes sean representados adecuadamente se emplea el argumento scale_x_continuos() en el cual se establecen los límites que corresponden al mínimo (2.3) y al máximo (5). Finalmente se establecen los breakes que son análogos lo establecido en la tabla de frecuencia, breaks = seq(2.3, 5, by = 0.27)

evals %>% 
  ggplot(aes(score))+
  geom_histogram(binwidth = 0.27,  boundary = 2.3, color = "white", fill= "azure3")+
  scale_y_continuous(breaks = scales::pretty_breaks())+
  scale_x_continuous(
    limits = c(2.3, 5), 
    breaks = seq(2.3, 5, by = 0.27) 
  )

Así, cada una de las barras representa el intervalo definido en la tabla de frecuencia que se realizó anteriormente.

Histograma con geom_bar()

Otra forma de vizualizarlo es por medio de geom_bar() ya que existe un argumento que permite definir la escala de x para que muestre intervalos definidos. Es por ello que se debe extraer los datos del límite superior para que estos aparezca en el gráfico final.

lim_sup = evals %>%
  mutate(bins = cut(score,
                   breaks = seq(2.3, 5, by = 0.27),
                   include.lowest = TRUE)) %>%
  group_by(bins) %>%
  summarize(frecuencia = n()) %>%
  ungroup() %>% 
  mutate(
    freq_acumulada = cumsum(frecuencia), 
    freq_porcentual = round((frecuencia/463)*100,3),
    limite_superior = as.numeric(sub(".*,\\s*(\\d+\\.?\\d*)\\]", "\\1", as.character(bins)))
  ) %>% 
  select(limite_superior)


evals %>% 
  ggplot(aes(score))+
  geom_bar(fill= "azure3")+
  scale_x_binned(breaks = lim_sup)+
  scale_y_continuous(breaks = scales::pretty_breaks())

Como se puede apreciar, se obtiene casi el mismo gráfico, pero ahora están definidos sólo los límites superiores.

Referencias

https://www.youtube.com/watch?v=CmSZwmoGnJY&ab_channel=Ingenier%C3%ADaIndustrialEasy https://www.youtube.com/watch?v=5CH1cAFm7ag&ab_channel=Gibr%C3%A1nSayeg