Construir un modelo basado en árboles de regresión y realizar predicciones
Con los datos de precios de casas aplicar un modelo de árboles de regresión y realizar predicciones Fundamento teórico
Los árboles de regresión/clasificación tienen como objetivo predecir la variable respuesta Y en función de covariables. (Hernández, 2020)
Los árboles de regresión permiten al igual que otros modelos de regresión predecir una variable dependiente Y en relación varias variables independentes Xs.
library(rpart)
library(rpart.plot)
## Warning: package 'rpart.plot' was built under R version 4.0.3
library(caret)
## Warning: package 'caret' was built under R version 4.0.3
## Loading required package: lattice
## Loading required package: ggplot2
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(readr)
library(ggplot2)
library(reshape)
## Warning: package 'reshape' was built under R version 4.0.3
##
## Attaching package: 'reshape'
## The following object is masked from 'package:dplyr':
##
## rename
library(knitr)
options(scipen = 999)
datos <- read.csv("https://raw.githubusercontent.com/rpizarrog/FundamentosMachineLearning/master/datos/datos%20precios%20de%20casas.csv", encoding = "UTF-8")
kable(head(datos))
| precio | estacionamientos | recamaras | ba.f1.os | habitaciones | agnio.construccion | construccion | terreno | calle.domicilio | colonia.fraccionamiento | ciudad | descripcion |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1780000 | 2 | 3 | 2 | 5 | 2020 | 169 | 126 | Privada San Fernanda | San Fernando- Durango | Durango | Ubicadas en la salida Mazatl |
| 650000 | 1 | 3 | 1 | 4 | NA | 90 | 90 | Prolongaci |
Centro | Durango | Casa un piso 3 recamaras 2 ba |
| 590000 | 2 | 2 | 2 | 4 | NA | 63 | 90 | Centro | Centro | Durango | Casa un piso bonita 3 recamaras 2 ba |
| 1300000 | 2 | 3 | 2 | 5 | NA | 130 | 120 | Centro | Centro | Durango | Casa en venta nueva |
| 1000000 | 2 | 2 | 1 | 3 | NA | 110 | 160 | Centro | Centro | Durango | Bonita casa en dos pisos dise |
| 465000 | 2 | 3 | 1 | 4 | NA | 53 | 89 | Centro | Centro | Durango | Bonita casa con 2 recamras un ba |
datos <- datos[,c(1,2,3,4,7,8)]
names(datos)[4] <- c("banio")
datos <- mutate(datos, estacionamientos = ifelse(is.na(estacionamientos) ,0,estacionamientos ))
datos <- mutate(datos, construccion = ifelse(is.na(construccion),mean(construccion, na.rm = TRUE),construccion ))
kable(head(datos), caption = "Los datos")
| precio | estacionamientos | recamaras | banio | construccion | terreno |
|---|---|---|---|---|---|
| 1780000 | 2 | 3 | 2 | 169 | 126 |
| 650000 | 1 | 3 | 1 | 90 | 90 |
| 590000 | 2 | 2 | 2 | 63 | 90 |
| 1300000 | 2 | 3 | 2 | 130 | 120 |
| 1000000 | 2 | 2 | 1 | 110 | 160 |
| 465000 | 2 | 3 | 1 | 53 | 89 |
70 % datos de entrenamiento
30 % datos de validación
set.seed(2020)
entrena <- createDataPartition(y = datos$precio, p = 0.7, list = FALSE, times = 1)
# Datos entrenamiento
datos.entrenamiento <- datos[entrena, ] # [renglones, columna]
# Datos validación
datos.validacion <- datos[-entrena, ]
kable(head(datos.entrenamiento, 10), caption = "Datos de entrenamiento (primeros diez)", row.names = 1:nrow(datos.entrenamiento))
## Warning in if (is.na(row.names)) row.names = has_rownames(x): la condición tiene
## longitud > 1 y sólo el primer elemento será usado
## Warning in if (row.names) {: la condición tiene longitud > 1 y sólo el primer
## elemento será usado
| precio | estacionamientos | recamaras | banio | construccion | terreno | |
|---|---|---|---|---|---|---|
| 2 | 650000 | 1 | 3 | 1 | 90.0000 | 90 |
| 3 | 590000 | 2 | 2 | 2 | 63.0000 | 90 |
| 4 | 1300000 | 2 | 3 | 2 | 130.0000 | 120 |
| 5 | 1000000 | 2 | 2 | 1 | 110.0000 | 160 |
| 7 | 780000 | 2 | 1 | 1 | 84.0000 | 90 |
| 8 | 464520 | 0 | 2 | 1 | 47.0000 | 98 |
| 10 | 580000 | 0 | 3 | 1 | 65.0000 | 103 |
| 11 | 1550000 | 2 | 3 | 2 | 155.0000 | 126 |
| 12 | 640000 | 0 | 2 | 1 | 151.1156 | 90 |
| 14 | 480000 | 0 | 2 | 1 | 53.0000 | 90 |
kable(tail(datos.entrenamiento, 10), caption = "Datos de entrenamiento (ultimos diez)", row.names = 1:nrow(datos.entrenamiento))
## Warning in if (is.na(row.names)) row.names = has_rownames(x): la condición tiene
## longitud > 1 y sólo el primer elemento será usado
## Warning in if (row.names) {: la condición tiene longitud > 1 y sólo el primer
## elemento será usado
| precio | estacionamientos | recamaras | banio | construccion | terreno | |
|---|---|---|---|---|---|---|
| 39 | 1290000 | 0 | 2 | 1.0 | 160.0 | 132 |
| 40 | 585000 | 0 | 2 | 1.0 | 52.4 | 90 |
| 41 | 8200000 | 1 | 4 | 4.0 | 512.0 | 512 |
| 42 | 2300000 | 2 | 3 | 2.0 | 242.0 | 200 |
| 43 | 720000 | 1 | 3 | 1.0 | 66.0 | 128 |
| 44 | 1750000 | 1 | 3 | 2.0 | 154.0 | 130 |
| 46 | 1400000 | 1 | 3 | 1.5 | 100.0 | 184 |
| 47 | 2850000 | 2 | 4 | 3.0 | 208.0 | 235 |
| 48 | 1455000 | 2 | 3 | 2.5 | 148.0 | 112 |
| 50 | 462000 | 1 | 2 | 1.0 | 90.0 | 47 |
set.seed(2020)
modelo <- rpart(formula = precio ~ ., data = datos.entrenamiento)
modelo
## n= 38
##
## node), split, n, deviance, yval
## * denotes terminal node
##
## 1) root 38 81930710000000 1572540.0
## 2) construccion< 205.5 30 6480123000000 991950.7
## 4) construccion< 152.5578 23 1930233000000 807892.2
## 8) construccion< 96.5 12 116237700000 603043.3 *
## 9) construccion>=96.5 11 761104500000 1031364.0 *
## 5) construccion>=152.5578 7 1210533000000 1596714.0 *
## 3) construccion>=205.5 8 27416120000000 3749750.0 *
prp(modelo, type = 2, nn = TRUE,
fallen.leaves = TRUE, faclen = 4,
varlen = 8, shadow.col = "gray")
prediccion <- predict(object = modelo, newdata = datos.validacion)
predicciones <- data.frame(datos.validacion, prediccion)
kable(predicciones)
| precio | estacionamientos | recamaras | banio | construccion | terreno | prediccion | |
|---|---|---|---|---|---|---|---|
| 1 | 1780000 | 2 | 3 | 2.0 | 169.00 | 126 | 1596714.3 |
| 6 | 465000 | 2 | 3 | 1.0 | 53.00 | 89 | 603043.3 |
| 9 | 660000 | 0 | 3 | 1.0 | 73.00 | 112 | 603043.3 |
| 13 | 2350000 | 2 | 3 | 2.5 | 194.56 | 203 | 1596714.3 |
| 16 | 1000000 | 2 | 3 | 2.0 | 110.00 | 120 | 1031363.6 |
| 23 | 660000 | 0 | 3 | 1.0 | 73.00 | 112 | 603043.3 |
| 25 | 1750000 | 1 | 3 | 2.0 | 154.00 | 130 | 1596714.3 |
| 32 | 2100000 | 0 | 4 | 2.0 | 151.00 | 151 | 1031363.6 |
| 34 | 640000 | 1 | 2 | 1.0 | 60.00 | 90 | 603043.3 |
| 35 | 462000 | 1 | 2 | 1.0 | 47.00 | 90 | 603043.3 |
| 45 | 960000 | 1 | 3 | 2.0 | 162.00 | 90 | 1596714.3 |
| 49 | 1200000 | 1 | 3 | 1.5 | 115.00 | 112 | 1031363.6 |
| 51 | 3450000 | 2 | 3 | 2.0 | 200.00 | 280 | 1596714.3 |
estacionamientos <- 2
recamaras <- 3
banio <- 2
construccion <- 250
terreno = 201
nuevos.datos <- data.frame(estacionamientos=estacionamientos,recamaras=recamaras, banio=banio, construccion=construccion,terreno=terreno)
prediccion <- predict(object = modelo,
newdata = nuevos.datos)
paste("El valor del precio predicho es: ", round(prediccion, 2))
## [1] "El valor del precio predicho es: 3749750"
La limpieza de los datos es fundamental para utilizar menos variables y poderlas visualizar de una manera mas ordenada.
La prediccion de los datos la utilizamos para comenzar a generar el modelo de regresion basandonos en el entrenamiento y la validacion de 70 y 30.
La libreria rpart genera lo que es el modelo con la variable dependiente Precio y las demas variables como independientes.
El arbol a simple vista no es muy comprensible por lo cual con la prediccion de los valores en la tabla se puede mostrar mejor el modelo y se puede validar por medio de los datos una estadistica de los valores independientes respecto a la variable dependiente.
La prediccion de los valores se encuenta muy cercana a el precio especifico con una diferencia mu poca de probabilidad.
Que nos facilita el comenzar a predecir los valores de nuevos registros agregando nuevos valores y checando la prediccion de aproximadamente ek 80% de resultado estadistico total.