Cette article fait suite au premier article sur la découverte des données.
Après avoir identifié nos données, l’étape suivante dans tous projets de machine learning est de “nettoyer la donnée”, ceci afin de la rendre plus facilement exploitable et de supprimer les cas incohérents ou trop marginaux (outliers)
cars <- read.csv("finalcars.csv", sep=",", header=TRUE, stringsAsFactors = FALSE)
stringsAsFactors = FALSE nous permet de désactiver la conversion automatique en Factor, cela nous permet d’éviter des optimisations intempestives et notamment de conserver le millésime (yearModel) en tant qu’entier
- En visualisant le résumé du dataframe, nous observons des NA que nous supprimons :
summary(cars)
## brand model version
## Length:258320 Length:258320 Length:258320
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
##
## yearModel mileage gearbox energy
## Length:258320 Length:258320 Min. : 0.0 Min. : 1.000
## Class :character Class :character 1st Qu.: 2.0 1st Qu.: 2.000
## Mode :character Mode :character Median : 2.0 Median : 2.000
## Mean : 13.7 Mean : 1.905
## 3rd Qu.: 2.0 3rd Qu.: 2.000
## Max. :999999.0 Max. :11.000
## NA's :123 NA's :7
## doors powerDin priceNew price
## Min. : 0.000 Min. : -1 Min. : 0 Min. : 0
## 1st Qu.: 4.000 1st Qu.: 90 1st Qu.: 17200 1st Qu.: 9600
## Median : 5.000 Median : 111 Median : 24000 Median : 13990
## Mean : 4.314 Mean : 65529 Mean : 26400 Mean : 17384
## 3rd Qu.: 5.000 3rd Qu.: 149 3rd Qu.: 31000 3rd Qu.: 20500
## Max. :11.000 Max. :999999 Max. :1076400 Max. :4190000
## NA's :1
cars <- na.exclude(cars) summary(cars)
## brand model version
## Length:258189 Length:258189 Length:258189
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
## yearModel mileage gearbox energy
## Length:258189 Length:258189 Min. :0.00 Min. : 1.000
## Class :character Class :character 1st Qu.:2.00 1st Qu.: 2.000
## Mode :character Mode :character Median :2.00 Median : 2.000
## Mean :1.78 Mean : 1.905
## 3rd Qu.:2.00 3rd Qu.: 2.000
## Max. :2.00 Max. :11.000
## doors powerDin priceNew price
## Min. :0.000 Min. : -1 Min. : 0 Min. : 0
## 1st Qu.:4.000 1st Qu.: 90 1st Qu.: 17200 1st Qu.: 9600
## Median :5.000 Median : 111 Median : 24000 Median : 13990
## Mean :4.315 Mean : 65563 Mean : 26019 Mean : 17370
## 3rd Qu.:5.000 3rd Qu.: 149 3rd Qu.: 31000 3rd Qu.: 20500
## Max. :9.000 Max. :999999 Max. :1076400 Max. :4190000
NA signifie en R que la donnée n’est pas présente (à noter que R possède également un type NULL dont la signification diffère). Il est important d’identifier ces données manquantes pour supprimer chaque ligne incomplète. Nous pouvons nous le permettre car nous avons un volume de données suffisant.
- Affichage de la distribution du prix sous forme d’histogramme :
hist(cars$price)
En l’état, cet histogramme est illisible, nous allons utiliser la notion de quartile pour exclure les données excentriques (outliers).
Les quartiles sont des paquets contenant le même nombre d’observations, peu importe leurs valeurs :
Nous cherchons à visualiser la répartition du prix, nous analysons les quantiles, puis les redécoupons pour en afficher 100.
quantile(cars$price)
## 0% 25% 50% 75% 100%
## 0 9600 13990 20500 4190000
seq(from=0, to=1, by=0.01)
## [1] 0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13
## [15] 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27
## [29] 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41
## [43] 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.50 0.51 0.52 0.53 0.54 0.55
## [57] 0.56 0.57 0.58 0.59 0.60 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69
## [71] 0.70 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.80 0.81 0.82 0.83
## [85] 0.84 0.85 0.86 0.87 0.88 0.89 0.90 0.91 0.92 0.93 0.94 0.95 0.96 0.97
## [99] 0.98 0.99 1.00
quantile(cars$price, seq(from=0, to=1, by=0.01))
## 0% 1% 2% 3% 4% 5%
## 0.00 2350.00 2999.00 3890.00 4400.00 4900.00
## 6% 7% 8% 9% 10% 11%
## 5000.00 5500.00 5950.00 6000.00 6490.00 6880.00
## 12% 13% 14% 15% 16% 17%
## 6990.00 7200.00 7490.00 7800.00 7980.00 7990.00
## 18% 19% 20% 21% 22% 23%
## 8350.00 8500.00 8800.00 8900.00 8990.00 9150.00
## 24% 25% 26% 27% 28% 29%
## 9490.00 9600.00 9900.00 9990.00 9990.00 10350.00
## 30% 31% 32% 33% 34% 35%
## 10500.00 10850.00 10900.00 10990.00 11200.00 11490.00
## 36% 37% 38% 39% 40% 41%
## 11690.00 11900.00 11990.00 11990.00 12480.00 12500.00
## 42% 43% 44% 45% 46% 47%
## 12890.00 12900.00 12990.00 13200.00 13490.00 13690.00
## 48% 49% 50% 51% 52% 53%
## 13900.00 13990.00 13990.00 14490.00 14590.00 14900.00
## 54% 55% 56% 57% 58% 59%
## 14990.00 14990.00 15490.00 15800.00 15900.00 15990.00
## 60% 61% 62% 63% 64% 65%
## 16470.00 16600.00 16900.00 16990.00 17350.00 17540.00
## 66% 67% 68% 69% 70% 71%
## 17900.00 17990.00 18490.00 18800.00 18990.00 19127.92
## 72% 73% 74% 75% 76% 77%
## 19600.00 19900.00 19990.00 20500.00 20920.00 21300.00
## 78% 79% 80% 81% 82% 83%
## 21895.00 21990.00 22500.00 22900.00 23490.00 23900.00
## 84% 85% 86% 87% 88% 89%
## 24450.00 24900.00 25500.00 26000.00 26990.00 27900.00
## 90% 91% 92% 93% 94% 95%
## 28980.00 29990.00 31900.00 33900.00 35900.00 38900.00
## 96% 97% 98% 99% 100%
## 42900.00 47990.00 56900.00 73900.00 4190000.00
- Nous enlevons les prix marginaux :
cars <- subset(cars, price>=100 & price<=70000)
- Nous pouvons désormais afficher les prix sous forme d’histogramme :
hist(cars$price)
Création de factor
Recréation de factor pour nos marques :
str(cars$brand)
## chr [1:255367] "ABARTH" "ABARTH" "ABARTH" "ABARTH" "ABARTH" ...
cars$brand <- as.factor(cars$brand) str(cars$brand)
## Factor w/ 122 levels "ABARTH","AC",..: 1 1 1 1 1 1 1 1 1 1 ...
- Pour le reste du nettoyage nous avons créé une petite fonction utilitaire dont le code est le suivant :
cleanAndLoad
## function (carsfile) ## { ## cars <- read.csv(carsfile, sep = ",", header = TRUE, stringsAsFactors = FALSE) ## cars <- na.exclude(cars) ## cars <- subset(cars, price >= 100 & price <= 70000) ## filterOutliers <- function(x, min, max) { ## x >= min & x <= max ## } ## cars$mileage <- as.numeric(cars$mileage) ## cars <- subset(cars, filterOutliers(cars$mileage, 10, 3e+05)) ## cars <- subset(cars, filterOutliers(cars$powerDin, 60, 400)) ## cars <- subset(cars, filterOutliers(cars$priceNew, 5000, ## 70000)) ## cars <- subset(cars, filterOutliers(cars$doors, 1, 9)) ## cars$yearModel <- as.numeric(cars$yearModel) ## cars <- subset(cars, filterOutliers(cars$yearModel, 2000, ## 2015)) ## cars$brand <- as.factor(cars$brand) ## cars$gearbox <- factor(cars$gearbox, levels = c(1, 2), labels = c("AUTOMATIQUE", ## "MECANIQUE")) ## cars$energy <- factor(cars$energy, levels = c(1, 2, 3, 4, ## 5, 6, 7, 8, 9, 10, 11), labels = c("ESSENCE", "DIESEL", ## "GPL", "ELECTRIQUE", "BIOCARBURANT", "HYDROGENE", "AIR_COMPRIME", ## "HYBRIDE_ESSENCE", "HYBRIDE_DIESEL", "BIOETHANOL", "GNV")) ## cars ## }
Prochain épisode : Prédiction avec un modèle de régression linéaire
Par Philippe Vasconcelos & Nathaniel Richand