Cuando tenemos datos cuantitativos continuos, una de las primeras tareas que se debe realizar es determinar cual es su distribución, para tal fin, se tiene que graficar un histograma. La estructura del histogramas es:
En la construcción del histograma un paso clave es determinar el número de clases o intervalos, ya que, de ello dependera la variabilidad de agrupamiento.
Existen varios métodos para su construcción. El más conocido es el
método de Sturges y en R existe una funcion
hist() que por defecto emplea este método, no es necesario
poner el argumento breaks = “Sturges”.
Veamos el siguiente ejemplo:
Tomemos la variable Tiempo de espera entre erupciones
del data set faithful que se encuentra por defecto en
R.
library(agricolae) #Cargamos esta libreria para la construcción de Tablas de Frecuencias
data(faithful)
print(table.freq(hist(faithful[,2],plot = FALSE)))
## Lower Upper Main Frequency Percentage CF CPF
## 1 40 45 42.5 4 1.5 4 1.5
## 2 45 50 47.5 22 8.1 26 9.6
## 3 50 55 52.5 33 12.1 59 21.7
## 4 55 60 57.5 24 8.8 83 30.5
## 5 60 65 62.5 14 5.1 97 35.7
## 6 65 70 67.5 10 3.7 107 39.3
## 7 70 75 72.5 27 9.9 134 49.3
## 8 75 80 77.5 54 19.9 188 69.1
## 9 80 85 82.5 55 20.2 243 89.3
## 10 85 90 87.5 23 8.5 266 97.8
## 11 90 95 92.5 5 1.8 271 99.6
## 12 95 100 97.5 1 0.4 272 100.0
hist(faithful[,2] , xlab = "Tiempo de espera en min", main = "Histograma con Sturges por defecto")
Graficar un histograma según la regla de Sturges consiste en:
Dada \(n\) observaciones:
range(faithful[,2]) # calcular el máximo y mínimo de un vector
## [1] 43 96
Rango = max(faithful[,2]) - min(faithful[,2])
Rango
## [1] 53
K = ceiling(1 + 3.33*log10(length(faithful[,2]))) #ceiling devuelve el entero siguiente
K
## [1] 10
Si A > 0, \(A = \frac{Rango + 1}{k}\)
Si A < 0, \(A = \frac{Rango - 1}{k}\)
A = round(Rango/K,1)
if (A>1) {
A = round((Rango + 1)/K,1)
} else{
A = round((Rango - 1)/K,1)
}
A
## [1] 5.4
NR = K*A
NR
## [1] 54
E = NR - Rango
E
## [1] 1
Primer_LI = min(faithful[,2]) - E/2
Primer_LI
## [1] 42.5
Último_LS = max(faithful[,2]) + E/2
Último_LS
## [1] 96.5
L_I = numeric(K) #Contiene un vector de ceros de tamaño k
L_I[1] = min(faithful[,2]) - E/2
for (i in 2:K) {
L_I[i] = L_I[i-1] + A
}
matrix(L_I)
## [,1]
## [1,] 42.5
## [2,] 47.9
## [3,] 53.3
## [4,] 58.7
## [5,] 64.1
## [6,] 69.5
## [7,] 74.9
## [8,] 80.3
## [9,] 85.7
## [10,] 91.1
L_S = numeric(K) #Contiene un vector de ceros de tamaño k
L_S[1] = L_I[2]
for (i in 2:K) {
L_S[i] = L_I[i] + A
}
matrix(L_S)
## [,1]
## [1,] 47.9
## [2,] 53.3
## [3,] 58.7
## [4,] 64.1
## [5,] 69.5
## [6,] 74.9
## [7,] 80.3
## [8,] 85.7
## [9,] 91.1
## [10,] 96.5
Frecuencias = numeric(K)
for (i in 1:K) {
Frecuencias[i] =sum(L_I[i] <= faithful[,2] & faithful[,2]<L_S[i])
}
matrix(Frecuencias)
## [,1]
## [1,] 13
## [2,] 31
## [3,] 26
## [4,] 24
## [5,] 9
## [6,] 23
## [7,] 62
## [8,] 55
## [9,] 24
## [10,] 5
library(tidyverse) # para usar la función str_c() en este caso
Intervalos = numeric(K)
a = paste(L_I,L_S,sep = " - ")
for (i in 1:K) {
Intervalos[i] = str_c("[",a[i],")")
}
Tabla_Frecuencias = data.frame(Intervalos,Frecuencias)
Tabla_Frecuencias
## Intervalos Frecuencias
## 1 [42.5 - 47.9) 13
## 2 [47.9 - 53.3) 31
## 3 [53.3 - 58.7) 26
## 4 [58.7 - 64.1) 24
## 5 [64.1 - 69.5) 9
## 6 [69.5 - 74.9) 23
## 7 [74.9 - 80.3) 62
## 8 [80.3 - 85.7) 55
## 9 [85.7 - 91.1) 24
## 10 [91.1 - 96.5) 5
library(ggplot2) # para grpaficos sofisticados
library(plotly) # para gráficos interactivos
hist = ggplot(data =Tabla_Frecuencias,aes(Intervalos,Frecuencias)) + geom_col(width = 1,color = "black",fill = "#AFEEEE")+
labs(title = "Histograma manual con el método de Sturges", x = "Tiempo de espera entre erupciones (min)", y = "Frecuencia") +
theme_minimal()+
theme(axis.text.x = element_text(size = rel(0.8)),plot.title=element_text(hjust=0.5))
ggplotly(hist) # para obtener un histograma dinámico
En muchas ocasiones tenemos presencia de valores atípicos, llamados también outliers que pueden agrandar dramáticamente el rango y así aumentar el tamaño de los intervalos. Para ello hay dos alternativas que pueden ser empleadas, fueron propuestas por:
- Scott
- Freedman & Diaconis
Para obtener el número de intervalos que necesita nuestra
distribución, utilizaremos la función nclass.scott:
x = faithful[,2]
Intervalos = nclass.scott(x)
Cortes <- seq(min(x), max(x), length.out = Intervalos + 1)
hist = hist(x, breaks = Cortes, main = "Histograma con el método de Scott", freq = FALSE, ylab = "densidad", xlab = "Tiempo de espera entre erupciones (min)", col = "#AFEEEE")
lines(density(x), lwd = 2, col = 'red')
print(table.freq(hist))
## Lower Upper Main Frequency Percentage CF CPF
## 1 43.000 49.625 46.3125 21 7.7 21 7.7
## 2 49.625 56.250 52.9375 42 15.4 63 23.2
## 3 56.250 62.875 59.5625 24 8.8 87 32.0
## 4 62.875 69.500 66.1875 16 5.9 103 37.9
## 5 69.500 76.125 72.8125 40 14.7 143 52.6
## 6 76.125 82.750 79.4375 70 25.7 213 78.3
## 7 82.750 89.375 86.0625 47 17.3 260 95.6
## 8 89.375 96.000 92.6875 12 4.4 272 100.0
Para obtener el número de intervalos que necesita nuestra
distribución, utilizaremos la función nclass.FD:
x = faithful[,2]
Intervalos = nclass.FD(x)
Cortes <- seq(min(x), max(x), length.out = Intervalos + 1)
hist = hist(x, breaks = Cortes, main = "Histograma con el método de Freedman & Diaconis", freq = FALSE, ylab = "densidad", xlab = "Tiempo de espera entre erupciones (min)", col = "#AFEEEE")
lines(density(x), lwd = 2, col = 'red')
print(table.freq(hist))
## Lower Upper Main Frequency Percentage CF CPF
## 1 43.000 49.625 46.3125 21 7.7 21 7.7
## 2 49.625 56.250 52.9375 42 15.4 63 23.2
## 3 56.250 62.875 59.5625 24 8.8 87 32.0
## 4 62.875 69.500 66.1875 16 5.9 103 37.9
## 5 69.500 76.125 72.8125 40 14.7 143 52.6
## 6 76.125 82.750 79.4375 70 25.7 213 78.3
## 7 82.750 89.375 86.0625 47 17.3 260 95.6
## 8 89.375 96.000 92.6875 12 4.4 272 100.0
Para obtener el número de intervalos que necesita nuestra
distribución, utilizaremos la función nclass.Sturges:
x = faithful[,2]
Intervalos = nclass.Sturges(x)
Cortes <- seq(min(x), max(x), length.out = Intervalos + 1)
hist = hist(x, breaks = Cortes, main = "Histograma con el método de Sturges",freq = FALSE, ylab = "densidad", xlab = "Tiempo de espera entre erupciones (min)", col = "#AFEEEE")
lines(density(x), lwd = 2, col = 'red')
print(table.freq(hist))
## Lower Upper Main Frequency Percentage CF CPF
## 1 43.0 48.3 45.65 16 5.9 16 5.9
## 2 48.3 53.6 50.95 28 10.3 44 16.2
## 3 53.6 58.9 56.25 26 9.6 70 25.7
## 4 58.9 64.2 61.55 24 8.8 94 34.6
## 5 64.2 69.5 66.85 9 3.3 103 37.9
## 6 69.5 74.8 72.15 23 8.5 126 46.3
## 7 74.8 80.1 77.45 62 22.8 188 69.1
## 8 80.1 85.4 82.75 55 20.2 243 89.3
## 9 85.4 90.7 88.05 23 8.5 266 97.8
## 10 90.7 96.0 93.35 6 2.2 272 100.0