library(readxl)
Base_de_datos <- read_excel("C:/Users/USUARIO/Desktop/Base de datos.xlsx")
View(Base_de_datos)
c <- Base_de_datos
head(c)
## # A tibble: 6 × 4
## Periodo Ciudad `Total area licenciada metros cuadrados` Despachos de cemento…¹
## <dbl> <chr> <dbl> <dbl>
## 1 2005 Bogota 333345 124122
## 2 2005 Bogota 291808 117670.
## 3 2005 Bogota 328718 125706.
## 4 2005 Bogota 234104 133875
## 5 2005 Bogota 379570 119691
## 6 2005 Bogota 347630 132501.
## # ℹ abbreviated name: ¹`Despachos de cemento gris toneladas`
Generamos el histograma de la variable “DESPACHO DE CEMENTO GRIS (TON)” y superponemos la curva de densidad de una v.a Normal con media y desviacion típica iguales a la de la varible “DESPACHO DE CEMENTO GRIS (TON)”:
Base de datos, Queremos ver si se distribuye normalamente, para poder predecir resultados de la variable de estudio.
Analisis por medio de histogramas.
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
ggplot(data = c, mapping = aes(x =c$`Despachos de cemento gris toneladas`)) +
geom_histogram(aes(y =..density..), color="black", fill="bisque3", position = 'identity', bins = 45) +
stat_function(
fun = dnorm,
args = list(mean = mean(c$`Despachos de cemento gris toneladas`), sd = sd(c$`Despachos de cemento gris toneladas`)),
lwd = 1,
col = 'red2' ) +
scale_y_continuous( n.breaks = 15 )+
scale_x_continuous(n.breaks = 15)+
labs(x = "DESPACHOS DE CEMENTO GRIS (TON)", y = "Frecuencia Relativa")
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: Use of `` c$`Despachos de cemento gris toneladas` `` is discouraged.
## ℹ Use `Despachos de cemento gris toneladas` instead.
## Use of `` c$`Despachos de cemento gris toneladas` `` is discouraged.
## ℹ Use `Despachos de cemento gris toneladas` instead.
Segun mi criterio, el perfil del histograma y la curva de densidad normal no son aproximadamente iguales, hay demasiada diferencia como para considerar que X=DESPACHOS DE CEMENTO GRIS (TON) tiene una distribucion significativamente normal. Por lo que no habria evidencia estadistica significativa como para aceptar que X, de muestra tiene una distribucion normal.
s=sd(c$`Despachos de cemento gris toneladas`)
n=length(c$`Despachos de cemento gris toneladas`)
max=max(c$`Despachos de cemento gris toneladas`)
min=min(c$`Despachos de cemento gris toneladas`)
#Amplitud teorica
At = 3.5*s*n^-(1/3)
#Numero de intervalos
lambda = ceiling((max-min)/At)
#Amplitud de los intervalos
A = ceiling((max-min)/lambda)
#Primer extremo
L1 = min
#Vector con los extremos de los intervalos
L = L1 + 0:lambda * A
library(tidyverse)
ggplot(data = c, mapping = aes(x = c$`Despachos de cemento gris toneladas`)) +
geom_histogram(aes(y =..density..), color="black", fill="bisque3", position = 'identity', breaks=L) +
stat_function(
fun = dnorm,
args = list(mean = mean(c$`Despachos de cemento gris toneladas`), sd = sd(c$`Despachos de cemento gris toneladas`)),
lwd = 1.5,
col = 'red2' ) +
scale_y_continuous( n.breaks = 15 )+
scale_x_continuous(n.breaks = 15)+
labs(x = "DESPACHOS DE CEMENTO GRIS (TON)", y = "Frecuencia Relativa")
## Warning: Use of `` c$`Despachos de cemento gris toneladas` `` is discouraged.
## ℹ Use `Despachos de cemento gris toneladas` instead.
## Use of `` c$`Despachos de cemento gris toneladas` `` is discouraged.
## ℹ Use `Despachos de cemento gris toneladas` instead.
reducir el numero de intervalos el perfil del histograma se aproxima mas a la curva de densidad normal.
Veamos ahora cual sería el resultado si simulamos valores de un v.a. Normal con media y desviación típica igual a la media y desviación tipica de la variable “DESPACHOS DE CEMENTO GRIS (TON)”, y representamos su histograma, y ademas superponemos la curva normal como hicimos antes.
set.seed(123)
df<- tibble(Variable_Normal_Simulada = rnorm(n=200000, mean=mean(c$`Despachos de cemento gris toneladas`), sd=sd(c$`Despachos de cemento gris toneladas`)) )
knitr::kable(head(df) , align="c")
| Variable_Normal_Simulada |
|---|
| 115062.2 |
| 121144.9 |
| 154088.7 |
| 126682.3 |
| 127764.7 |
| 156968.1 |
##Gráfico Q-Q-Norm en R Investigan….
ggplot(c, aes(sample = c$`Despachos de cemento gris toneladas`) ) +
stat_qq( color="red2") + stat_qq_line(color="black", size=0.6) +
scale_y_continuous( n.breaks = 15 )+
scale_x_continuous(n.breaks =20)+
xlab("Cuantiles teoricos N(0,1)")+
ylab("Cuantiles variable peso Media ")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: Use of `` c$`Despachos de cemento gris toneladas` `` is discouraged.
## ℹ Use `Despachos de cemento gris toneladas` instead.
## Use of `` c$`Despachos de cemento gris toneladas` `` is discouraged.
## ℹ Use `Despachos de cemento gris toneladas` instead.
El analisis de Normalidad basado en los graficos Q-Q-Norm se basa en esta última conclusión. El criterio antes expuesto tiene su fundamento teorico en este último hecho.
Como consideramos que el entendimiento de los graficos Q-Q-Norm es algo complicado, al menos en un principio, se va a desarrollar otro grafico mas intuitivo, a mi juicio, que tambien puede usarse para realizar un análisis de normalidad.
##Grafico de Cuantiles Comparados
cuantiles_normales <- quantile(rnorm(200000 , mean=mean(c$`Despachos de cemento gris toneladas`), sd=sd(c$`Despachos de cemento gris toneladas`)) , seq(0, 1 , by=0.05) )
cuantiles_variable <- quantile( c$`Despachos de cemento gris toneladas` , seq(0, 1 , by=0.05))
orden_cuantiles <- c(seq(0, 1 , by=0.05), seq(0, 1 , by=0.05) )
cuantiles <- c(cuantiles_normales , cuantiles_variable)
dff<-tibble( orden_cuantiles , cuantiles, tipo=c(rep("Normal", length(cuantiles_normales)) , rep("Variable", length(cuantiles_variable))) )
knitr::kable(head(df) , align="c")
| Variable_Normal_Simulada |
|---|
| 115062.2 |
| 121144.9 |
| 154088.7 |
| 126682.3 |
| 127764.7 |
| 156968.1 |
ggplot(data = dff , aes(x = orden_cuantiles, y = cuantiles, color = tipo))+
geom_point( ) +
scale_y_continuous( n.breaks = 15 )+
scale_x_continuous(n.breaks =15)+
xlab("Orden del cuantil")+
ylab("Cuantiles") +
scale_color_manual(breaks = c("Normal", "Variable"),
values=c("red", "black" ))
Como puede verse hay bastante similitud entre los cuantiles de la variable de interés y los de la variable normal simulada con media y desviacion tipica igual a la de la variable de interés.
A=seq(0, 1 , by=0.005) (Se representarán muchos mas cuantiles en este caso)
cuantiles_normales <- quantile(rnorm(200000 , mean=mean(c$`Despachos de cemento gris toneladas`), sd=sd(c$`Despachos de cemento gris toneladas`)) , seq(0, 1 , by=0.05) )
cuantiles_variable <- quantile(c$`Despachos de cemento gris toneladas` , seq(0, 1 , by=0.05))
orden_cuantiles <- c(seq(0, 1 , by=0.05), seq(0, 1 , by=0.05) )
cuantiles <- c(cuantiles_normales , cuantiles_variable)
df<-tibble( orden_cuantiles , cuantiles, tipo=c(rep("Normal", length(cuantiles_normales)) , rep("Variable", length(cuantiles_variable))) )
knitr::kable(head(df) , align="c")
| orden_cuantiles | cuantiles | tipo |
|---|---|---|
| 0.00 | 43720.93 | Normal |
| 0.05 | 95240.73 | Normal |
| 0.10 | 101859.49 | Normal |
| 0.15 | 106378.25 | Normal |
| 0.20 | 109901.39 | Normal |
| 0.25 | 112965.33 | Normal |
ggplot(data = df , aes(x = orden_cuantiles, y = cuantiles, color = tipo))+
geom_point( ) +
scale_y_continuous( n.breaks = 15)+
scale_x_continuous(n.breaks =15)+
xlab("Orden del cuantil")+
ylab("Cuantiles") +
scale_color_manual(breaks = c("Normal", "Variable"),
values=c("red", "black" ))
Como puede verse hay bastante similitud entre los cuantiles de la variable de interés y los de la variable normal simulada con media y desviacion tipica igual a la de la variable de interés. Por lo que segun este metodo podria considerarse que la distribucion de peso es significativamente Normal, y con ello aceptarlo a nivel poblacional.
##Gráfico de Comparación de Frecuencias Relativas en R
Tabla_Frecuencias <- function(X, V1 ,p1 ){
tabla<- matrix(NA, nrow=p1+1, ncol= 4 )
X<- cbind(X, V1)
for(i in 0:p1){
tabla[i+1, 1 ] <- dim( ( X %>% filter(V1==i ) ) )[1]
}
for(i in 0:p1){
tabla[i+1, 2 ] <- ( dim( ( X %>% filter(V1==i ) ) )[1] / dim(X)[1] )
}
for(i in 0:p1){
tabla[i+1, 3] <- cumsum(tabla[1:(i+1) ,1])[i+1]
}
for(i in 0:p1){
tabla[i+1, 4] <- cumsum(tabla[1:(i+1) ,2])[i+1]
}
rownames(tabla)<-0:p1
colnames(tabla)<-c("F.Abs","F.Rel", "F.Abs.Cum","F.Rel.Cum")
tabla <- as.data.frame(tabla)
return(tabla)
}
DESPACHO <- c$`Despachos de cemento gris toneladas`
s=sd(DESPACHO)
n=length(DESPACHO)
max=max(DESPACHO)
min=min(DESPACHO)
#Numero de intervalos --> 45
#Amplitud de los intervalos
A = ceiling((max-min)/45)
#Primer extremo
L1 = min - 5
#Vector con los extremos de los intervalos
( L = L1 + 0:45 * A )
## [1] 9728.558 13320.558 16912.558 20504.558 24096.558 27688.558
## [7] 31280.558 34872.558 38464.558 42056.558 45648.558 49240.558
## [13] 52832.558 56424.558 60016.558 63608.558 67200.558 70792.558
## [19] 74384.558 77976.558 81568.558 85160.558 88752.558 92344.558
## [25] 95936.558 99528.558 103120.558 106712.558 110304.558 113896.558
## [31] 117488.558 121080.558 124672.558 128264.558 131856.558 135448.558
## [37] 139040.558 142632.558 146224.558 149816.558 153408.558 157000.558
## [43] 160592.558 164184.558 167776.558 171368.558
#Calculamos las frecuencias relativas
set.seed(666)
variable_normal <- rnorm(200000, mean = mean(DESPACHO), sd = sd(DESPACHO))
a<-(cut(variable_normal, breaks = L , include.lowest = T, labels=F))
variable_normal_categorizada <- a-1
df<- data.frame(variable_normal_categorizada)
Frecuencias_Relativas_Normal <- Tabla_Frecuencias(df, variable_normal_categorizada, p1=44)$F.Rel
df2<- data.frame(Frecuencias_Relativas_Normal, intervalo=1:45)
##########################################################################################################
b<-(cut(DESPACHO, breaks = L , include.lowest = T, labels=F))
DESPACHO_categorizada <- b-1
df3<- data.frame(DESPACHO_categorizada)
Frecuencias_Relativas_DESPACHO <- Tabla_Frecuencias(df3, DESPACHO_categorizada, p1=44)$F.Rel
##########################################################################################################
df_completo <- data.frame( Frecuencias_Relativas=c(Frecuencias_Relativas_DESPACHO, Frecuencias_Relativas_Normal), intervalo=rep(1:45, 2), tipo=c(rep("Variable de interes",45),rep("Variable Normal",45)))
library(tidyverse)
ggplot(data = df_completo, aes(y=Frecuencias_Relativas, x=intervalo, color=tipo)) +
geom_point()+
geom_line()+
scale_y_continuous( n.breaks = 15 )+
scale_x_continuous(n.breaks = 15)+
labs(x = "Intervalos", y = "Frecuencia Relativa")
En el grafico se pueden ver las frecuencias relativas de la variable cuantitativa de interes DESPACHO y la variable Normal simulada , en los mismos intervalos. Esto permite analizar visualmente la disparidad o semejanza de las frecuencias relativas en el caso de la variable original frente al caso de que la variable tuviese distribucion normal.
Queda a ojo del analista decidir si las frecuencias relativas de la variable de interes y la variable normal estan suficientemente proximas como para considerarlas aproximadamente iguales y con ello considerar que la variable de interes tiene una distribucion significativamente normal.
##Métodos Analíticos:
Coeficiente de Asimetria
Asimetria en R
library(moments)
skewness(c$`Despachos de cemento gris toneladas`)
## [1] -1.248709
[0, 1.5]
Podemos concluir que hay evidencia estadisitica de que la distribucion de frecuencias de la variable de interes es una distribucion aproximadamente Normal con media y varianza igual a la de la variable de interes.
Si simulamos una variable normal se obtiene el siguiente resultado:
library(moments)
set.seed(666)
skewness(rnorm(n=200000, mean=mean(c$`Despachos de cemento gris toneladas`), sd=sd(c$`Despachos de cemento gris toneladas`)))
## [1] -0.006374078
Como era de esperar el valor obtenido es prácticamente 0, lo que indica que la distribucion de frecuencias de la variable normal simulada es efectivamente una distribucion Normal.
##Curtosis en R
library(moments)
kurtosis(c$`Despachos de cemento gris toneladas`)
## [1] 9.575457
library(moments)
kurtosis(rnorm(n=15000, mean=mean(c$`Despachos de cemento gris toneladas`), sd=sd(c$`Despachos de cemento gris toneladas`)))
## [1] 2.910792
Como era de espera la curtosis de la variable normal simulada es aproximadamente 3.
#Contrastes de hipótesis
A continuacion vamos a exponer los contrastes de hipotesis mas empleados para analizar la normalidad de una variable cuantitativa.
Un contraste de hipotesis es un procedimiento estadistico para rechazar una hipotesis basandose en datos/evidencia.
#Test de Shapiro-Wilk en R
shapiro.test( x = c$`Despachos de cemento gris toneladas` )
##
## Shapiro-Wilk normality test
##
## data: c$`Despachos de cemento gris toneladas`
## W = 0.93197, p-value = 9.434e-09
Como pvalor=9.434e-09 < α=0.05, Se rechaza la hipotesis nula
para un nivel de significacion de 0.05, no hay suficiente evidencia estadistica en los datos como para rechazar la hipotesis de que la variable de interes tenga una distribución de frecuencias Normal con media y desviacion tipica igual a la de la variable de interés.
#Test de Kolmogorov-Smirnov-Lilliefors en R
library(nortest)
lillie.test(x = c$`Despachos de cemento gris toneladas` )
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: c$`Despachos de cemento gris toneladas`
## D = 0.053194, p-value = 0.1216
Como pvalor=0.1216>α=0.05, para un nivel de significacion de 0.05, no hay suficiente evidencia estadistica en los datos como para rechazar la hipotesis de que la variable de interes tenga una distribución de frecuencias Normal con media y desviacion tipica igual a la de la variable de interés.
#Comparacion de funciones de distribución en R
Detras del test de Kolmogorov-Smirnov-Lilliefors esta la comparacion entre la funcion de distribucion de la variable de interes y la de una v.a. Normal con media y desviacion tipica igual a la de la variable de interés.
En el fondo el grafico de comparación de cuantiles expuesto en la seccion de métodos gráficos es la superposicion de los graficos de las funciones de distribucion empiricas de la variable de interes y la v.a. Normal con media y desviacion tipica igual a la de interés.
Podemos obtener con R el grafico de la funcion de distribucion empirica de una variable del siguiente modo:
despacho_medio=c$`Despachos de cemento gris toneladas`
plot(ecdf(despacho_medio))
m=mean(c$`Despachos de cemento gris toneladas`)