Análisis de vehículos vendidos por Ebay en Alemania


Librerías a utilizar

library(tidyverse)
library(htmlTable)
library(kableExtra)
library(knitr)
library(rmdformats)
library(lubridate)
library(modeest)
library(corrplot)
library(dummies)
library(FNN)
library(caret)
library(rpart)
library(rpart.plot)

Dataset a utilizar

Más de 370000 automóviles usados tomados de la base de datos de Ebay-Kleinanzeigen. El contenido de los datos está en alemán, en caso de querer traducir los nombres de los carros.

Dataset tomado de la web https://www.kaggle.com/orgesleka/used-cars-database#autos.csv, para el ejercicio

Como se puede observar este dataset tiene 189349 observaciones y 20 variables


Exploración de los datos

En esta fase se pretende definir que datos son relevantes para el análisis. la idea es simplificar el dataset con la menor perdida de información

Nombres de los campos del dataset:

  • dateCrawled : Cuando este anuncio se rastreó por primera vez, todos los valores de campo se toman de esta fecha
  • Name : Nombre del carro
  • Seller : Privado o distribuidor
  • OfferType : Tipo de oferta
  • Price : El precio en el anuncio para vender el coche.
  • Abtest: Prueba AB
  • VehicleType: Tipo de vehículo
  • YearOfRegistration: En qué año se registró por primera vez el automóvil.
  • Gearbox: Tipo de trasmisión
  • PowerPS : Potencia del vehículo
  • Model: Modelo
  • Kilometer : Cuantos kilómetros el carro se a conducido
  • MonthOfRegistration : En qué mes se registró por primera vez el coche.
  • FuelType: Tipo de combustible
  • Brand: Marca
  • NotRepairedDamage : Si el auto tiene un daño que aún no ha sido reparado.
  • DateCreated : La fecha para la cual se creó el anuncio en eBay.
  • NrOfPictures : Número de imágenes en el anuncio (des afortunadamente, este campo contiene un 0 en todas partes y, por lo tanto, es inútil (error en el rastreador))
  • PostalCode: Código postal
  • LastSeenOnline : Cuando el rastreador vio este último anuncio en línea

Dado que el campo NrOfPictures tiene valor 0 se procede a borrar del dataset, también la variable X pues solo es el consecutivo de los datos al descargar la base de datos.

summary(df_autos$nrOfPictures)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       0       0       0       0       0       0
summary(df_autos$X)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       1   47338   94675   94675  142012  189349
df_autos$nrOfPictures = NULL
df_autos$X = NULL

Para saber la estructura de cada uno de los datos se procede a realizar un resumen de cada variable:

summary(df_autos)
##               dateCrawled            seller         offerType     
##  2016-03-08 15:50:29:     5   gewerblich:     2   Angebot:189341  
##  2016-03-20 16:50:22:     5   privat    :189347   Gesuch :     8  
##  2016-03-26 10:51:07:     5                                       
##  2016-03-31 17:57:07:     5                                       
##  2016-04-02 14:50:21:     5                                       
##  2016-03-05 15:48:41:     4                                       
##  (Other)            :189320                                       
##      price              abtest          vehicleType    yearOfRegistration
##  Min.   :       0   control:91131   limousine :48701   Min.   :1000      
##  1st Qu.:    1150   test   :98218   kleinwagen:40759   1st Qu.:1999      
##  Median :    2950                   kombi     :34498   Median :2003      
##  Mean   :   10895                             :19437   Mean   :2005      
##  3rd Qu.:    7200                   bus       :15532   3rd Qu.:2008      
##  Max.   :99999999                   cabrio    :11668   Max.   :9999      
##                                     (Other)   :18754                     
##       gearbox          powerPS            model          kilometer     
##           : 10395   Min.   :    0.0   golf   : 15286   Min.   :  5000  
##  automatik: 39220   1st Qu.:   70.0   andere : 13453   1st Qu.:125000  
##  manuell  :139734   Median :  105.0   3er    : 10528   Median :150000  
##                     Mean   :  114.7          : 10398   Mean   :125640  
##                     3rd Qu.:  150.0   polo   :  6714   3rd Qu.:150000  
##                     Max.   :19208.0   corsa  :  6415   Max.   :150000  
##                                       (Other):126555                   
##  monthOfRegistration    fuelType                brand       notRepairedDamage
##  Min.   : 0.000      benzin :114106   volkswagen   :40687       : 36542      
##  1st Qu.: 3.000      diesel : 54968   bmw          :20545   ja  : 18410      
##  Median : 6.000             : 16936   opel         :20427   nein:134397      
##  Mean   : 5.733      lpg    :  2732   mercedes_benz:17931                    
##  3rd Qu.: 9.000      cng    :   308   audi         :16676                    
##  Max.   :12.000      hybrid :   142   ford         :13093                    
##                      (Other):   157   (Other)      :59990                    
##               dateCreated       postalCode                   lastSeen     
##  2016-04-03 00:00:00:  7392   Min.   : 1067   2016-04-07 00:46:04:    14  
##  2016-04-04 00:00:00:  7185   1st Qu.:30559   2016-04-06 04:17:47:    12  
##  2016-03-20 00:00:00:  6860   Median :49661   2016-04-06 05:44:34:    12  
##  2016-03-12 00:00:00:  6853   Mean   :50892   2016-04-06 08:15:55:    12  
##  2016-03-21 00:00:00:  6843   3rd Qu.:71577   2016-04-06 09:46:11:    12  
##  2016-03-14 00:00:00:  6691   Max.   :99998   2016-04-06 09:46:51:    12  
##  (Other)            :147525                   (Other)            :189275
df_autos_copy = df_autos # se realiza una copia del dataset para manipular sin afectar la información inicial

Para identificar las características de calidad de los datos se realiza un pequeño análisis exploratorio de los datos por cada variable a analizar:

Análisis variable dateCrawled

dateCrawled: Cuando este anuncio se rastreó por primera vez, todos los valores de campo se toman de esta fecha

  • Tipo de variable: Fecha
  • Requiere transformación: Si a formato fecha estándar
  • Rango: 2016-03-05 hasta 2016-04-07
  • Datos perdidos N/A: No tiene

Se procede a convertir a formato estándar de R de fecha y a realizar un histograma de la variable

##         Min.      1st Qu.       Median         Mean      3rd Qu.         Max. 
## "2016-03-05" "2016-03-13" "2016-03-21" "2016-03-20" "2016-03-29" "2016-04-07"

Análisis variable seller

seller: Privado o distribuidor son las categorías y define quien fue el que vendió el vehículo una persona natural o un distribuidor especializado

  • Tipo de variable: String
  • Requiere transformación: Categórica
  • Rango: Dos categorías
  • Datos perdidos N/A: No tiene
  • Comentario: No útil, de una categoría se tiene 2 observaciones de la otra 189347 observaciones
## gewerblich     privat 
##          2     189347

Análisis variable offerType

offerType: Tipo de oferta, oferta o petición

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: Solo dos categorías
  • Datos perdidos N/A: No tiene
  • Comentario: No útil, de una categoría se tiene 8 observaciones de la otra 189341 observaciones
## Angebot  Gesuch 
##  189341       8

Análisis variable price

price: El precio en el anuncio para vender el vehículo.

  • Tipo de variable: Numérica
  • Requiere transformación: No
  • Rango: 0 - 99999999
  • Datos perdidos N/A: No tiene
  • Comentario: Útil, esta es la variable a predecir pero no es lógico tener un vehículo. de valor 0, por otro lado el valor máximo es atípico para un vehículo. estándar se debe validar el tratamiento a estos valores
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##        0     1150     2950    10895     7200 99999999

Como se puede observar existen algunos variables atípicos en el price, para esto se transformar el eje Y en escala logarítmica y se restringió la escala hasta €200.000

##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##        0     1150     2950    10895     7200 99999999
## Warning: Removed 87 rows containing non-finite values (stat_bin).
## Warning: Transformation introduced infinite values in continuous y-axis
## Warning: Removed 211 rows containing missing values (geom_bar).

Análisis variable Prueba AB

Abtest: Prueba AB

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: Solo dos categorías
  • Datos perdidos N/A: No tiene
  • Comentario: Útil, las categorías están casi repartidas en un 45% - 55%, pero se debe investigar más sobre esta prueba y su incidencia en la venta de vehículos
## control    test 
##   91131   98218

Análisis variable vehicleType

vehicleType: Tipo de vehículo

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: , coupe, suv, kleinwagen, limousine, cabrio, bus, kombi, andere
  • Datos perdidos: 19437
  • Comentario: Útil, esta es la variable al se categórica nominal puede servir para establecerla como parámetro del modelo, en función que según el tipo de carro el valor es proporcional
##                andere        bus     cabrio      coupe kleinwagen      kombi 
##      19437       1708      15532      11668       9635      40759      34498 
##  limousine        suv 
##      48701       7411

Categoría Traducción
andere otro
bus autobús
cabrio descapotable
coupé coupe
kleinwagen pequeño
kombi minibus
limousine sedan
SUV utilitario

Análisis variable yearOfRegistration

yearOfRegistration: En qué año se registró por primera vez el automóvil

  • Tipo de variable: Fecha
  • Requiere transformación: Si a formato fecha estándar
  • Rango:1000 hasta 9999
  • Datos perdidos: N/A No tiene
  • Comentario:El rango que presenta la variable no es lógico dada la fecha de invención del primer automóvil y la fecha mas grande es en el futuro se debe validar
summary(df_autos_copy$yearOfRegistration)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1000    1999    2003    2005    2008    9999
ggplot(data = df_autos_copy, mapping = aes(df_autos_copy$yearOfRegistration)) +
  geom_histogram(bins = 500, fill = "gray72", color = "gray60") +
  scale_x_continuous(limits = c(0, 10000)) +
  ggtitle("Histograma frecuencia variable yearOfRegistration") +
  labs(x = "Año", y = "Frecuencia") 
## Warning: Removed 2 rows containing missing values (geom_bar).

Análisis variable Gearbox

Gearbox: Tipo de trasmisión

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: Dos categorías
  • Datos perdidos N/A: Tiene 10395
summary(df_autos_copy$gearbox)
##           automatik   manuell 
##     10395     39220    139734
ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$gearbox)) +
  geom_bar(fill = "gray72", color = "gray60") +
  ggtitle("Categorías variable gearbox") +
  labs(x = "Tipos de transmisión", y = "Cantidad de anuncios")

Categoría Traducción
automatik automática
manuell manual

Análisis variable powerPS

powerPS: Potencia del vehículo

  • Tipo de variable: Numérica
  • Requiere transformación: No
  • Rango: 0 - 19210
  • Datos perdidos N/A: No tiene
  • Comentario: Útil, no es lógico tener un vehículo. de potencia 0, por otro lado el valor máximo es atípico para un vehículo. estándar se debe validar el tratamiento a estos valores
summary(df_autos_copy$powerPS)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     0.0    70.0   105.0   114.7   150.0 19208.0
ggplot(data = df_autos_copy, mapping = aes(x = 1:length(row.names(df_autos_copy)), y = df_autos_copy$powerPS)) +
  geom_point(fill = "gray72", color = "gray60") +
  ggtitle("Distribución variable powerPS") +
  labs(x = "Consecutivo", y = "Potencia")

Análisis variable model

model: Modelo, pero analizarlo la información hace referencia a la marca del vehículo

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: 251
  • Datos perdidos N/A: No tiene
  • Comentario: Esta variable muestra que no hay vehículos nuevos en los datos
summary(df_autos_copy$model)
##        golf      andere         3er                    polo       corsa 
##       15286       13453       10528       10398        6714        6415 
##       astra      passat          a4    c_klasse         5er    e_klasse 
##        5484        5293        5169        4488        4311        3908 
##          a3          a6       focus      fiesta transporter      twingo 
##        3372        3057        3015        2938        2860        2494 
##     2_reihe      fortwo      vectra    a_klasse         1er      mondeo 
##        2487        2265        2173        2145        1962        1904 
##        clio     3_reihe      touran       punto      zafira      megane 
##        1814        1807        1785        1712        1569        1514 
##          ka       ibiza        lupo     x_reihe     octavia      cooper 
##        1346        1340        1308        1153        1146        1083 
##       fabia         clk       micra       caddy      sharan          80 
##        1074         933         881         842         838         819 
##      scenic      laguna         slk       omega        leon          tt 
##         744         706         699         698         697         692 
##     1_reihe     6_reihe       civic     i_reihe      galaxy         7er 
##         688         668         655         619         597         580 
##    m_klasse       yaris    mx_reihe          a5    s_klasse      meriva 
##         577         538         537         523         519         511 
##        vito      kangoo         911         500    b_klasse      escort 
##         509         502         494         473         471         464 
##      tiguan        colt         one       arosa      beetle     z_reihe 
##         462         452         449         446         445         436 
##         v40        bora    berlingo    sprinter     transit       tigra 
##         435         434         425         418         407         401 
##         fox     touareg       swift          sl       c_max    seicento 
##         394         381         364         357         341         341 
##    insignia     corolla       panda     4_reihe         v70          a1 
##         339         334         330         326         324         323 
##    scirocco       stilo         147      espace      almera          a8 
##         313         310         307         306         302         299 
##     primera       grand         156     (Other) 
##         298         294         289       18023
length(unique(df_autos_copy$model))
## [1] 251

Análisis variable kilometer

kilometer Cuantos kilómetros el carro se a conducido

  • Tipo de variable: Numérica
  • Requiere transformación: No
  • Rango: 5000 - 150000
  • Datos perdidos N/A: No tiene
  • Comentario: Esta variable muestra que la mayoría de los vehículos son usados y la mayoría tienen mas de 100000 kilómetros
summary(df_autos_copy$kilometer)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    5000  125000  150000  125640  150000  150000
ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$kilometer)) +
  geom_histogram(fill = "gray72", color = "gray60", bins = 20) +
  ggtitle("Distribución variable kilometer") +
  labs(x = "Consecutivo", y = "Kilometraje")

### Análisis variable monthOfRegistration

monthOfRegistration En qué mes se registró por primera vez el vehículo

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: 1 - 12
  • Datos perdidos N/A: No tiene
  • Comentario: Se puede apreciar que a principio de año se realizan mas anuncios que en el segundo semestre del año esta variable puede influir en la venta del vehículo se debe revisar
summary(df_autos_copy$monthOfRegistration)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.000   3.000   6.000   5.733   9.000  12.000
ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$monthOfRegistration)) +
  geom_bar(fill = "gray72", color = "gray60") +
  ggtitle("Categorías variable monthOfRegistration") +
  labs(x = "Mes de registro", y = "Cantidad de anuncios")

### Análisis variable FuelType

FuelType Tipo de combustible

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: 1 - 12
  • Datos perdidos N/A: 16936
  • Comentario: Ninguno
summary(df_autos_copy$fuelType)
##          andere  benzin     cng  diesel elektro  hybrid     lpg 
##   16936     114  114106     308   54968      43     142    2732
ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$fuelType)) +
  geom_bar(fill = "gray72", color = "gray60") +
  ggtitle("Categorías variable fuelType") +
  labs(x = "Tipo de combustible", y = "Cantidad de anuncios")

Categoría Traducción
andere otro
benzin gasolina
cng gas natural
diesel diesel
elektro eléctrico
hybrid hibrido
lpg gas licuado de petroleo

Análisis variable brand

brand Marca

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: 40 categorías
  • Datos perdidos N/A: No tiene
  • Comentario: Ninguno
summary(df_autos_copy$brand)
##     alfa_romeo           audi            bmw      chevrolet       chrysler 
##           1186          16676          20545            924            745 
##        citroen          dacia         daewoo       daihatsu           fiat 
##           2635            455            283            400           4938 
##           ford          honda        hyundai         jaguar           jeep 
##          13093           1429           1830            303            407 
##            kia           lada         lancia     land_rover          mazda 
##           1280             98            243            389           2945 
##  mercedes_benz           mini     mitsubishi         nissan           opel 
##          17931           1708           1522           2564          20427 
##        peugeot        porsche        renault          rover           saab 
##           5697           1144           9146            262            261 
##           seat          skoda          smart sonstige_autos         subaru 
##           3532           2922           2759           1984            403 
##         suzuki         toyota        trabant     volkswagen          volvo 
##           1195           2385            295          40687           1721
length(unique(df_autos_copy$brand))
## [1] 40

Análisis variable notRepairedDamage

notRepairedDamage Si el auto tiene un daño que aún no ha sido reparado

  • Tipo de variable: Categórica
  • Requiere transformación: No
  • Rango: Dos categorías
  • Datos perdidos N/A: 36542
  • Comentario: Se debe determinar si es útil esta variable
summary(df_autos_copy$notRepairedDamage)
##            ja   nein 
##  36542  18410 134397
ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$notRepairedDamage)) +
  geom_bar(fill = "gray72", color = "gray60") +
  ggtitle("Categorías variable notRepairedDamage") +
  labs(x = "ja = sí nein = no", y = "Cantidad de anuncios")

Análisis variable dateCreated

dateCreated La fecha para la cual se creó el anuncio en eBay.

  • Tipo de variable: Fecha
  • Requiere transformación: si al formato estándar
  • Rango: No esta en el formato estándar no se pudo determinar
  • Datos perdidos N/A: No tiene
  • Comentario: Se debe tener cuidado por su parecido la nombre de la variable dateCrawled, se debe analizar si es necesario cambiar el nombre
summary(df_autos_copy$dateCreated)
## 2014-03-10 00:00:00 2015-03-20 00:00:00 2015-08-10 00:00:00 2015-09-04 00:00:00 
##                   1                   1                   1                   2 
## 2015-10-14 00:00:00 2015-11-12 00:00:00 2015-11-13 00:00:00 2015-11-23 00:00:00 
##                   1                   1                   1                   1 
## 2015-11-24 00:00:00 2015-12-05 00:00:00 2015-12-17 00:00:00 2015-12-30 00:00:00 
##                   1                   1                   1                   2 
## 2016-01-02 00:00:00 2016-01-03 00:00:00 2016-01-07 00:00:00 2016-01-08 00:00:00 
##                   3                   1                   2                   1 
## 2016-01-10 00:00:00 2016-01-13 00:00:00 2016-01-17 00:00:00 2016-01-18 00:00:00 
##                   3                   2                   2                   2 
## 2016-01-19 00:00:00 2016-01-22 00:00:00 2016-01-23 00:00:00 2016-01-25 00:00:00 
##                   3                   1                   1                   2 
## 2016-01-26 00:00:00 2016-01-27 00:00:00 2016-01-28 00:00:00 2016-01-29 00:00:00 
##                   2                   2                   5                   4 
## 2016-01-30 00:00:00 2016-01-31 00:00:00 2016-02-01 00:00:00 2016-02-02 00:00:00 
##                   5                   2                   1                   6 
## 2016-02-03 00:00:00 2016-02-04 00:00:00 2016-02-05 00:00:00 2016-02-06 00:00:00 
##                   3                   1                   5                   2 
## 2016-02-07 00:00:00 2016-02-08 00:00:00 2016-02-09 00:00:00 2016-02-10 00:00:00 
##                   7                   2                   4                   4 
## 2016-02-11 00:00:00 2016-02-12 00:00:00 2016-02-13 00:00:00 2016-02-14 00:00:00 
##                   3                   6                   4                   6 
## 2016-02-15 00:00:00 2016-02-16 00:00:00 2016-02-17 00:00:00 2016-02-18 00:00:00 
##                   3                   5                   1                  13 
## 2016-02-19 00:00:00 2016-02-20 00:00:00 2016-02-21 00:00:00 2016-02-22 00:00:00 
##                   7                   6                  12                   3 
## 2016-02-23 00:00:00 2016-02-24 00:00:00 2016-02-25 00:00:00 2016-02-26 00:00:00 
##                   3                  11                   8                  12 
## 2016-02-27 00:00:00 2016-02-28 00:00:00 2016-02-29 00:00:00 2016-03-01 00:00:00 
##                  14                  26                  29                  26 
## 2016-03-02 00:00:00 2016-03-03 00:00:00 2016-03-04 00:00:00 2016-03-05 00:00:00 
##                  21                 196                 319                4254 
## 2016-03-06 00:00:00 2016-03-07 00:00:00 2016-03-08 00:00:00 2016-03-09 00:00:00 
##                2945                6506                6314                6351 
## 2016-03-10 00:00:00 2016-03-11 00:00:00 2016-03-12 00:00:00 2016-03-13 00:00:00 
##                6196                6223                6853                3183 
## 2016-03-14 00:00:00 2016-03-15 00:00:00 2016-03-16 00:00:00 2016-03-17 00:00:00 
##                6691                6321                5685                5944 
## 2016-03-18 00:00:00 2016-03-19 00:00:00 2016-03-20 00:00:00 2016-03-21 00:00:00 
##                2662                6566                6860                6843 
## 2016-03-22 00:00:00 2016-03-23 00:00:00 2016-03-24 00:00:00 2016-03-25 00:00:00 
##                6014                6074                5602                6278 
## 2016-03-26 00:00:00 2016-03-27 00:00:00 2016-03-28 00:00:00 2016-03-29 00:00:00 
##                6052                5689                6627                6591 
## 2016-03-30 00:00:00 2016-03-31 00:00:00 2016-04-01 00:00:00 2016-04-02 00:00:00 
##                6373                6085                6446                6614 
## 2016-04-03 00:00:00 2016-04-04 00:00:00 2016-04-05 00:00:00 2016-04-06 00:00:00 
##                7392                7185                2224                 576 
## 2016-04-07 00:00:00 
##                 304

Análisis variable postalCode

postalCode Código postal

  • Tipo de variable: Ubicación
  • Requiere transformación: Es probable tener que convertir a longitud y latitud
  • Rango: 1067 - 100000
  • Datos perdidos N/A: No tiene
  • Comentario: Es probable tener que pasar esta variable a formato de longitud y latitud
summary(df_autos_copy$postalCode)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1067   30559   49661   50892   71577   99998

Análisis variable lastSeen

lastSeen cuando el rastreador vio este último anuncio en línea

  • Tipo de variable: Fecha
  • Requiere transformación: Si a formato fecha estándar
  • Rango: No esta en el formato adecuado no se pudo determinar
  • Datos perdidos N/A: No tiene
  • Comentario: Se debe validar si esta variable aporta al modelo
summary(df_autos_copy$lastSeen)
## 2016-04-07 00:46:04 2016-04-06 04:17:47 2016-04-06 05:44:34 2016-04-06 08:15:55 
##                  14                  12                  12                  12 
## 2016-04-06 09:46:11 2016-04-06 09:46:51 2016-04-06 11:46:06 2016-04-06 13:46:26 
##                  12                  12                  12                  12 
## 2016-04-07 02:16:06 2016-04-07 04:16:52 2016-04-07 05:17:16 2016-04-07 07:44:31 
##                  12                  12                  12                  12 
## 2016-04-07 08:16:23 2016-04-07 11:15:53 2016-04-05 23:45:22 2016-04-06 00:16:25 
##                  12                  12                  11                  11 
## 2016-04-06 03:45:06 2016-04-06 04:17:44 2016-04-06 05:15:52 2016-04-06 05:45:20 
##                  11                  11                  11                  11 
## 2016-04-06 06:44:38 2016-04-06 06:45:16 2016-04-06 07:15:39 2016-04-06 07:16:20 
##                  11                  11                  11                  11 
## 2016-04-06 07:46:16 2016-04-06 08:15:19 2016-04-06 09:16:18 2016-04-06 09:44:39 
##                  11                  11                  11                  11 
## 2016-04-06 10:18:01 2016-04-06 10:45:16 2016-04-06 11:17:08 2016-04-06 12:45:55 
##                  11                  11                  11                  11 
## 2016-04-06 15:16:40 2016-04-06 15:18:06 2016-04-06 22:15:41 2016-04-06 22:17:44 
##                  11                  11                  11                  11 
## 2016-04-06 22:17:58 2016-04-06 22:44:36 2016-04-06 23:15:54 2016-04-07 00:46:01 
##                  11                  11                  11                  11 
## 2016-04-07 03:44:24 2016-04-07 03:46:16 2016-04-07 05:16:42 2016-04-07 06:16:46 
##                  11                  11                  11                  11 
## 2016-04-07 07:15:24 2016-04-07 07:15:37 2016-04-07 07:16:19 2016-04-07 07:17:11 
##                  11                  11                  11                  11 
## 2016-04-07 07:45:37 2016-04-07 07:46:01 2016-04-07 08:15:24 2016-04-07 08:15:40 
##                  11                  11                  11                  11 
## 2016-04-07 08:17:28 2016-04-07 09:15:47 2016-04-07 09:16:10 2016-04-07 11:15:52 
##                  11                  11                  11                  11 
## 2016-04-07 11:16:02 2016-04-07 11:45:57 2016-04-07 12:17:44 2016-04-05 14:15:38 
##                  11                  11                  11                  10 
## 2016-04-05 14:17:48 2016-04-05 14:46:29 2016-04-05 15:16:08 2016-04-05 15:16:44 
##                  10                  10                  10                  10 
## 2016-04-05 16:44:22 2016-04-05 16:44:44 2016-04-05 16:44:47 2016-04-05 16:45:17 
##                  10                  10                  10                  10 
## 2016-04-05 16:46:28 2016-04-05 18:18:01 2016-04-05 21:17:38 2016-04-05 22:45:02 
##                  10                  10                  10                  10 
## 2016-04-05 22:45:23 2016-04-05 23:46:07 2016-04-06 00:15:21 2016-04-06 00:15:54 
##                  10                  10                  10                  10 
## 2016-04-06 00:45:02 2016-04-06 00:45:05 2016-04-06 00:46:07 2016-04-06 01:16:21 
##                  10                  10                  10                  10 
## 2016-04-06 01:16:26 2016-04-06 01:16:39 2016-04-06 01:17:03 2016-04-06 01:17:04 
##                  10                  10                  10                  10 
## 2016-04-06 01:17:26 2016-04-06 01:47:20 2016-04-06 02:15:57 2016-04-06 02:16:36 
##                  10                  10                  10                  10 
## 2016-04-06 02:17:23 2016-04-06 02:45:18 2016-04-06 02:46:53 2016-04-06 03:15:27 
##                  10                  10                  10                  10 
## 2016-04-06 03:15:29 2016-04-06 03:16:38 2016-04-06 03:17:28 2016-04-06 03:45:15 
##                  10                  10                  10                  10 
## 2016-04-06 03:45:26 2016-04-06 03:45:52 2016-04-06 03:45:55             (Other) 
##                  10                  10                  10              188284

Conclusiones iniciales de los datos

  1. En la variable yearOfRegistration se puede apreciar errores en la digitalización de los datos debido al rango que tiene desde 1000 a 9999
  2. Se puede apreciar que en los datos no existen vehículos nuevos por el rango de kilómetros recorridos que va de 5000 a 15000Se puede apreciar que en los datos no existen vehículos nuevos por el rango de kilómetros recorridos que va de 5000 a 150000
  3. La mayoría de las variables tienen datos no disponibles (N/A), por tanto es necesario determinar una técnica para su tratamiento con la perdida mínima de información
  4. Las variables offertType y seller en el 95% de los casos solo tiene una categoría es decir que no aportan al análisis información relevante
  5. La variable name no esta codificada en UTF-8 esto puede generar problemas en el tratamiento de los datos y en la publicación si se hace en formato html por tanto se debe convertir
  6. El rango de la variable price de 0 a 100000000, puede segar el análisis dado que los vehículos estándar están muy por debajo de € 100000000 y un valor de € 0 posiblemente sea un error en la toma de los datos
  7. La variable nrOfPictures no aporta nada al análisis pues su valor siempre es 0, por tanto se podría borrar del dataset

Revisión de la correlación entre las variables

Para verificar de las 18 variables del dataset se procede a las transformaciones para poder analizar las variables de forma adecuada

Transformación de variables de tipo fecha

Dado que los datos tiene un rango de un mes esta se creará una variable que tenga en cuenta solamente el día de publicación para analizar si tiene correlación en el para el modelo

df_autos_copy$dateCrawled = wday(df_autos_copy$dateCrawled, label = TRUE) # trasformaciòn a día como categoría
df_autos_copy = df_autos_copy[df_autos_copy$yearOfRegistration > 1900 & df_autos_copy$yearOfRegistration < 2016,] # borrado de datos fuera de rango
mod_month = mlv(df_autos_copy$monthOfRegistration, method = "mvf") # calculo de la moda de la variable del mes de registro del vehiculo
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
for (i in 1:length(df_autos_copy$monthOfRegistration)) { # cambio del vlaor 0 por la moda
  if (df_autos_copy[i,12] == 0) {
    df_autos_copy[i,12] = mod_month
  }
}
df_autos_copy$dateCrawled = as.factor(df_autos_copy$dateCrawled)
ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$dateCrawled)) +
  geom_bar(fill = "lemonchiffon3", color = "gray60") +
  ggtitle("Comportamiento de la variable dateCrawled convertida") +
  labs(x = "Fecha de publicación del anuncio", y = "Numero de anuncios por fecha")

ggplot(data = df_autos_copy, mapping = aes(df_autos_copy$yearOfRegistration)) +
  geom_histogram(bins = 500, fill = "lemonchiffon3", color = "gray60") +
  scale_x_continuous(limits = c(1910, 2015)) +
  ggtitle("Histograma variable yearOfRegistration suprimiendo valores fuera de rango") +
  labs(x = "Año", y = "Frecuencia") 
## Warning: Removed 2 rows containing missing values (geom_bar).

Transformación de variables categóricas

En esta parte del análisis se alistaran las variables categóricas para su análisis

Variables a eliminar apriori

df_autos_copy$seller = NULL # esta variable de las dos categorias una solo tiene dos observaciones
df_autos_copy$offerType = NULL # esta variable se elimina dado que una de las categorias solo tiene 8 observaciones
df_autos_copy$notRepairedDamage = NULL # definitivamente los mas probable es qu no de defina si el vehiculo tiene reparaciones o no
df_autos_copy$brand = NULL # esta variable tiene 16936 valores perdidos, que es complejo completar por la cantida de categorias, para este caso no se tien en cuenta pero se sujiere hacer un modelo quitando los NA pero teniendo encuenta las 40 categorias de marca
df_autos_copy$lastSeen = NULL # la variable de la ultima vez que salió el anuncio no es relevante
df_autos_copy$postalCode = NULL # esta variable no aporta a este modelo
df_autos_copy$dateCreated = NULL # esta varible solo determina la fecha de publicación del anuncio

Variables a transformar

mod_vehic = mlv(df_autos_copy$vehicleType, method = "mvf") # cambia por la moda de los datos
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
for (i in 1:length(df_autos_copy$vehicleType)) { # cambio del valor faltante por la moda de los datos
  if (df_autos_copy[i,4] == "") {
    df_autos_copy[i,4] = mod_vehic
  }
}

ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$vehicleType)) +
  geom_bar(fill = "lemonchiffon3", color = "gray60") +
  ggtitle("Variable vehicleType ajustada con valores faltantes") +
  labs(x = "Tipos de vehículos", y = "Cantidad de anuncios")

mod_gear = mlv(df_autos_copy$gearbox, method = "mvf") # cambia por la moda de los datos
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
for (i in 1:length(df_autos_copy$gearbox)) { # cambio del valor faltante por la moda de los datos
  if (df_autos_copy[i,6] == "") {
    df_autos_copy[i,6] = mod_gear
  }
}

ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$gearbox)) +
  geom_bar(fill = "lemonchiffon3", color = "gray60") +
  ggtitle("Variable gearbox sin valores faltantes") +
  labs(x = "Tipos de transmisión", y = "Cantidad de anuncios")

mod_fuel = mlv(df_autos_copy$fuelType, method = "mvf") # cambia por la moda de los datos
## argument 'na.rm' is soft-deprecated, please start using 'na_rm' instead
for (i in 1:length(df_autos_copy$fuelType)) { # cambio del valor faltante por la moda de los datos
  if (df_autos_copy[i,11] == "") {
    df_autos_copy[i,11] = mod_fuel
  }
}

ggplot(data = df_autos_copy, mapping = aes(x = df_autos_copy$fuelType)) +
  geom_bar(fill = "lemonchiffon3", color = "gray60") +
  ggtitle("Variable fuelType sin valores faltantes") +
  labs(x = "Tipo de combustible", y = "Cantidad de anuncios")

La variable model tiene 251 categorias lo cual no permite utilizarla para el objetivo del modelo, por esa razón se elimina del dataset

summary(df_autos_copy$model) 
##        golf      andere         3er                    polo       corsa 
##       13898       12927       10072        8637        6129        5820 
##       astra      passat          a4    c_klasse         5er    e_klasse 
##        5051        5036        5012        4321        4195        3791 
##          a3          a6       focus transporter      fiesta     2_reihe 
##        3079        2957        2795        2729        2707        2374 
##      twingo      fortwo      vectra    a_klasse         1er      mondeo 
##        2236        2146        2002        1899        1888        1808 
##     3_reihe      touran        clio       punto      zafira      megane 
##        1679        1645        1638        1527        1438        1417 
##          ka       ibiza        lupo     x_reihe     octavia      cooper 
##        1237        1236        1202        1120        1110        1047 
##       fabia         clk       micra          80      sharan       caddy 
##        1020         889         818         776         774         758 
##         slk          tt       omega      laguna      scenic     1_reihe 
##         685         673         672         668         665         641 
##        leon     6_reihe     i_reihe       civic    m_klasse         7er 
##         641         633         599         580         565         552 
##      galaxy    mx_reihe          a5       yaris    s_klasse        vito 
##         552         530         510         508         495         484 
##         911         500      tiguan      meriva    b_klasse      kangoo 
##         471         458         453         450         433         432 
##     z_reihe      escort         one        colt        bora      beetle 
##         430         428         422         420         417         411 
##       arosa         v40    berlingo    sprinter       tigra     touareg 
##         408         405         390         376         375         373 
##         fox     transit          sl       swift    insignia         v70 
##         367         365         356         339         333         320 
##     4_reihe    seicento       c_max          a1     corolla       panda 
##         315         315         313         312         311         310 
##    scirocco       grand          a8     qashqai     primera         eos 
##         298         286         285         281         280         278 
##       stilo     avensis      espace     (Other) 
##         278         277         277       17144
df_autos_copy$model = NULL

Variables numéricas con valores fuera de rango

En este paso las variables con valores fuera de rango se van ajustar para poder tener unos valores medianamente normales en el modelo

summary(df_autos_copy$price)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##        0     1200     3000    11151     7500 99999999
ggplot(data = df_autos_copy)+
  geom_boxplot(mapping = aes(y = df_autos_copy$price)) +
  ggtitle("Variable price original") +
  labs(x = "Variable price", y = "Valor")

df_autos_copy = df_autos_copy[df_autos_copy$price > 800 & df_autos_copy$price < 50000,]

ggplot(data = df_autos_copy)+
  geom_boxplot(mapping = aes(y = df_autos_copy$price)) +
  ggtitle("Variable price original") +
  labs(x = "Variable price", y = "Valor")

Con la variable price de tomo un rango de 810, 49999 con el cual quedaron 145435, es decir a la final se pierden únicamente 0

Matriz de correlación

df_autos_copy_p = df_autos_copy
df_autos_copy_p$dateCrawled = as.character(df_autos_copy_p$dateCrawled)
str(df_autos_copy_p$dateCrawled)
##  chr [1:145435] "jue" "lun" "jue" "jue" "vie" "lun" "jue" "sáb" "jue" "mar" ...
df_autos_copy_p$dateCrawled = as.factor(df_autos_copy_p$dateCrawled)
str(df_autos_copy_p$dateCrawled)
##  Factor w/ 7 levels "dom","jue","lun",..: 2 3 2 2 7 3 2 6 2 4 ...
df_autos_copy_dummy_1 = read.csv("../Proyecto_final/df_autos_copy_dummy_A.csv")
df_autos_copy_dummy_1$X = NULL
corrplot(auto_corr_1, method = "shade", # gráfica con cuadrados la correlación
         shade.col = NA, # para que no queden unas líneas 
         tl.col = "black", # color del texto
         tl.srt = 60, # ángulo del texto en la parte superior
         tl.cex = 0.8
         )

Se observa una baja correlación con las variables del día que se publica el anuncio, por esta razón se descarta esa variable; así mismo el mes de registro del anuncio no tiene correlación con el resto de variables

corrplot(auto_corr_2, method = "shade", # gráfica con cuadrados la correlación
         shade.col = NA, # para que no queden unas líneas 
         tl.col = "black", # color del texto
         tl.srt = 60, # ángulo del texto en la parte superior
         tl.cex = 0.8
         )

Modelo a aplicar

Partición de los datos

train_id = createDataPartition(df_autos_copy_dummy_2$price, p = 0.8, list = FALSE)
train_data = df_autos_copy_dummy_2[train_id,]
test_data = df_autos_copy_dummy_2[-train_id,]

Modelo knn para regresión

##Función para automatizar KNN
rda_knn_reg = function(tr_predictor, val_predictors,
                        tr_target, val_target, k){
  res = knn.reg(tr_predictor, val_predictors,
                 tr_target, k, algorithm = "brute") # función knn
  
  rmserror = sqrt(mean((val_target - res$pred)^2)) # calculo del rms
  
  cat(paste("RMSE para k = ", toString(k), ": ", rmserror,"\n", sep = "")) # impresón de los valores en pantalla
  
  rmserror
}

##Funcion para realizar múltiples KNN
rda_knn_reg_multi = function(tr_predictors, val_predictors,
                              tr_target, val_target, start_k, end_k){
  rms_errors = vector() # aqui creo un vector vacio
  
  for(k in start_k:end_k){ # aqui tengo el for para automatizar la funcion
    rms_error = rda_knn_reg(tr_predictors, val_predictors,
                               tr_target, val_target, k)
    
    rms_errors = c(rms_errors, rms_error) # lleno el vector vacio con los datos de la iteración
  }
  plot(rms_errors, type = 'o', xlab = "k", ylab = "RMSE") #plot de los datos
}

rda_knn_reg_multi(train_data[,2:21], test_data[,2:21], 
                  train_data[,1], test_data[,1], 1,10)
## RMSE para k = 1: 0.514735860389275
## RMSE para k = 2: 0.463475516105846
## RMSE para k = 3: 0.444562975314446
## RMSE para k = 4: 0.435723907659413
## RMSE para k = 5: 0.431319653888354
## RMSE para k = 6: 0.428104645167255
## RMSE para k = 7: 0.42618252042859
## RMSE para k = 8: 0.425733490870983
## RMSE para k = 9: 0.42592663127532
## RMSE para k = 10: 0.425735304110126

En este caso el modelo genero un error de 0.5147 con un k de 1

Aplicación del modelo con el k optimo

mod_knn = knn.reg(train_data[,2:21], test_data[,2:21],
                 train_data[,1], k = 1, algorithm = "brute") # función knn

Modelo de árbol de desicion

mod_tree = rpart(price~., data = test_data) # función para crear el arbol de regresión

prp(mod_tree, # el data set creado con rpart
    type = 2, # donde debe estar colocado el titulo del nodo
    nn = TRUE, # numero del nodo
    fallen.leaves = TRUE, # para que los nodos hoja esten abajo y alineados
    faclen = 4, # la longitud de los factores
    varlen = 8, # longitud de las variables
    shadow.col = "gray" # color de fondo
    )

Comparación de los dos modelos

Función para calculo de error cuadrático medio

rmsa = function(actual, predicho){
  return(sqrt(mean((actual - predicho)^2)))
}

Test con modelo árbol de desicion

test_data = as.data.frame(test_data)
predic_tree = predict(mod_tree, test_data)
rmsa_tree = rmsa(predic_tree, test_data$price)

plot(predic_tree[100:200], type = "l", col = "red", xlab="",ylab="", ylim = c(-1, 6),
     main = "Comparación predicho árbol decisión con 100 datos reales")
par(new=TRUE)
plot(test_data[100:200, 1], type = "l", col = "blue", xlab="",ylab="", ylim = c(-1, 6))
legend("topright",col=c("red","blue"),legend =c("Predicho","Real"), lwd=3, bty = "n")

Test con modelo knn

predic_knn = mod_knn$pred
rmsa_knn = rmsa(predic_knn, test_data$price)

plot(predic_knn[100:200], type = "l", col = "red", xlab="",ylab="", ylim = c(-1, 6),
     main = "Comparación predicho knn con 100 datos reales")
par(new=TRUE)
plot(test_data[100:200, 1], type = "l", col = "blue", xlab="",ylab="", ylim = c(-1, 6))
legend("topright",col=c("red","blue"),legend =c("Predicho","Real"), lwd=3, bty = "n")

Resumen de los modelos aplicados

Para este caso los modelos se comportaron de manera similar pero el error cuadrático medios del algoritmo del árbol de decisión fue de 0.5917674, versus 0.5147359 del algoritmo de knn, en conclusión y dado el tiempo de computo el mejor modelo es un árbol de decisión

De igual manera las conclusiones mas relevantes del análisis son:

  • Dada la matriz de correlación el día que se publique no tiene relevancia con el precio del vehículo
  • El modelo se puede simplificar en base a la correlación de las variables
  • Uno de los valores que mas influye en el costo del vehículo es kilometraje, seguido del año de fabricación
  • Los vehículos diessel tienen un valor mas alto
  • La trasmisión automática aumenta el valor del vehículo