library(tidyverse)
library(caret)
library(doMC)
library(ggcorrplot)
registerDoMC(cores=7)

Load Datasets

winedataset_blanco <- read_csv("blanco_train.csv.gz")
Parsed with column specification:
cols(
  `fixed acidity` = col_double(),
  `volatile acidity` = col_double(),
  `citric acid` = col_double(),
  `residual sugar` = col_double(),
  chlorides = col_double(),
  `free sulfur dioxide` = col_double(),
  `total sulfur dioxide` = col_double(),
  density = col_double(),
  pH = col_double(),
  sulphates = col_double(),
  alcohol = col_double(),
  quality = col_integer()
)
winedataset_red <- read_csv("tinto_train.csv.gz")
Parsed with column specification:
cols(
  `fixed acidity` = col_double(),
  `volatile acidity` = col_double(),
  `citric acid` = col_double(),
  `residual sugar` = col_double(),
  chlorides = col_double(),
  `free sulfur dioxide` = col_double(),
  `total sulfur dioxide` = col_double(),
  density = col_double(),
  pH = col_double(),
  sulphates = col_double(),
  alcohol = col_double(),
  quality = col_integer()
)
winedataset_blanco$type="white"
winedataset_red$type="red"
winedataset<-rbind(winedataset_blanco,winedataset_red)
winedataset
winedataset %>% map(is.null)
$`fixed acidity`
[1] FALSE

$`volatile acidity`
[1] FALSE

$`citric acid`
[1] FALSE

$`residual sugar`
[1] FALSE

$chlorides
[1] FALSE

$`free sulfur dioxide`
[1] FALSE

$`total sulfur dioxide`
[1] FALSE

$density
[1] FALSE

$pH
[1] FALSE

$sulphates
[1] FALSE

$alcohol
[1] FALSE

$quality
[1] FALSE

$type
[1] FALSE
winedataset %>% group_by(quality) %>% summarise(total=n())
winedataset %>% group_by(`total sulfur dioxide`,quality)  %>% summarise(total=n())

Exploratory Analysis

Correlation Matrix

#Matriz de correlacion
cor_matrix<-cor(winedataset %>% select(-type))
ggcorrplot(cor_matrix)

Boxplot volatile

ggplot(winedataset)+
  geom_boxplot(aes(x=as.factor(quality),y=`volatile acidity`,fill=as.factor(quality)))

NA

Boxplot alcohol

ggplot(winedataset)+
  geom_boxplot(aes(x=as.factor(quality),y=`alcohol`))

Create categorical features

Create category labels for quality

Create clustering labels (dbscan)

Create clustering labels (kmeans)

Eliminate type

trainset <- trainset %>% select(-type)
names(trainset)
 [1] "fixed acidity"        "volatile acidity"     "citric acid"          "residual sugar"       "chlorides"           
 [6] "free sulfur dioxide"  "total sulfur dioxide" "density"              "pH"                   "sulphates"           
[11] "alcohol"              "quality"              "cluster"             

Split train and test

trainIndex <- createDataPartition(as.factor(trainset$quality), p=0.80, list=FALSE)
data_train <- trainset[ trainIndex,]
data_test <-  trainset[-trainIndex,]
colnames(data_train) <- make.names(colnames(data_train))
colnames(data_test) <- make.names(colnames(data_test))

Plot class distribution in train

data_train  %>% group_by(quality) %>% summarise(total=n()) %>%
  ggplot()+
  geom_col(aes(x=quality,y=total,fill=quality))+
  theme_classic()

Plot class distribution in test

data_test  %>% group_by(quality) %>% summarise(total=n()) %>%
  ggplot()+
  geom_col(aes(x=quality,y=total,fill=quality))+
  theme_classic()

Feature selection

Train model

ctrl_fast <- trainControl(method="cv", 
                     repeats=1,
                     number=5, 
                   #  summaryFunction=twoClassSummary,
                     verboseIter=T,
                     classProbs=T,
                     allowParallel = TRUE)  
`repeats` has no meaning for this resampling method.
importance <- varImp(rfFitupsam, scale=FALSE)
plot(importance)

Test model

predsrfprobsamp=predict(rfFitupsam,data_test)
# use for regresion
#confusionMatrix(as.factor(predsrfprobsamp %>% round()),as.factor(data_test$quality))
confusionMatrix(predsrfprobsamp,as.factor(data_test$quality))
Confusion Matrix and Statistics

          Reference
Prediction high low medium
    high    122   0     45
    low       0   3      4
    medium   82  37    745

Overall Statistics
                                          
               Accuracy : 0.8382          
                 95% CI : (0.8143, 0.8601)
    No Information Rate : 0.7649          
    P-Value [Acc > NIR] : 4.354e-09       
                                          
                  Kappa : 0.5116          
 Mcnemar's Test P-Value : NA              

Statistics by Class:

                     Class: high Class: low Class: medium
Sensitivity               0.5980   0.075000        0.9383
Specificity               0.9460   0.995992        0.5123
Pos Pred Value            0.7305   0.428571        0.8623
Neg Pred Value            0.9059   0.964113        0.7184
Prevalence                0.1965   0.038536        0.7649
Detection Rate            0.1175   0.002890        0.7177
Detection Prevalence      0.1609   0.006744        0.8324
Balanced Accuracy         0.7720   0.535496        0.7253

LS0tCnRpdGxlOiAiV2luZSBRdWFsaXR5IG1lZXR1cCAyMC8wMy8yMDE5IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkoZG9NQykKbGlicmFyeShnZ2NvcnJwbG90KQpyZWdpc3RlckRvTUMoY29yZXM9NykKCmBgYAojIyBMb2FkIERhdGFzZXRzCmBgYHtyfQp3aW5lZGF0YXNldF9ibGFuY28gPC0gcmVhZF9jc3YoImJsYW5jb190cmFpbi5jc3YuZ3oiKQp3aW5lZGF0YXNldF9yZWQgPC0gcmVhZF9jc3YoInRpbnRvX3RyYWluLmNzdi5neiIpCgp3aW5lZGF0YXNldF9ibGFuY28kdHlwZT0id2hpdGUiCndpbmVkYXRhc2V0X3JlZCR0eXBlPSJyZWQiCgp3aW5lZGF0YXNldDwtcmJpbmQod2luZWRhdGFzZXRfYmxhbmNvLHdpbmVkYXRhc2V0X3JlZCkKCndpbmVkYXRhc2V0CndpbmVkYXRhc2V0ICU+JSBtYXAoaXMubnVsbCkKYGBgCmBgYHtyfQp3aW5lZGF0YXNldCAlPiUgZ3JvdXBfYnkocXVhbGl0eSkgJT4lIHN1bW1hcmlzZSh0b3RhbD1uKCkpCndpbmVkYXRhc2V0ICU+JSBncm91cF9ieShgdG90YWwgc3VsZnVyIGRpb3hpZGVgLHF1YWxpdHkpICAlPiUgc3VtbWFyaXNlKHRvdGFsPW4oKSkKYGBgCiMjIEV4cGxvcmF0b3J5IEFuYWx5c2lzCiMjIyBDb3JyZWxhdGlvbiBNYXRyaXgKYGBge3J9CiNNYXRyaXogZGUgY29ycmVsYWNpb24KCmNvcl9tYXRyaXg8LWNvcih3aW5lZGF0YXNldCAlPiUgc2VsZWN0KC10eXBlKSkKZ2djb3JycGxvdChjb3JfbWF0cml4KQpgYGAKIyMjIEJveHBsb3Qgdm9sYXRpbGUKYGBge3J9CmdncGxvdCh3aW5lZGF0YXNldCkrCiAgZ2VvbV9ib3hwbG90KGFlcyh4PWFzLmZhY3RvcihxdWFsaXR5KSx5PWB2b2xhdGlsZSBhY2lkaXR5YCxmaWxsPWFzLmZhY3RvcihxdWFsaXR5KSkpCiAgCmBgYAojIyMgQm94cGxvdCBhbGNvaG9sCmBgYHtyfQpnZ3Bsb3Qod2luZWRhdGFzZXQpKwogIGdlb21fYm94cGxvdChhZXMoeD1hcy5mYWN0b3IocXVhbGl0eSkseT1gYWxjb2hvbGApKQpgYGAKIyMgQ3JlYXRlIGNhdGVnb3JpY2FsIGZlYXR1cmVzCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnRyYWluc2V0PC13aW5lZGF0YXNldCAlPiUgbXV0YXRlKHZpbmVnYXIgPSBpZmVsc2UoYHZvbGF0aWxlIGFjaWRpdHlgPD0wLjQsJ2xvdycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoYHZvbGF0aWxlIGFjaWRpdHlgPjAuNCAmIGB2b2xhdGlsZSBhY2lkaXR5YDw9MC44LCdtZWRpdW0nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2hpZ2gnKSkpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShhY29ob2xfbGV2ZWwgPSBpZmVsc2UoYGFsY29ob2xgPD05LCdsb3cnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGBhbGNvaG9sYD45ICYgYGFsY29ob2xgPD0xMSwnbWVkaXVtJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdoaWdoJykpKSAlPiUgIHNlbGVjdCgtYHJlc2lkdWFsIHN1Z2FyYCwtYGZpeGVkIGFjaWRpdHlgLC1gdm9sYXRpbGUgYWNpZGl0eWAsLWFsY29ob2wsLWBmcmVlIHN1bGZ1ciBkaW94aWRlYCkKCiN0cmFpbnNldDwtd2luZWRhdGFzZXQgJT4lIHNlbGVjdChgdm9sYXRpbGUgYWNpZGl0eWAsZGVuc2l0eSxwSCxgcmVzaWR1YWwgc3VnYXJgLGBmaXhlZCBhY2lkaXR5YCxgZnJlZSBzdWxmdXIgZGlveGlkZWAscXVhbGl0eSkKCiNnZ3Bsb3QodHJhaW5zZXQpKwojICAgICAgICAgZ2VvbV9wb2ludChhZXMoeD1gZnJlZSBzdWxmdXIgZGlveGlkZWAseT1gdG90YWwgc3VsZnVyIGRpb3hpZGVgKSkKYGBgCgojIyBDcmVhdGUgY2F0ZWdvcnkgbGFiZWxzIGZvciBxdWFsaXR5CmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnNldC5zZWVkKDEwKQoKdHJhaW5zZXQgPC0gd2luZWRhdGFzZXQgJT4lIG11dGF0ZShxdWFsaXR5PWlmZWxzZShxdWFsaXR5PT0zLCdsb3cnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShxdWFsaXR5PT00LCdsb3cnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShxdWFsaXR5PT01LCdtZWRpdW0nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShxdWFsaXR5PT02LCdtZWRpdW0nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShxdWFsaXR5PT03LCdoaWdoJywnaGlnaCcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkpKSkgIyU+JSBmaWx0ZXIocXVhbGl0eSAlaW4lIGMoJ3NldmVuJywnZml2ZScsJ3NpeCcpKQoKYGBgCiMjIENyZWF0ZSBjbHVzdGVyaW5nIGxhYmVscyAoZGJzY2FuKQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGRic2NhbikKCgpkYnNjYW5fbW9kPC1kYnNjYW4odHJhaW5zZXQgJT4lIHNlbGVjdCgtcXVhbGl0eSwtdHlwZSksIGVwcz01LCBtaW5QdHMgPSAxMCkKdHJhaW5zZXQgPC1jYmluZCh0cmFpbnNldCxjbHVzdGVyPWRic2Nhbl9tb2QkY2x1c3RlcikKdHJhaW5zZXQgJT4lIGdyb3VwX2J5KHF1YWxpdHksY2x1c3RlcikgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lCiAgZ2dwbG90KCkrCiAgICBnZW9tX2NvbChhZXMoeD1xdWFsaXR5LHk9bixmaWxsPWFzLmZhY3RvcihjbHVzdGVyKSkpCgpgYGAKCiMjIENyZWF0ZSBjbHVzdGVyaW5nIGxhYmVscyAoa21lYW5zKQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKCmttZWFuc19tb2Q8LWttZWFucyh0cmFpbnNldCAlPiUgc2VsZWN0KC1xdWFsaXR5LC10eXBlKSxjZW50ZXJzID04LG5zdGFydD00MCkKdHJhaW5zZXQgPC1jYmluZCh0cmFpbnNldCxjbHVzdGVyPWttZWFuc19tb2QkY2x1c3RlcikKdHJhaW5zZXQgJT4lIGdyb3VwX2J5KHF1YWxpdHksY2x1c3RlcikgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lCiAgZ2dwbG90KCkrCiAgICBnZW9tX2NvbChhZXMoeT1uLHg9YXMuZmFjdG9yKGNsdXN0ZXIpKSkrCiAgZmFjZXRfd3JhcCh+cXVhbGl0eSkKCnRyYWluc2V0CmBgYAoKCiMjIEVsaW1pbmF0ZSB0eXBlCmBgYHtyfQoKdHJhaW5zZXQgPC0gdHJhaW5zZXQgJT4lIHNlbGVjdCgtdHlwZSkKYGBgCgpgYGB7cn0KbmFtZXModHJhaW5zZXQpCmBgYAojIyBTcGxpdCB0cmFpbiBhbmQgdGVzdApgYGB7cn0KCnRyYWluSW5kZXggPC0gY3JlYXRlRGF0YVBhcnRpdGlvbihhcy5mYWN0b3IodHJhaW5zZXQkcXVhbGl0eSksIHA9MC44MCwgbGlzdD1GQUxTRSkKZGF0YV90cmFpbiA8LSB0cmFpbnNldFsgdHJhaW5JbmRleCxdCmRhdGFfdGVzdCA8LSAgdHJhaW5zZXRbLXRyYWluSW5kZXgsXQpjb2xuYW1lcyhkYXRhX3RyYWluKSA8LSBtYWtlLm5hbWVzKGNvbG5hbWVzKGRhdGFfdHJhaW4pKQpjb2xuYW1lcyhkYXRhX3Rlc3QpIDwtIG1ha2UubmFtZXMoY29sbmFtZXMoZGF0YV90ZXN0KSkKCgpgYGAKIyMjIFBsb3QgY2xhc3MgZGlzdHJpYnV0aW9uIGluIHRyYWluCmBgYHtyfQpkYXRhX3RyYWluICAlPiUgZ3JvdXBfYnkocXVhbGl0eSkgJT4lIHN1bW1hcmlzZSh0b3RhbD1uKCkpICU+JQogIGdncGxvdCgpKwogIGdlb21fY29sKGFlcyh4PXF1YWxpdHkseT10b3RhbCxmaWxsPXF1YWxpdHkpKSsKICB0aGVtZV9jbGFzc2ljKCkKCmBgYAojIyMgUGxvdCBjbGFzcyBkaXN0cmlidXRpb24gaW4gdGVzdApgYGB7cn0KZGF0YV90ZXN0ICAlPiUgZ3JvdXBfYnkocXVhbGl0eSkgJT4lIHN1bW1hcmlzZSh0b3RhbD1uKCkpICU+JQogIGdncGxvdCgpKwogIGdlb21fY29sKGFlcyh4PXF1YWxpdHkseT10b3RhbCxmaWxsPXF1YWxpdHkpKSsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCiMjIEZlYXR1cmUgc2VsZWN0aW9uCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnJmZWNydGwgPC0gcmZlQ29udHJvbChmdW5jdGlvbnM9cmZGdW5jcywgbWV0aG9kPSJjdiIsIG51bWJlcj0xMCxhbGxvd1BhcmFsbGVsPVRSVUUpCnJlc3VsdHMgPC0gcmZlKHF1YWxpdHl+LiAsIGRhdGE9ZGF0YV90cmFpbiwgc2l6ZXM9YygxOjEzKSwgcmZlQ29udHJvbD1yZmVjcnRsKQpyZXN1bHRzCnByZWRpY3RvcnMocmVzdWx0cykKIyBwbG90IHRoZSByZXN1bHRzCnBsb3QocmVzdWx0cywgdHlwZT1jKCJnIiwgIm8iKSkKYGBgCgojIyBUcmFpbiBtb2RlbApgYGB7cn0KY3RybF9mYXN0IDwtIHRyYWluQ29udHJvbChtZXRob2Q9ImN2IiwgCiAgICAgICAgICAgICAgICAgICAgIHJlcGVhdHM9MSwKICAgICAgICAgICAgICAgICAgICAgbnVtYmVyPTUsIAogICAgICAgICAgICAgICAgICAgIyAgc3VtbWFyeUZ1bmN0aW9uPXR3b0NsYXNzU3VtbWFyeSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZUl0ZXI9VCwKICAgICAgICAgICAgICAgICAgICAgY2xhc3NQcm9icz1ULAogICAgICAgICAgICAgICAgICAgICBhbGxvd1BhcmFsbGVsID0gVFJVRSkgIApgYGAKCmBgYHtyfQpkYXRhX3RyYWluICU+JSBmaWx0ZXIocXVhbGl0eSA9PSAnbWVkaXVtJykgJT4lIHNhbXBsZV9uKHNpemUgPSAxMDAscmVwbGFjZSA9IFRSVUUpICU+JSB1bmlvbihkYXRhX3RyYWluKQoKY3RybF9mYXN0JHNhbXBsaW5nPC0idXAiCgpzdm1HcmlkIDwtICBleHBhbmQuZ3JpZChzaWdtYT0gYygwLjAwMSwwLjAwMDEsMC4wMDAwMSksIAogICAgICAgICAgICAgICAgICAgICAgICBDID0gYygxLDIsNCw4LDE2LDMyLDY0LDgwLDEwMCwxMjApIAogICAgICAgICAgICAgICAgICAgICAgICApCgojc3ZtR3JpZCA8LSAgZXhwYW5kLmdyaWQoQz0gYygxMDApLCBzaWdtYSA9IGMoMSkpCgoKdHJhaW5fZm9ybXVsYTwtZm9ybXVsYShxdWFsaXR5fi4pCnJmRml0dXBzYW08LSB0cmFpbih0cmFpbl9mb3JtdWxhLAogICAgICAgICAgICAgICBkYXRhID0gZGF0YV90cmFpbiwKICAgICAgICAgICAgICAgI21ldGhvZCA9ICJyZiIsICAgIyBSYWRpYWwga2VybmVsCiAgICAgICAgICAgICAgICNtZXRob2QgPSAieGdiVHJlZSIsCiAgICAgICAgICAgICAgIG1ldGhvZCA9ICJyZiIsCiAgICAgICAgICAgICAgICN0dW5lTGVuZ3RoID0gOSwKICAgICAgICAgICAgICAgI3R1bmVHcmlkID0gc3ZtR3JpZCwKICAgICAgICAgICAgICAgI3ByZVByb2Nlc3M9Yygic2NhbGUiLCJjZW50ZXIiKSwKICAgICAgICAgICAgICAgI21ldHJpYz0iUk9DIiwKICAgICAgICAgICAgICAgI3dlaWdodHMgPSBtb2RlbF93ZWlnaHRzLAogICAgICAgICAgICAgICB0ckNvbnRyb2wgPSBjdHJsX2Zhc3QpCgojcGxvdChyZkZpdHVwc2FtKQpyZkZpdHVwc2FtCiNyZkZpdHVwc2FtJGZpbmFsTW9kZWwKYGBgCmBgYHtyfQppbXBvcnRhbmNlIDwtIHZhckltcChyZkZpdHVwc2FtLCBzY2FsZT1GQUxTRSkKcGxvdChpbXBvcnRhbmNlKQpgYGAKIyMgVGVzdCBtb2RlbApgYGB7cn0KcHJlZHNyZnByb2JzYW1wPXByZWRpY3QocmZGaXR1cHNhbSxkYXRhX3Rlc3QpCiMgdXNlIGZvciByZWdyZXNpb24KI2NvbmZ1c2lvbk1hdHJpeChhcy5mYWN0b3IocHJlZHNyZnByb2JzYW1wICU+JSByb3VuZCgpKSxhcy5mYWN0b3IoZGF0YV90ZXN0JHF1YWxpdHkpKQoKY29uZnVzaW9uTWF0cml4KHByZWRzcmZwcm9ic2FtcCxhcy5mYWN0b3IoZGF0YV90ZXN0JHF1YWxpdHkpKQoKYGBgCmBgYHtyfQojY29uZnVzaW9ubWF0IDwtIHRhYmxlKHByZWRzcmZwcm9ic2FtcCAlPiUgcm91bmQoKSxhcy5mYWN0b3IoZGF0YV90ZXN0JHF1YWxpdHkpKQoKY29uZnVzaW9ubWF0IDwtIHRhYmxlKHByZWRzcmZwcm9ic2FtcCxhcy5mYWN0b3IoZGF0YV90ZXN0JHF1YWxpdHkpKQoKY29uZnVzaW9ubWF0CnJlc2hhcGUyOjptZWx0KGNvbmZ1c2lvbm1hdCkgJT4lCiAgZ2dwbG90KGFlcyh4PXByZWRzcmZwcm9ic2FtcCx5PVZhcjIpKSsKICBnZW9tX3RpbGUoYWVzKGZpbGw9dmFsdWUpLCBjb2xvdXIgPSAid2hpdGUiKSArIAogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc3ByaW50ZigiJTEuMGYiLCB2YWx1ZSkpLCB2anVzdCA9IDEpKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIpKwogIHhsYWIoIiBQcmVkaWN0ZWQgQWN0aXZpdHkgIikreWxhYigiIEFjdHVhbCBBY3Rpdml0eSIpKwogIHNjYWxlX3lfZGlzY3JldGUobGltaXRzPWMoJ2xvdycsJ21lZGl1bScsJ2hpZ2gnKSkrCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHM9YygnaGlnaCcsJ21lZGl1bScsJ2xvdycpKSsKICAKICAjc2NhbGVfeV9kaXNjcmV0ZShsaW1pdHM9YygndGhyZWUnLCdzaXgnLCdzZXZlbicsJ2ZvdXInLCdmaXZlJywnZWlnaHQnKSkrCiAgI3NjYWxlX3hfZGlzY3JldGUobGltaXRzPWMoJ2VpZ2h0JywnZml2ZScsJ2ZvdXInLCdzZXZlbicsJ3NpeCcsJ3RocmVlJykpKwogIAogIHRoZW1lX2J3KCkrIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgo=