library(tidyr)
library(class)
library(gmodels)
# read and clean the data
tele <- read.csv("telemarketing.csv")
TeleName <- c("age","job","marital","education","default","housing","loan","contact","month","day_of_week","duration","campaign","pdays","previous","poutcome","emp.var.rate","cons.price.idx","cons.conf.idx","euribor3m","nr.employed","y")
tele <- separate(data= tele,
col = "age.job.marital.education.default.housing.loan.contact.month.day_of_week.duration.campaign.pdays.previous.poutcome.emp.var.rate.cons.price.idx.cons.conf.idx.euribor3m.nr.employed.y",
sep = ";",into = TeleName)
# change data type of columns
str(tele)
## 'data.frame': 41188 obs. of 21 variables:
## $ age : chr "56" "57" "37" "40" ...
## $ job : chr "housemaid" "services" "services" "admin." ...
## $ marital : chr "married" "married" "married" "married" ...
## $ education : chr "basic.4y" "high.school" "high.school" "basic.6y" ...
## $ default : chr "no" "unknown" "no" "no" ...
## $ housing : chr "no" "no" "yes" "no" ...
## $ loan : chr "no" "no" "no" "no" ...
## $ contact : chr "telephone" "telephone" "telephone" "telephone" ...
## $ month : chr "may" "may" "may" "may" ...
## $ day_of_week : chr "mon" "mon" "mon" "mon" ...
## $ duration : chr "261" "149" "226" "151" ...
## $ campaign : chr "1" "1" "1" "1" ...
## $ pdays : chr "999" "999" "999" "999" ...
## $ previous : chr "0" "0" "0" "0" ...
## $ poutcome : chr "nonexistent" "nonexistent" "nonexistent" "nonexistent" ...
## $ emp.var.rate : chr "1.1" "1.1" "1.1" "1.1" ...
## $ cons.price.idx: chr "93.994" "93.994" "93.994" "93.994" ...
## $ cons.conf.idx : chr "-36.4" "-36.4" "-36.4" "-36.4" ...
## $ euribor3m : chr "4.857" "4.857" "4.857" "4.857" ...
## $ nr.employed : chr "5191" "5191" "5191" "5191" ...
## $ y : chr "no" "no" "no" "no" ...
tele$age = as.numeric(tele$age)
tele$job = as.factor(tele$job)
tele$marital = as.factor(tele$marital)
tele$education = as.factor(tele$education)
tele$default = as.factor(tele$default)
tele$housing = as.factor(tele$housing)
tele$loan = as.factor(tele$loan)
tele$contact = as.factor(tele$contact)
tele$month = as.factor(tele$month)
tele$day_of_week = as.factor(tele$day_of_week)
tele$duration = as.numeric(tele$duration)
tele$campaign = as.numeric(tele$campaign)
tele$pdays = as.numeric(tele$pdays)
tele$previous = as.numeric(tele$previous)
tele$poutcome = as.factor(tele$poutcome)
tele$emp.var.rate = as.numeric(tele$emp.var.rate)
tele$cons.price.idx = as.numeric(tele$cons.price.idx)
tele$cons.conf.idx = as.numeric(tele$cons.conf.idx)
tele$nr.employed = as.numeric(tele$nr.employed)
tele$euribor3m = as.numeric(tele$euribor3m)
tele$y = as.factor(tele$y)
# remove column duration
tele <- tele[-11]
# turn all categoried variables into dummy variables ######
library(dummies)
## dummies-1.5.6 provided by Decision Patterns
tele_dummy <- dummy.data.frame(data = tele[-ncol(tele)], sep = ".")
tele_dummy$y <- tele$y
# normalize data
tele_n<- as.data.frame(scale(tele_dummy[c("age","pdays","previous","emp.var.rate","cons.conf.idx","cons.price.idx","euribor3m","nr.employed","campaign")]))
tele_dummy[c("age","pdays","previous","emp.var.rate","cons.conf.idx","cons.price.idx","euribor3m","nr.employed","campaign")] <- tele_n[c("age","pdays","previous","emp.var.rate","cons.conf.idx","cons.price.idx","euribor3m","nr.employed","campaign")]
# define random 80% as training data and 20% as test data
tele_80_id <- sample(seq_len(nrow(tele_dummy)),floor(0.8*nrow(tele_dummy)))
tele_20_id <- seq_len(nrow(tele_dummy))[-tele_80_id]
tele_dummy_80 <- tele_dummy[tele_80_id,]
tele_dummy_20 <- tele_dummy[tele_20_id,]
tele_train <- tele_dummy_80[-ncol(tele_dummy_80)]
tele_test <- tele_dummy_20[-ncol(tele_dummy_20)]
# define labels
train_labels <- tele_dummy_80$y
test_labels <- tele_dummy_20$y
# check out train set labels and test test labels
summary(train_labels)
## no yes
## 29252 3698
summary(test_labels)
## no yes
## 7296 942
# run knn model
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 202)
summary(tele_test_knn)
## no yes
## 7958 280
CrossTable(x = test_labels, y = tele_test_knn, prop.chisq = FALSE)
##
##
## Cell Contents
## |-------------------------|
## | N |
## | N / Row Total |
## | N / Col Total |
## | N / Table Total |
## |-------------------------|
##
##
## Total Observations in Table: 8238
##
##
## | tele_test_knn
## test_labels | no | yes | Row Total |
## -------------|-----------|-----------|-----------|
## no | 7197 | 99 | 7296 |
## | 0.986 | 0.014 | 0.886 |
## | 0.904 | 0.354 | |
## | 0.874 | 0.012 | |
## -------------|-----------|-----------|-----------|
## yes | 761 | 181 | 942 |
## | 0.808 | 0.192 | 0.114 |
## | 0.096 | 0.646 | |
## | 0.092 | 0.022 | |
## -------------|-----------|-----------|-----------|
## Column Total | 7958 | 280 | 8238 |
## | 0.966 | 0.034 | |
## -------------|-----------|-----------|-----------|
##
##
# caculate knn model prediction accuracy
correct.count <- function () {
n <- 0
for (i in 1:nrow(tele_test)) {
if (test_labels[i] == tele_test_knn[i]) {
n <- (n + 1)
}
}
return(n)
}
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy <- round(accuracy, digits = 1)
paste("accuracy is: ", accuracy,"%")
## [1] "accuracy is: 89.6 %"
# improve the model by trying different k
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 1)
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy1 <- round(accuracy, digits = 1)
paste("when k =1,"," accuracy is: ", accuracy1,"%")
## [1] "when k =1, accuracy is: 84.7 %"
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 10)
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy2 <- round(accuracy, digits = 1)
paste("when k =10,"," accuracy is: ", accuracy2,"%")
## [1] "when k =10, accuracy is: 89.2 %"
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 100)
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy3 <- round(accuracy, digits = 1)
paste("when k =100,"," accuracy is: ", accuracy3,"%")
## [1] "when k =100, accuracy is: 89.7 %"
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 150)
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy4 <- round(accuracy, digits = 1)
paste("when k = 150,"," accuracy is: ", accuracy4,"%")
## [1] "when k = 150, accuracy is: 89.7 %"
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 200)
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy5 <- round(accuracy, digits = 1)
paste("when k = 200,"," accuracy is: ", accuracy5,"%")
## [1] "when k = 200, accuracy is: 89.5 %"
tele_test_knn <- knn(train = tele_train, test = tele_test, cl = train_labels,
k= 400)
correct <- correct.count()
accuracy <- as.numeric(correct)/nrow(tele_test) * 100
accuracy6 <- round(accuracy, digits = 1)
paste("when k = 400,"," accuracy is: ", accuracy6,"%")
## [1] "when k = 400, accuracy is: 89.3 %"
# visual the impact of k on accuracy
plot(x = c(1,10,100,150,200,400),
y = c(accuracy1,accuracy2,accuracy3,accuracy4,accuracy5,accuracy6), type = "b")

Conclusion:
the optimal k is between 100 and 200, where prediction accuracy is above 89%