Maestria en ciencia de datos

Modelos estadisticos para la toma de decisiones

Para iniciar con la actividad se realiza principalmente un análisis exploratorio de los datos y ajustes de limpieza de los datos.

Se llaman todos los paquetes y librerías a utilizar para el procesamiento, modelado y graficas.

# instalacion de librerias y paquetes
#install.packages("learnr") # solo la primera vez
#install.packages("devtools") # solo la primera vez
devtools::install_github("dgonxalex80/paqueteMODELOS", force =TRUE)
## digest (0.6.34 -> 0.6.35) [CRAN]
## package 'digest' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\PC\AppData\Local\Temp\RtmpY7NIWs\downloaded_packages
## ── R CMD build ─────────────────────────────────────────────────────────────────
##          checking for file 'C:\Users\PC\AppData\Local\Temp\RtmpY7NIWs\remotes4b885a042beb\dgonxalex80-paqueteMODELOS-796f588/DESCRIPTION' ...  ✔  checking for file 'C:\Users\PC\AppData\Local\Temp\RtmpY7NIWs\remotes4b885a042beb\dgonxalex80-paqueteMODELOS-796f588/DESCRIPTION'
##       ─  preparing 'paqueteMODELOS': (1.3s)
##    checking DESCRIPTION meta-information ...  ✔  checking DESCRIPTION meta-information
##       ─  checking for LF line-endings in source and make files and shell scripts
##       ─  checking for empty or unneeded directories
##       ─  building 'paqueteMODELOS_0.1.0.tar.gz'
##      
## 
library(paqueteMODELOS)
library(dplR)
library(plotly)
library(corrplot)
#install.packages("PerformanceAnalytics")
library(PerformanceAnalytics)
#install.packages("mice")
library(mice)#install.packages("caret")
library(caret)

Se importa el data set vivienda y es llamado como “data” en este ejercicio.

# importacion del data set vivienda
data("vivienda")

Se identifica si el data set tienen valores faltantes.

# identificar valores nan 
vivienda_na <- colSums(is.na(vivienda)) %>% as.data.frame()
print(vivienda_na)
##                 .
## id              3
## zona            3
## piso         2638
## estrato         3
## preciom         2
## areaconst       3
## parqueaderos 1605
## banios          3
## habitaciones    3
## tipo            3
## barrio          3
## longitud        3
## latitud         3
head(vivienda)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 Zona O… <NA>        3     250        70            1      3            6
## 2  1169 Zona O… <NA>        3     320       120            1      2            3
## 3  1350 Zona O… <NA>        3     350       220            2      2            4
## 4  5992 Zona S… 02          4     400       280            3      5            3
## 5  1212 Zona N… 01          5     260        90            1      2            3
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Se muestran gráficamente los datos faltantes.

 # muestra los datos faltantes en la grafica
grafico <-md.pattern(vivienda, rotate.names = TRUE)

Se observa que existen dos filas totalmente vacías por lo que se procede a depurarla realizando eliminación de estos datos ya que no aportan información, para la variable parqueadero se sustituye por cero (0) y para la variable piso por la moda.

Se realiza ajuste donde se colocan las variables categóricas en mayúsculas para manejar un estándar.

# se colocan las variabloes categoricas en mayuscula

vivienda$barrio = toupper(vivienda$barrio)
vivienda$tipo = toupper(vivienda$tipo)
vivienda$zona = toupper(vivienda$zona)

Para los parqueaderos que cuentan con datos vacíos se realiza sustitución por el valor cero (0) indicando que no existen parqueaderos.

#limpieza de los dtaos
# parqueadero nulos se reemplazan por 0
vivienda$parqueaderos[is.na(vivienda$parqueaderos)] <- 0
grafico <-md.pattern(vivienda, rotate.names = TRUE)

Para la variable piso se realiza sustitución de los datos vacíos por la moda correspondiente.

moda <- as.numeric(names(sort(table(vivienda$piso), decreasing = TRUE)[1]))

# Reemplaza los NA por la moda
vivienda$piso[is.na(vivienda$piso)] = moda
grafico <-md.pattern(vivienda, rotate.names = TRUE)

Para las filas vacías se elimina la información.

#Eliminancion de filas nan
vivienda= na.omit(vivienda)
grafico <-md.pattern(vivienda, rotate.names = TRUE)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

De acuerdo a la imagen anterior podemos evidenciar que no existe ningún dato faltante por lo cual podemos proceder con el ejercicio.

1- Realice un filtro a la base de datos e incluya solo las ofertas de: base1: casas, de la zona norte de la ciudad. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta.

# se seleccionan las casas de la zona norte de cali
# se realiza conteo de las zonas con su respectivo tipo de vivienda
table(vivienda$zona, vivienda$tipo)
##               
##                APARTAMENTO CASA
##   ZONA CENTRO           24  100
##   ZONA NORTE          1198  722
##   ZONA OESTE          1029  169
##   ZONA ORIENTE          62  289
##   ZONA SUR            2787 1939

Se selecciona la zona norte y las viviendas tipo casa.

# se selecciona la zona norte y las viviendas tipo casa
Data = subset(vivienda, vivienda$zona ==  "ZONA NORTE" & vivienda$tipo == "CASA")

Se muestran los primeros tres registros de la selección de casas de la zona norte.

# primeros 3 datos
print("Primeros 3 registros:")
## [1] "Primeros 3 registros:"
print(head(Data, 3))
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1209 ZONA N… 02          5     320       150            2      4            6
## 2  1592 ZONA N… 02          5     780       380            2      3            3
## 3  4057 ZONA N… 02          6     750       445            0      7            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
# Verificar con algunas tablas
print("Tabla de frecuencias de zona y tipo de vivienda:")
## [1] "Tabla de frecuencias de zona y tipo de vivienda:"
print(table(Data$zona, Data$tipo))
##             
##              CASA
##   ZONA NORTE  722
print("Resumen de datos:")
## [1] "Resumen de datos:"
print(summary(Data))
##        id             zona               piso              estrato     
##  Min.   :  58.0   Length:722         Length:722         Min.   :3.000  
##  1st Qu.: 766.2   Class :character   Class :character   1st Qu.:3.000  
##  Median :2257.0   Mode  :character   Mode  :character   Median :4.000  
##  Mean   :2574.6                                         Mean   :4.202  
##  3rd Qu.:4225.0                                         3rd Qu.:5.000  
##  Max.   :8319.0                                         Max.   :6.000  
##     preciom         areaconst       parqueaderos        banios      
##  Min.   :  89.0   Min.   :  30.0   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.: 261.2   1st Qu.: 140.0   1st Qu.: 0.000   1st Qu.: 2.000  
##  Median : 390.0   Median : 240.0   Median : 1.000   Median : 3.000  
##  Mean   : 445.9   Mean   : 264.9   Mean   : 1.314   Mean   : 3.555  
##  3rd Qu.: 550.0   3rd Qu.: 336.8   3rd Qu.: 2.000   3rd Qu.: 4.000  
##  Max.   :1940.0   Max.   :1440.0   Max.   :10.000   Max.   :10.000  
##   habitaciones        tipo              barrio             longitud     
##  Min.   : 0.000   Length:722         Length:722         Min.   :-76.59  
##  1st Qu.: 3.000   Class :character   Class :character   1st Qu.:-76.53  
##  Median : 4.000   Mode  :character   Mode  :character   Median :-76.52  
##  Mean   : 4.507                                         Mean   :-76.52  
##  3rd Qu.: 5.000                                         3rd Qu.:-76.50  
##  Max.   :10.000                                         Max.   :-76.47  
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.452  
##  Median :3.468  
##  Mean   :3.460  
##  3rd Qu.:3.482  
##  Max.   :3.496

2- Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio de la casa) en función del área construida, estrato, numero de baños, número de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.

Se seleccionan las variables más relevantes de acuerdo a la solicitud.

Data2 <- Data[, c(5, 6, 4, 8, 9)]  # Selecciona las columnas 1, 3 y 5

print(head(Data2,5))
## # A tibble: 5 × 5
##   preciom areaconst estrato banios habitaciones
##     <dbl>     <dbl>   <dbl>  <dbl>        <dbl>
## 1     320       150       5      4            6
## 2     780       380       5      3            3
## 3     750       445       6      7            6
## 4     625       355       4      5            5
## 5     750       237       5      6            6

Se presenta la correlación de las variables para saber el efecto que positivo que van a tener en el modelo.

# Calcular la matriz de correlación
matriz_correlacion <- cor(Data2[, c("preciom", "areaconst", "estrato", "banios", "habitaciones")])

# Imprimir la matriz de correlación
print(matriz_correlacion)
##                preciom areaconst   estrato    banios habitaciones
## preciom      1.0000000 0.7313480 0.6123503 0.5233357    0.3227096
## areaconst    0.7313480 1.0000000 0.4573818 0.4628152    0.3753323
## estrato      0.6123503 0.4573818 1.0000000 0.4083039    0.1073141
## banios       0.5233357 0.4628152 0.4083039 1.0000000    0.5755314
## habitaciones 0.3227096 0.3753323 0.1073141 0.5755314    1.0000000

De acuerdo a la matriz de correlación se evidencia que la correlación más fuerte en el data set es el precio de la vivienda con el área construida con un 73% seguido del precio de la vivienda y el estrato con una correlación de 61%.

# Crear un gráfico de heatmap interactivo con plotly
heatmap <- plot_ly(z = matriz_correlacion, x = colnames(matriz_correlacion), y = colnames(matriz_correlacion), type = "heatmap", colorscale = "Viridis")

# Mostrar el gráfico
heatmap

Se grafica la matriz de correlación con un gráfico de dispersión en 3D.

# Gráfico de dispersión 3D
# Convertir la matriz a un data frame
datos_3d <- as.data.frame(as.table(matriz_correlacion))

# Crear un gráfico 3D interactivo
grafico_3d <- plot_ly(datos_3d, x = ~Var1, y = ~Var2, z = ~Freq, type = 'scatter3d', mode = 'markers')

# Mostrar el gráfico 3D
grafico_3d
columnas_numericas <- Data2[sapply(Data2, is.numeric)]
matrizcor <- cor(columnas_numericas)
corrplot (matrizcor, method = "number", number.cex = 0.5)

chart.Correlation(Data2, histogram = TRUE, method = "pearson")

Siguiendo la dinámica se observa nuevamente la fuerte correlación entre el precio de la vivienda con el área construida y el estrato, también se observa que la correlación más baja encontrada es entre el estrato y las habitaciones.

3- Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f (área construida, estrato, número de cuartos, número de parqueaderos, número de baños)) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).

Se estima el modelo de regresión lineal múltiple.

Data3 <- Data[, c(5, 6, 4, 9, 7, 8)]  # Selecciona las columnas 1, 3 y 5
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = Data3)

Se saca un resumen del modelo de regresion.

# Resumen del modelo
summary(modelo)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = Data3)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -964.04  -80.10  -17.08   50.06 1069.45 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -236.47551   30.36582  -7.788 2.40e-14 ***
## areaconst       0.82677    0.04368  18.926  < 2e-16 ***
## estrato        86.42579    7.39747  11.683  < 2e-16 ***
## habitaciones    1.44443    4.16411   0.347    0.729    
## parqueaderos   -1.67672    4.31505  -0.389    0.698    
## banios         26.97978    5.34384   5.049 5.65e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 159.1 on 716 degrees of freedom
## Multiple R-squared:  0.6508, Adjusted R-squared:  0.6484 
## F-statistic: 266.9 on 5 and 716 DF,  p-value: < 2.2e-16

De acuerdo al modelo anterior se puede interpretar de la siguiente forma:

Área construida: Por cada metro cuadrado de la casa esperamos que el precio de la vivienda aumente en promedio un $0.83. manteniendo la demás información igual.

Estrato: Por cada estrato adicional en el que se encuentra la vivienda “CASA” esperamos que el precio de esta aumente en promedio un $86.63 esto indica la influencia que tienen el estrato con el precio de la vivienda.

Habitaciones y parqueaderos: En promedio no parece a ver ningún efecto significativo en el precio de la vivienda y no podemos estar seguro de estar relaciones ya que el valor p no es significativo y este tiene un impacto distinto en el pecio después de tener presente otras variables.

Baños: Por cada baño adiciona en la vivienda esperamos que el precio aumente en promedio un $26.98 esto da indicios a que por baño adicional puede agregar valor a la vivienda.

4- Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).

Se realiza las siguientes interpretaciones de los resultados.

#Interpretar los coeficientes
# Coeficientes estimados
coeficientes <- coef(modelo)
print(coeficientes)
##  (Intercept)    areaconst      estrato habitaciones parqueaderos       banios 
##  -236.475512     0.826774    86.425791     1.444431    -1.676721    26.979782

No se tendrá en cuenta la interpretación de los coeficientes ya que en el punto anterior se realiza la interpretación correspondiente y detallada.

# Intervalos de confianza para los coeficientes
intervalos_confianza <- confint(modelo)
print(intervalos_confianza)
##                     2.5 %       97.5 %
## (Intercept)  -296.0921999 -176.8588248
## areaconst       0.7410086    0.9125393
## estrato        71.9024643  100.9491180
## habitaciones   -6.7309017    9.6197637
## parqueaderos  -10.1483778    6.7949359
## banios         16.4883088   37.4712559

De acuerdo a los intervalos de confianza del 95% se puede interpretar que el área construida el coeficiente esta aproximadamente entre el 0.7441 y 0.913, esto indica que el precio esperado para la vivienda puede aumentar por cada metro adicional. En cuanto al estrato, está en aproximadamente 71.902 y 100.949 y por cada estrato puede aumentar el precio de la vivienda. Los baños el verdadero coeficiente está en aproximadamente 16.488 y 37.471 indicando el precio adicional por cada baño. Por otra parte, sin descartar las habitaciones y los baños no existe suficiente información y no está claro el efecto que puede tener en el precio de la vivienda esto indica que el coeficiente no es significativo y no podemos estar seguro del impacto que este genere en el precio final de la vivienda.

# Pruebas de hipótesis sobre los coeficientes
pruebas_hipotesis <- summary(modelo)$coef[, c("Estimate", "Pr(>|t|)")]
print(pruebas_hipotesis)
##                 Estimate     Pr(>|t|)
## (Intercept)  -236.475512 2.399693e-14
## areaconst       0.826774 4.397467e-65
## estrato        86.425791 5.495234e-29
## habitaciones    1.444431 7.287864e-01
## parqueaderos   -1.676721 6.977058e-01
## banios         26.979782 5.646533e-07

De acuerdo a las hipótesis se puede observar e interpretar que los valores p para el área construida, estrato y baños tiene un efecto significativo en el precio de la vivienda, por otro lado, las habitaciones y parqueaderos no se tienen suficiente evidencia para indicar si tienen o no un efecto significativo en el precio de la vivienda.

5- Realice una partición en los datos de forma aleatoria donde 70% sea un set para entrenar el modelo y 30% para prueba. Estime el modelo con la muestra del 70%. Muestre los resultados.

Se crea una semilla para la reproducibilidad.

set.seed(123)

Se realiza la partición de los datos de forma aleatoria donde el 70% es para entrenar el modelo y el 30 % para la prueba del modelo.

# Partición de datos (70% entrenamiento, 30% prueba)
indice_particion <- createDataPartition(Data3$preciom, p = 0.7, list = FALSE)
datos_entrenamiento <- Data3[indice_particion, ]
datos_prueba <- Data3[-indice_particion, ]

Se ajusta el modelo con la muestra de entrenamiento del 70%.

modelo_entrenamiento <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
                             banios, data = datos_entrenamiento)

Por medio de la función summary se estiman los resultados del modelo de entrenamiento.

summary(modelo_entrenamiento)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = datos_entrenamiento)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -767.94  -82.43  -20.27   47.44 1026.16 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -238.0965    35.6840  -6.672 6.68e-11 ***
## areaconst       0.9132     0.0512  17.837  < 2e-16 ***
## estrato        81.8633     8.8550   9.245  < 2e-16 ***
## habitaciones    4.0646     4.8588   0.837    0.403    
## parqueaderos   -2.2614     5.1712  -0.437    0.662    
## banios         24.4086     6.0513   4.034 6.35e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 156.1 on 501 degrees of freedom
## Multiple R-squared:  0.6832, Adjusted R-squared:  0.6801 
## F-statistic: 216.1 on 5 and 501 DF,  p-value: < 2.2e-16

6- Realice predicciones con el modelo anterior usando los datos de prueba (30%).

A continuación, con ayuda de la función predict se predice el modelo con el set de prueba.

# Realiza predicciones con el modelo en el conjunto de prueba
predicciones <- predict(modelo_entrenamiento, newdata = datos_prueba)

Se para comprobar el modelo se muestran las primeras filas de las predicciones realizadas.

head(predicciones)
##        1        2        3        4        5        6 
## 599.1478 351.1711 462.7797 214.6228 404.7525 202.5018

En el código anterior, predict se utiliza para obtener las predicciones del modelo entrenado (modelo entrenamiento) sobre los datos de prueba (datos prueba). El resultado es un vector de predicciones que se puede utilizar para comparar con los valores reales, es decir, La precisión del modelo comparando las predicciones con las respuestas reales. Por ejemplo, se puede calcular el error cuadrático medio (MSE) o el coeficiente de determinación ( r2). esto lo podemos evidenciar en el siguiente código de MSE.

# Calcula el MSE
mse <- mean((datos_prueba$preciom - predicciones)^2)

# Muestra el MSE
print(paste("Error Cuadrático Medio (MSE):", mse))
## [1] "Error Cuadrático Medio (MSE): 28256.6335796622"

7- Calcule el error cuadrático medio, el error absoluto medio y el R2, interprete.

# Cálculo del MSE
mse <- mean((datos_prueba$preciom - predicciones)^2)

# Cálculo del MAE
mae <- mean(abs(datos_prueba$preciom - predicciones))

# Cálculo del R^2
r_cuadrado <- 1 - sum((datos_prueba$preciom - predicciones)^2) / sum((datos_prueba$preciom - mean(datos_prueba$preciom))^2)

# Muestra los resultados
print(paste("Error Cuadrático Medio (MSE):", mse))
## [1] "Error Cuadrático Medio (MSE): 28256.6335796622"
print(paste("Error Absoluto Medio (MAE):", mae))
## [1] "Error Absoluto Medio (MAE): 102.751472496813"
print(paste("Coeficiente de Determinación (R^2):", r_cuadrado))
## [1] "Coeficiente de Determinación (R^2): 0.54532890848541"

Interpretación

MSE (Error Cuadrático Medio): Mide el promedio de los errores al cuadrado entre las predicciones y los valores reales. Cuanto más cercano a cero es mejor. En este caso el valor es de 28256.63 aproximados indicando que el modelo no se ajusta a los datos o que existe un alto grado de variabilidad, si este valor fuera más bajo, el modelo seria capas de predecir con mayor precisión los valores observados.

MAE (Error Absoluto Medio): Mide el promedio de las diferencias absolutas entre las predicciones y los valores reales. en este caso es de 102.75 aproximados y si este valor fuera mas bajo mejor es el ajuste del modelo a los datos.

R2 (Coeficiente de Determinación): Indica la proporción de la variabilidad total en la variable dependiente que es explicada por el modelo. Un R 2 cercano a 1 indica un buen ajuste, mientras que cercano a 0 indica un mal ajuste. En este caso el valor es de 0.54 aproximados indicando que el 54% de la variabilidad en la variable dependiente puede ser explicada por el modelo.