EL HISTOGRAMA

Es uno de los tipos de gráficos más utilizados, y recuerda a simple vista el diagrama de barras, pero presenta algunas diferentes sustanciales.

Gracias a este tipo de gráfico se obtiene una “primera impresión” de la distribución de una variable, deduciendo inicialmente su grado de dispersión, posibles sesgos etc… Su utilidad se hace más evidente cuando se cuenta con un gran número de datos, que se agrupan en intervalos de clase.

Si no se ha cargado el dataframe alumnos_UC.RData, es el momento de hacerlo.

La función hist() elabora un histograma, acompañado de una serie de argumentos para modificar el histograma.

hist(alumnos_uc$peso,
     main = "Título del histograma",                                     # Título
     freq = TRUE,                                                        # Si TRUE distribución de frecuencias, si FALSE distribución de densidad.
     sub = "Subtítulo",                                                  # Subtítulo
     xlab = "Etiqueta eje X",                                            # Etiqueta eje X
     ylab = "Etiqueta eje Y",                                            # Etiqueta eje Y
     ylim = c(0,25),                                                     # Valores del eje Y
     col = "blue",                                                       # Color de las barras
     border = "red",                                                     # Color del borde de las barras
     density = 10,                                                       # Líneas de sombreado
     angle = 20)                                                         # Ángulo de las líneas

Obtención de los datos numéricos con los que se construye el histograma

Con el argumento plot = FALSE podemos obtener los datos numéricos resultado de la construcción del histograma

hist(alumnos_uc$peso,
     plot = FALSE)                                                              
## $breaks
##  [1]  55  60  65  70  75  80  85  90  95 100
## 
## $counts
## [1]  4  7 13  6 13 18 16 18  5
## 
## $density
## [1] 0.008 0.014 0.026 0.012 0.026 0.036 0.032 0.036 0.010
## 
## $mids
## [1] 57.5 62.5 67.5 72.5 77.5 82.5 87.5 92.5 97.5
## 
## $xname
## [1] "alumnos_uc$peso"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"

La función histograma sin gráfico devuelve una lista de 6 elementos

  • $breaks: intervalos.

  • $counts: número de observaciones en cada intervalo.

  • $density: frecuencia de valores de cada intervalo.

  • $mids: marcas

  • $xname : nombre de la variable en el eje horizontal

  • $equidist: valor lógico indicando si los intervalos estÁ¡n espaciados regularmente

Histograma con dos variables simultáneas

Aunque el uso más frecuente implica dibujar un gráfico por variable, es posible la elaboración de histograma con dos variables simultáneas. Esto permite comparar la distribución de ambas variables al mismo tiempo.

masc <- subset(alumnos_uc, 
               genero=="Masculino")                                              
fem <- subset(alumnos_uc, 
              genero=="Femenino")                                              

hist(masc$peso, 
     main = "Distribución del peso según el género", 
     ylab = "Frecuencia", 
     ylim = c(0, 15))
hist(fem$peso, add = TRUE, col = rgb(1, 0, 0, alpha = 0.5))

Pasos para la construcción del histograma

Como en el caso de las tablas para variables continuas, la creación de un histograma debería seguir los siguientes pasos.

  • PASO 1: Número de clases (intervalos).

  • PASO 2: Amplitud de los intervalos.

  • PASO 3: Límites (superior e inferior de los intervalos)

  • PASO 4: Valor representativo de cada intervalo (marca de clase)

La selección del número de clases es clave:

  • Pocas clases agruparán demasiado las observaciones.

  • Con demasiadas clases habrá pocas observaciones en cada una de ellas.

Ejemplo de estas circunstancias son los siguientes gráficos

# Una fila, dos columnas
par(mfrow = c(1, 2))

# Los siguientes gráficos se combinarán
hist(alumnos_uc$peso, breaks = 5, main = "Pocas clases", ylab = "Frecuencia")
hist(alumnos_uc$peso, breaks = 15, main = "Demasiadas clases", ylab = "Frecuencia")

# Volvemos al estado original
par(mfrow = c(1, 1))

El número de clases es controlado por el argumento breaks. Este argumento puede ser aplicado de diferentes maneras.

  • Con unos intervalos proporcionados por nosotros
min <- min(alumnos_uc$peso)
max <- max(alumnos_uc$peso)

hist(alumnos_uc$peso, 
     breaks=c(50,65,80,95, 110),                        # Alternativa: crear objeto limites <- seq(50,110, by = 15) y sustituir breaks por limites
     freq= TRUE,                                        # Opción por defecto frecuencia relativa; FALSE absoluta. 
     ylim=range(0:60),                                  # Atención: rango del eje vertical, que varía si es freq. abs o rel
     col="lightblue",
     right=FALSE,
     main="Distribución del peso",
     include.lowest=TRUE, 
     plot=TRUE)

abline(v=mean(alumnos_uc$peso),                         # v: valor del eje X por donde queremos que pase una recta vertical.
       col="red",                                       # Color de la línea.
       lty=2,                                           # Tipo de línea (tipo 2: discontinua trazo)
       lwd=2)                                           # Ancho de línea

  • Con intervalos calculados por la propia función hist(), aplicando los algorítmos de Sturges (por defecto), Scott o Fiedman-Diaconis.
hist(alumnos_uc$peso,
     breaks = "Sturges")
abline(v=mean(alumnos_uc$peso),                         # v: valor del eje X por donde queremos que pase una recta vertical.
       col="darkgreen",                                 # Color de la línea.
       lty=2,                                           # Tipo de línea (tipo 2: discontinua trazo)
       lwd=2)                                           # Ancho de línea

Una alternativa a los métodos precedentes para seleccionar el número de clases es el método plug-in que se utiliza para calcular el tamaño de la ventana (intervalo) óptima (Wand, 1995).

  • Instalación del paquete
# install.packages("KernSmooth")
library(KernSmooth)
  • Cálculo de la ventana óptima y del número de clases. El método para seleccionar el ancho óptimo proviene de (1995), siendo una modificación de la regla de Scott (1979).
ancho_barras <- dpih(alumnos_uc$peso)                                                   # Ventana óptima

nclases <- seq(min(alumnos_uc$peso) - ancho_barras,                                     # Número de clases
               max(alumnos_uc$peso) + ancho_barras,
               by = ancho_barras)
  • Creación del histograma
hist(alumnos_uc$peso,                                                                   # Histograma
     breaks = nclases,
     main = "Método plug-in")

El paquete fdth() permite reducir el tiempo empleado en el análisis de variables cuantitativas, al proporcionar tanto una tabla numérica como los gráficos correspondientes.

  • Instalación del paquete
library(fdth)                                                                   
  • Elaboración de la tabla.
tabla <- fdt(alumnos_uc$peso, breaks = "Sturges")             # calcula la distribución de frecuencias utilizando la regla Sturgess
tabla                                                         # Proporciona una tabla con los calculos de la distribución de frecuencias.
##     Class limits  f   rf rf(%)  cf cf(%)
##    [58.43,63.24)  6 0.06     6   6     6
##    [63.24,68.05) 14 0.14    14  20    20
##    [68.05,72.86)  6 0.06     6  26    26
##   [72.86,77.671) 11 0.11    11  37    37
##  [77.671,82.481) 15 0.15    15  52    52
##  [82.481,87.291) 16 0.16    16  68    68
##  [87.291,92.101) 17 0.17    17  85    85
##  [92.101,96.911) 15 0.15    15 100   100
  • Creación de los gráficos
par(mfrow=c(2,2))                                                               # Fraccionamos la ventana grafica en 2x2.
plot(tabla, type="fh", main = "Histograma de frecuencias relativas")
plot(tabla, type="cfh", main = "Histograma de frecuencias acumuladas")
plot(tabla, type="fp", main = "Gráfico de líneas frecuencias relativas")
plot(tabla, type="cfp", main = "Gráfico de líneas frecuencias acumuladas")

# Dos opciones para volver a la distribución original de la pantalla (1 gráfico)
par(mfrow=c(1,1))                                                               # Vuelve a la pantalla original
rm(ancho_barras, col, etiq, etiquetas, lab, max, min, nclases, pct,tabla)

📝 ****ACTIVIDAD DE EVALUACIÓN CONTINUA: HISTOGRAMA**::

  1. Elabora un histograma con la variable edad que incluya:
  • Título.

  • Representación de la distribución de frecuencias.

  • Número de intervalos según el algorítmo de Sturges.

  • Etiquetas en los ejes X e Y.

  • Ajusta las dimensiones del eje vertical para que no sobresalga en exceso.

  • Aplica como color de las barras el azul claro (lightblue).

  • Dibuja la línea correspondiente al valor medio con un color

hist(alumnos_uc$edad,
     main = "Título del histograma",                    # Título
     freq = TRUE,                                       # Si TRUE distribución de frecuencias, si FALSE distribución de densidad.
     breaks = "Sturges",
     xlab = "Etiqueta eje X",                           # Etiqueta eje X
     ylab = "Etiqueta eje Y",                           # Etiqueta eje Y
     ylim = c(0,25),                                    # Valores del eje Y
     col = "lightblue")                                 # Color de las barras
abline(v=mean(alumnos_uc$peso),                         # v: valor del eje X por donde queremos que pase una recta vertical.
       col="orange",                                    # Color de la línea.
       lty=2,                                           # Tipo de línea (tipo 2: discontinua trazo)
       lwd=2)                                           # Ancho de línea
  1. Elabora un histograma comparando la distribución de la variable Ozone en los meses de mayo y agosto. Estos datos se encuentran en el conjunto de datos airquality que se carga de la siguiente manera.
data(airquality)
airquality
##     Ozone Solar.R Wind Temp Month Day
## 1      41     190  7.4   67     5   1
## 2      36     118  8.0   72     5   2
## 3      12     149 12.6   74     5   3
## 4      18     313 11.5   62     5   4
## 5      NA      NA 14.3   56     5   5
## 6      28      NA 14.9   66     5   6
## 7      23     299  8.6   65     5   7
## 8      19      99 13.8   59     5   8
## 9       8      19 20.1   61     5   9
## 10     NA     194  8.6   69     5  10
## 11      7      NA  6.9   74     5  11
## 12     16     256  9.7   69     5  12
## 13     11     290  9.2   66     5  13
## 14     14     274 10.9   68     5  14
## 15     18      65 13.2   58     5  15
## 16     14     334 11.5   64     5  16
## 17     34     307 12.0   66     5  17
## 18      6      78 18.4   57     5  18
## 19     30     322 11.5   68     5  19
## 20     11      44  9.7   62     5  20
## 21      1       8  9.7   59     5  21
## 22     11     320 16.6   73     5  22
## 23      4      25  9.7   61     5  23
## 24     32      92 12.0   61     5  24
## 25     NA      66 16.6   57     5  25
## 26     NA     266 14.9   58     5  26
## 27     NA      NA  8.0   57     5  27
## 28     23      13 12.0   67     5  28
## 29     45     252 14.9   81     5  29
## 30    115     223  5.7   79     5  30
## 31     37     279  7.4   76     5  31
## 32     NA     286  8.6   78     6   1
## 33     NA     287  9.7   74     6   2
## 34     NA     242 16.1   67     6   3
## 35     NA     186  9.2   84     6   4
## 36     NA     220  8.6   85     6   5
## 37     NA     264 14.3   79     6   6
## 38     29     127  9.7   82     6   7
## 39     NA     273  6.9   87     6   8
## 40     71     291 13.8   90     6   9
## 41     39     323 11.5   87     6  10
## 42     NA     259 10.9   93     6  11
## 43     NA     250  9.2   92     6  12
## 44     23     148  8.0   82     6  13
## 45     NA     332 13.8   80     6  14
## 46     NA     322 11.5   79     6  15
## 47     21     191 14.9   77     6  16
## 48     37     284 20.7   72     6  17
## 49     20      37  9.2   65     6  18
## 50     12     120 11.5   73     6  19
## 51     13     137 10.3   76     6  20
## 52     NA     150  6.3   77     6  21
## 53     NA      59  1.7   76     6  22
## 54     NA      91  4.6   76     6  23
## 55     NA     250  6.3   76     6  24
## 56     NA     135  8.0   75     6  25
## 57     NA     127  8.0   78     6  26
## 58     NA      47 10.3   73     6  27
## 59     NA      98 11.5   80     6  28
## 60     NA      31 14.9   77     6  29
## 61     NA     138  8.0   83     6  30
## 62    135     269  4.1   84     7   1
## 63     49     248  9.2   85     7   2
## 64     32     236  9.2   81     7   3
## 65     NA     101 10.9   84     7   4
## 66     64     175  4.6   83     7   5
## 67     40     314 10.9   83     7   6
## 68     77     276  5.1   88     7   7
## 69     97     267  6.3   92     7   8
## 70     97     272  5.7   92     7   9
## 71     85     175  7.4   89     7  10
## 72     NA     139  8.6   82     7  11
## 73     10     264 14.3   73     7  12
## 74     27     175 14.9   81     7  13
## 75     NA     291 14.9   91     7  14
## 76      7      48 14.3   80     7  15
## 77     48     260  6.9   81     7  16
## 78     35     274 10.3   82     7  17
## 79     61     285  6.3   84     7  18
## 80     79     187  5.1   87     7  19
## 81     63     220 11.5   85     7  20
## 82     16       7  6.9   74     7  21
## 83     NA     258  9.7   81     7  22
## 84     NA     295 11.5   82     7  23
## 85     80     294  8.6   86     7  24
## 86    108     223  8.0   85     7  25
## 87     20      81  8.6   82     7  26
## 88     52      82 12.0   86     7  27
## 89     82     213  7.4   88     7  28
## 90     50     275  7.4   86     7  29
## 91     64     253  7.4   83     7  30
## 92     59     254  9.2   81     7  31
## 93     39      83  6.9   81     8   1
## 94      9      24 13.8   81     8   2
## 95     16      77  7.4   82     8   3
## 96     78      NA  6.9   86     8   4
## 97     35      NA  7.4   85     8   5
## 98     66      NA  4.6   87     8   6
## 99    122     255  4.0   89     8   7
## 100    89     229 10.3   90     8   8
## 101   110     207  8.0   90     8   9
## 102    NA     222  8.6   92     8  10
## 103    NA     137 11.5   86     8  11
## 104    44     192 11.5   86     8  12
## 105    28     273 11.5   82     8  13
## 106    65     157  9.7   80     8  14
## 107    NA      64 11.5   79     8  15
## 108    22      71 10.3   77     8  16
## 109    59      51  6.3   79     8  17
## 110    23     115  7.4   76     8  18
## 111    31     244 10.9   78     8  19
## 112    44     190 10.3   78     8  20
## 113    21     259 15.5   77     8  21
## 114     9      36 14.3   72     8  22
## 115    NA     255 12.6   75     8  23
## 116    45     212  9.7   79     8  24
## 117   168     238  3.4   81     8  25
## 118    73     215  8.0   86     8  26
## 119    NA     153  5.7   88     8  27
## 120    76     203  9.7   97     8  28
## 121   118     225  2.3   94     8  29
## 122    84     237  6.3   96     8  30
## 123    85     188  6.3   94     8  31
## 124    96     167  6.9   91     9   1
## 125    78     197  5.1   92     9   2
## 126    73     183  2.8   93     9   3
## 127    91     189  4.6   93     9   4
## 128    47      95  7.4   87     9   5
## 129    32      92 15.5   84     9   6
## 130    20     252 10.9   80     9   7
## 131    23     220 10.3   78     9   8
## 132    21     230 10.9   75     9   9
## 133    24     259  9.7   73     9  10
## 134    44     236 14.9   81     9  11
## 135    21     259 15.5   76     9  12
## 136    28     238  6.3   77     9  13
## 137     9      24 10.9   71     9  14
## 138    13     112 11.5   71     9  15
## 139    46     237  6.9   78     9  16
## 140    18     224 13.8   67     9  17
## 141    13      27 10.3   76     9  18
## 142    24     238 10.3   68     9  19
## 143    16     201  8.0   82     9  20
## 144    13     238 12.6   64     9  21
## 145    23      14  9.2   71     9  22
## 146    36     139 10.3   81     9  23
## 147     7      49 10.3   69     9  24
## 148    14      20 16.6   63     9  25
## 149    30     193  6.9   70     9  26
## 150    NA     145 13.2   77     9  27
## 151    14     191 14.3   75     9  28
## 152    18     131  8.0   76     9  29
## 153    20     223 11.5   68     9  30

El gráfico debe incluir:

  • Título.

  • Representación de la distribución de frecuencias.

  • Número de intervalos según el algorítmo de Sturges.

  • Etiquetas en los ejes X e Y.

  • Ajusta las dimensiones del eje vertical para que no sobresalga en exceso.

  • Aplica como color de las barras el azul claro (lightblue).

  • Dibuja la línea correspondiente al valor medio con un color

mayo <- subset(airquality, 
               Month == 5)                                              
agosto <- subset(airquality, 
               Month == 8)                                              

hist(mayo$Ozone, 
     main = "Distribución del ozono en los meses de mayo y agosto", 
     ylab = "Frecuencia",
     xlab = "Concentración en ppb",
     ylim = c(0, 20),
     xlim = c(0,140),
     col = "lightgrey")
hist(agosto$Ozone, 
     add = TRUE, 
     col = rgb(1, 0, 0, alpha = 0.25))
legend("topright", 
       c("Mayo", "Septiembre"), 
       col=c("lightgrey", rgb(1, 0, 0, alpha = 0.25)), 
       lwd=10,
       bty = "n")                                                  # Eliminar el marco de la leyenda  
  1. Elabora sendos histogramas a partir de la variable con la variable Temp del dataframe airquality.
  • Crea un nuevo vector (variables) transformando los datos en ºC según la siguiente fórmula Celsius = (Fahrenheit – 32) * 5/9.
temperatura <- (airquality$Temp - 32) * 5/9
  • Crea un histograma aplicando el algorítmo de Sturges para la obtención del número de intervalos y los límites de clase. Dibuja la línea que corersponde al promedio en color azul.
hist(temperatura,
     breaks = "Sturges")
abline(v=mean(temperatura),                         # v: valor del eje X por donde queremos que pase una recta vertical.
              col="darkgreen",                                 # Color de la línea.
       lty=2,                                           # Tipo de línea (tipo 2: discontinua trazo)
       lwd=2)                                           # Ancho de línea
  • A partir del gráfico anterior, extrae los datos numéricos sobre los que se elabora el histograma y contesta a las siguientes preguntas:

  • ¿Cuál es la categoría con el mayor número de elementos?

  • ¿Cuáles son los límites de esa categoría?

hist(temperatura,
     breaks = "Sturges", 
     plot = FALSE)                                                              

Repite el procedimiento mediante el cálculo de la ventana óptima siguiendo el método `plug-in”. Incorpora los elementos visuales que consideres oportuno (etiquetas en los ejes, título, etc)

ancho_barras_tem <- dpih(temperatura)                          # Ventana óptima

nclases_tem <- seq(min(temperatura) - ancho_barras_tem,        # Número de clases
               max(temperatura) + ancho_barras_tem,
               by = ancho_barras_tem)

hist(temperatura,                                              # Histograma
     breaks = nclases_tem,
     main = "Método plug-in")
abline(v=mean(temperatura),                                    # v: valor del eje X por donde queremos que pase una recta vertical.
              col="darkblue",                                  # Color de la línea.
       lty=2,                                                  # Tipo de línea (tipo 2: discontinua trazo)
       lwd=2) 
  • ¿Cuál es la categoría con el mayor número de elementos?

  • ¿Cuáles son los límites de esa categoría?

hist(temperatura,                                              # Histograma
     breaks = nclases_tem,
     main = "Método plug-in", 
     plot = FALSE)                                                              

Compara los resultados y señala qué diferencias observas entre ambos procedimientos.

POLÍGONO DE FRECUENCIAS

Los polígonos de frecuencia se crean a partir de los histograma, uniendo el punto medio del techo de cada columna mediante segmentos de recta. Ese punto es siempre el intervalo de mayor frecuencia del conjunto. No es un gráfico con un gran uso.

Para realizarlo hay que cargar el paquete agricolae.

library(agricolae)

La forma más sencilla de crear este gráfico es creando un objeto con un histograma, y luego aplicando la función polygon.freq() al objeto creado por hist().

h1 <- hist(alumnos_uc$peso,
           col = "white",
           border= "black")

polygon.freq(h1,
             frequency = 1,                                         # (1) recuento, (2) frecuencia relativa, (3) densidad
             col="red",
             lwd = 3)

Una forma más elaborada es proporcionar los intervalos (limites) y las frecuencias absolutas (frecuencias). Esto se realizará mediante la función hist() con el argumento plot = FALSE, por el cual obtenemos los datos numéricos con los que se elabora un histograma.

histograma <- hist(alumnos_uc$peso, breaks = "Sturges", plot = FALSE)
histograma
## $breaks
##  [1]  55  60  65  70  75  80  85  90  95 100
## 
## $counts
## [1]  4  7 13  6 13 18 16 18  5
## 
## $density
## [1] 0.008 0.014 0.026 0.012 0.026 0.036 0.032 0.036 0.010
## 
## $mids
## [1] 57.5 62.5 67.5 72.5 77.5 82.5 87.5 92.5 97.5
## 
## $xname
## [1] "alumnos_uc$peso"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"

De esos resultados creamos

limites <- histograma$breaks
frecuencias <- histograma$counts
z <- graph.freq(limites,
                counts = frecuencias, 
                main="Polígono de frecuencias",
                ylab = "Frecuencia")
polygon.freq(z, 
             frequency=1,                                                       # (1) recuento, (2) frecuencia relativa, (3) densidad
             col="red", 
             lwd = 3)

rm(limites, frecuencias, z, h1)

📝 ****ACTIVIDAD DE EVALUACIÓN CONTINUA: POLIGONO DE FRECUENCIAS**::

Siguiendo el método que consideres oportuno, crea un polígono de frecuencias sobre un histograma representando la variable Solar.R de la base de datos airquality. Incorpora las variables visuales a tu gusto.

rad <- hist(airquality$Solar.R,
           col = "white",
           border= "black")

polygon.freq(rad,
             frequency = 1,                                         # (1) recuento, (2) frecuencia relativa, (3) densidad
             col="red",
             lwd = 3)

CURVA DE DENSIDAD

Una curva de densidad es una representación idealizada de la distribución de una variable en la que el área bajo la curva equivale a 1 (o el 100%). La curva de densidad representa la función de densidad de una variable: esta a su vez refleja la probabilidad de que dicha variable alcance un valor determinado. La función de densidad se calcula mediante la siguiente fórmula:

(Número de observaciones en el intervalo/Número total de observaciones)/Longitud del intervalo.

La función hist() crea por defecto un histograma de frecuencias, que se transforma en un histograma de densidad estableciendo prob = TRUE.

hist(alumnos_uc$peso, 
     prob = TRUE, 
     ylim = c(0, 0.05),
     main = "Histograma de densidad",                                         
     ylab = "Densidad")

O con el argumento freq = FALSE.

hist(alumnos_uc$peso,
     ylim = c(0,0.05),
     main = "Histograma de densidad",
     freq = FALSE)    

Puede considerarse la función de densidad de probabilidad empírica como una versión suavizada del histograma. Esta suavización también se conoce como estimador de Parzen-Rosenblatt o estimador kernel.Para agregar una curva de densidad se puede utilizar la función density(), con diferentes opciones:

hist(alumnos_uc$peso, 
     freq = FALSE, 
     main = "Histograma con gráfico de densidad superpuesto")

dens_peso <- density(alumnos_uc$peso)
lines(dens_peso, 
      lwd = 2, 
      col = "red")

plot(dens_peso, 
     lwd = 2, 
     col = "red",
     main = "gráfico de densidad")

rug(jitter(alumnos_uc$peso))                                                      # Añadir los datos en el eje X

Sobre estas dos opciones se puede incluir información adicional, por ejemplo, la curva de densidad de una distribución normal o el valor medio de esa variable.

hist(alumnos_uc$peso,                                                           # Variable para crear el histograma
     prob = TRUE,                                                               # Argumento para crear la curva
     ylim = c(0,0.05),                                                          # Límites del eje x
     main = "Histograma con curva de densidad")                                 # Título del gráfico

grid(nx = NA, ny = NULL, lty = 2, col = "gray", lwd = 1)                        # Superposición de un grid
lines(density(alumnos_uc$peso), col = "red", lwd = 2)                           # Curva de densidad
curve(dnorm(x,                                                                  # Función para crear la curva normal
            mean=mean(alumnos_uc$peso),                                         # Promedio de la variable.
            sd=sd(alumnos_uc$peso)),                                            # Desviación típica de la variable.
      add=TRUE, 
      col="#00ff00", 
      lwd=3)
abline(v=mean(alumnos_uc$peso),                                                 # Línea vertical representando la media
       lwd=2,                                                                   # Anchura de la línea
       lty=3,                                                                   # Tipo de línea
       col="darkblue")                                                          # Color de la línea
legend("topleft",                                                               # Leyenda
       col=c("red","#00ff00"),
       legend =c("Densidad normal estimada","Distribución normal"),
       lwd=2, 
       bty = "n")

También se puede utilizar la siguiente función para crear automáticamente un histograma al que se le superpone una curva normal y otra de densidad.

histDenNorm <- function (x, ...) {
  hist(x, ...)                                                                  # Histograma
  lines(density(x), col = "blue", lwd = 2)                                      # Densidad
  x2 <- seq(min(x), max(x), length = 40)
  f <- dnorm(x2, mean(x), sd(x))
  lines(x2, f, col = "red", lwd = 2)                                            # Normal
  legend("topright", c("Histograma", "Densidad", "Normal"), box.lty = 0,        # Leyenda
         lty = 1, col = c("black", "blue", "red"), lwd = c(1, 2, 2))
}

histDenNorm(alumnos_uc$peso, 
            prob = TRUE, ylim= c(0,0.05), main = "Histograma")

Una opción alternativa es el uso del paquete EnvStats.

# install.packages("EnvStats")

library(EnvStats)

La función requerida para la creación de la curva es epalumnos_ucPlot().

epdfPlot(alumnos_uc$peso, 
         epdf.col  = "red")

Cuando R dibuja una curva de densidad aparece un número (estimador kernel) en la parte inferior, que es el valor que sirve para suavizar la curva a partir de los datos originales. Es posible modificar ese valor con el argumento bw(). En general, un valor elevado suaviza en exceso, mientras que uno pequeño actúa de manera contraria.

par(mfrow = c(1,2))

plot(density(alumnos_uc$peso, bw = 60), lwd = 2,
     col = "red", 
     main = "Ancho de banda elevado")

plot(density(alumnos_uc$peso, bw = 0.05), lwd = 2,
     col = "red", 
     main = "Ancho de banda pequeño")

par(mfrow = c(1,1))

Sintaxis equivalente con el paquete EnvStats

epdfPlot(alumnos_uc$peso, 
         epdf.col = "red", 
         density.arg.list = list(bw = 6),
         main = "Ancho de banda intermedio")

La selección del ancho de banda depende de la variable que estamos analizando o de los objetivos de nuestro estudio. Pero su elección puede apoyarse en una serie de procedimientos objetivos:

plot(density(alumnos_uc$peso), 
     main = "Rule of thumb",                            
     cex.lab = 1.5, cex.main = 1.75, lwd = 2)

plot(density(alumnos_uc$peso, 
             bw = bw.ucv(alumnos_uc$peso)), col = 2,  
     main = "Cross-validation", cex.lab = 1.5,
     cex.main = 1.75, lwd = 2)

plot(density(alumnos_uc$peso, 
             bw = bw.SJ(alumnos_uc$peso)), col = 4,
     main = "Plug-in bandwidth selection",
     cex.lab = 1.5, cex.main = 1.75, lwd = 2)

Existen otros estimadores Kernel disponibles (“gaussian”, “epanechnikov”, “rectangular”, “triangular,”biweight”, “cosine” y “optcosine”) que se pueden cambiar con el argumento kernel (por defecto Gaussian).

Con la función lines se pueden superponer diferentes curvas de densidad en R. El procedimiento consiste en crear inicialmente un gráfico de densidad y luego añadir la(s) nuevas líneas. En caso de que no coincidan los valores de los ejes X e Y se deben incluir los xlim e ylim con los valores máximo y mínimo de cada eje en la función plot, porque los límites se establecerán de forma predeterminada a partir de la primera curva.

dens_peso_masc <- density(masc$peso)
dens_peso_fem <- density(fem$peso)

plot(dens_peso_masc, 
     lwd = 2, 
     col = "red",
     main = "Dos curvas superpuestas", 
     xlab = "", 
     ylim = c(0, 0.05))

lines(dens_peso_fem, 
      col = "blue", 
      lwd = 2)

Hay otras maneras de comparar densidades, por ejemplo la función densityPlot() del paquete car. Esta función crea estimaciones de densidad no paramétricas condicionadas por un factor.

library(car)
?densityPlot                                                                    # Para obtener información adicional sobre la función y el método.

alumnos_uc$genero <- as.factor(alumnos_uc$genero)

densityPlot(alumnos_uc$peso,                                                      # Variable
            alumnos_uc$genero)                                                 # Factor

Se puede usar la función polygon() para sombrear el Á¡rea bajo las curvas de densidad. Usando la función rgb() en el argumento col el área del diagrama de densidad puede adquirir transparencia (argumento alpha, que va desde 0, que es transparencia total hasta 1, que dibuja el color opaco.

plot(dens_peso_masc, lwd = 4, main = "", xlab = "",
     col = rgb(0, 0, 1, alpha = 0.3), 
     xlim = c(50, 110))
polygon(dens_peso_masc, col = "red")

lines(dens_peso_fem, lwd = 4, col = "yellow")
polygon(dens_peso_fem, 
        col = rgb(0, 0, 1, alpha = 0.3))

Alternativa equivalente con el paquete EnvStats configurando los colores con el argumento curve.fill.col de la función epalumnos_ucPlot().

# install.packages("EnvStats")
library(EnvStats)

epdfPlot(alumnos_uc$peso,                                                         # Vector con datos
         xlim = c(50, 110),
         curve.fill = TRUE,                                                     # Colorear el área
         curve.fill.col = rgb(1, 0, 0, alpha = 0.5),                            # Color del área
         epdf.col  = "red")                                                      # Color de la curva

epdfPlot(alumnos_uc$peso, 
         curve.fill = TRUE,
         curve.fill.col = rgb(0, 0, 1, alpha = 0.5),
         epdf.col  = "blue",
         add = TRUE)                                                            # Añade la densidad sobre el plot anterior

📝 ****ACTIVIDAD DE EVALUACIÓN CONTINUA: CURVA DE DENSIDAD**::