I use data from the (UCI Machine Learning Repository)[http://archive.ics.uci.edu/ml/].

load in the data

library(tidyverse)
getwd()
[1] "C:/Users/edward cooper/Google Drive/Learn R"
sms=read.csv("sms_spam.csv",stringsAsFactors = FALSE)
str(sms)
'data.frame':   5574 obs. of  2 variables:
 $ type: chr  "ham" "ham" "spam" "ham" ...
 $ text: chr  "Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat..." "Ok lar... Joking wif u oni..." "Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C"| __truncated__ "U dun say so early hor... U c already then say..." ...

convert type column into factor for classification analysis

sms$type=sms$type%>%factor
str(sms)
'data.frame':   5574 obs. of  2 variables:
 $ type: Factor w/ 2 levels "ham","spam": 1 1 2 1 1 2 1 1 2 2 ...
 $ text: chr  "Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat..." "Ok lar... Joking wif u oni..." "Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C"| __truncated__ "U dun say so early hor... U c already then say..." ...

process the text data

The first step in processing text data involves creating a corpus, which is a collection of text documents.

I am most interested in how we could do this with tidytext packge recently developed.

library(tidytext)
sms_tidy=sms%>%unnest_tokens(output=word,input=text,token="words")%>%anti_join(stop_words,by="word")
sms_tidy%>%head(20)

visualizing text data using the famous wordcloud package

#install.packages("wordcloud")
library(wordcloud)
sms_sum=sms_tidy%>%group_by(word)%>%summarise(n=n())%>%arrange(desc(n))
sms_sum%>%head
wordcloud(words=sms_sum$word,freq=sms_sum$n,min.freq = 50,random.order = FALSE,random.color = FALSE)

# create a similar document term matrix 
names=sms%>%unnest_tokens(input=text,output=word,token="words")%>%anti_join(stop_words,by="word")%>%group_by(word)%>%summarise(n=n())%>%arrange(desc(n))%>%filter(n>5)
col_dim=dim(names)[1]
row_dim=dim(sms)[1]
library(foreach)
library(stringr)
DTM=foreach(i=1:col_dim,.combine = cbind)%do%{
  ifelse(str_detect(sms$text,names$word[i]),"yes","no")%>%factor()
}
colnames(DTM)=names$word
summary(DTM[,1:7])
      call             2               ur             â               gt              4       
 Min.   :1.000   Min.   :1.000   Min.   :1.00   Min.   :1.000   Min.   :1.000   Min.   :1.00  
 1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.00   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.00  
 Median :1.000   Median :1.000   Median :1.00   Median :1.000   Median :1.000   Median :1.00  
 Mean   :1.084   Mean   :1.159   Mean   :1.25   Mean   :1.009   Mean   :1.052   Mean   :1.12  
 3rd Qu.:1.000   3rd Qu.:1.000   3rd Qu.:1.00   3rd Qu.:1.000   3rd Qu.:1.000   3rd Qu.:1.00  
 Max.   :2.000   Max.   :2.000   Max.   :2.00   Max.   :2.000   Max.   :2.000   Max.   :2.00  
       lt      
 Min.   :1.00  
 1st Qu.:1.00  
 Median :1.00  
 Mean   :1.06  
 3rd Qu.:1.00  
 Max.   :2.00  

Create training and testing data set

library(caret)
index=createDataPartition(DTM[,1],p=0.8,list=FALSE)
sms_train=DTM[index,]
sms_test=DTM[-index,]
sms_train_cl=sms$type[index]
sms_test_cl=sms$type[-index]

Apply naive bayes classifer

sms_pred=predict(sms_cl,sms_test,type="class",threshold = 0.1)
sms_pred=predict(sms_cl,sms_test,type="class",threshold = 0.1)
confusionMatrix(sms_pred, sms_test_cl)
Confusion Matrix and Statistics

          Reference
Prediction ham spam
      ham  902   38
      spam  53  121
                                          
               Accuracy : 0.9183          
                 95% CI : (0.9007, 0.9337)
    No Information Rate : 0.8573          
    P-Value [Acc > NIR] : 2.881e-10       
                                          
                  Kappa : 0.6788          
 Mcnemar's Test P-Value : 0.1422          
                                          
            Sensitivity : 0.9445          
            Specificity : 0.7610          
         Pos Pred Value : 0.9596          
         Neg Pred Value : 0.6954          
             Prevalence : 0.8573          
         Detection Rate : 0.8097          
   Detection Prevalence : 0.8438          
      Balanced Accuracy : 0.8528          
                                          
       'Positive' Class : ham             
                                          

when I changed the thresold to 0.1 it gives a much much better result

LS0tDQp0aXRsZTogIk5haXZlIEJheWVzIGNsYXNzaWZpZXIgb24gU01TIGRhdGEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KSSB1c2UgZGF0YSBmcm9tIHRoZSAoVUNJIE1hY2hpbmUgTGVhcm5pbmcgUmVwb3NpdG9yeSlbaHR0cDovL2FyY2hpdmUuaWNzLnVjaS5lZHUvbWwvXS4NCg0KDQojIyBsb2FkIGluIHRoZSBkYXRhIA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0Kc21zPXJlYWQuY3N2KCJzbXNfc3BhbS5jc3YiLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCnN0cihzbXMpDQpgYGANCg0KIyMgY29udmVydCB0eXBlIGNvbHVtbiBpbnRvIGZhY3RvciBmb3IgY2xhc3NpZmljYXRpb24gYW5hbHlzaXMNCg0KYGBge3J9DQpzbXMkdHlwZT1zbXMkdHlwZSU+JWZhY3Rvcg0KDQpzdHIoc21zKQ0KYGBgDQoNCiMjIHByb2Nlc3MgdGhlIHRleHQgZGF0YQ0KDQpUaGUgZmlyc3Qgc3RlcCBpbiBwcm9jZXNzaW5nIHRleHQgZGF0YSBpbnZvbHZlcyBjcmVhdGluZyBhIGNvcnB1cywgd2hpY2ggaXMgYSBjb2xsZWN0aW9uDQpvZiB0ZXh0IGRvY3VtZW50cy4NCg0KSSBhbSBtb3N0IGludGVyZXN0ZWQgaW4gaG93IHdlIGNvdWxkIGRvIHRoaXMgd2l0aCB0aWR5dGV4dCBwYWNrZ2UgcmVjZW50bHkgZGV2ZWxvcGVkLiANCg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXRleHQpDQoNCnNtc190aWR5PXNtcyU+JXVubmVzdF90b2tlbnMob3V0cHV0PXdvcmQsaW5wdXQ9dGV4dCx0b2tlbj0id29yZHMiKSU+JWFudGlfam9pbihzdG9wX3dvcmRzLGJ5PSJ3b3JkIikNCg0Kc21zX3RpZHklPiVoZWFkKDIwKQ0KDQpgYGANCg0KIyMgdmlzdWFsaXppbmcgdGV4dCBkYXRhIHVzaW5nIHRoZSBmYW1vdXMgd29yZGNsb3VkIHBhY2thZ2UNCg0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJ3b3JkY2xvdWQiKQ0KbGlicmFyeSh3b3JkY2xvdWQpDQoNCnNtc19zdW09c21zX3RpZHklPiVncm91cF9ieSh3b3JkKSU+JXN1bW1hcmlzZShuPW4oKSklPiVhcnJhbmdlKGRlc2MobikpDQpzbXNfc3VtJT4laGVhZA0Kd29yZGNsb3VkKHdvcmRzPXNtc19zdW0kd29yZCxmcmVxPXNtc19zdW0kbixtaW4uZnJlcSA9IDUwLHJhbmRvbS5vcmRlciA9IEZBTFNFLHJhbmRvbS5jb2xvciA9IEZBTFNFKQ0KYGBgDQoNCmBgYHtyfQ0KIyBjcmVhdGUgYSBkb2N1bWVudCB0ZXJtIG1hdHJpeCANCg0KDQpuYW1lcz1zbXMlPiV1bm5lc3RfdG9rZW5zKGlucHV0PXRleHQsb3V0cHV0PXdvcmQsdG9rZW49IndvcmRzIiklPiVhbnRpX2pvaW4oc3RvcF93b3JkcyxieT0id29yZCIpJT4lZ3JvdXBfYnkod29yZCklPiVzdW1tYXJpc2Uobj1uKCkpJT4lYXJyYW5nZShkZXNjKG4pKSU+JWZpbHRlcihuPjUpDQoNCmNvbF9kaW09ZGltKG5hbWVzKVsxXQ0Kcm93X2RpbT1kaW0oc21zKVsxXQ0KDQoNCg0KbGlicmFyeShmb3JlYWNoKQ0KDQpsaWJyYXJ5KHN0cmluZ3IpDQoNCkRUTT1mb3JlYWNoKGk9MTpjb2xfZGltLC5jb21iaW5lID0gY2JpbmQpJWRvJXsNCiAgaWZlbHNlKHN0cl9kZXRlY3Qoc21zJHRleHQsbmFtZXMkd29yZFtpXSksInllcyIsIm5vIiklPiVmYWN0b3IoKQ0KfQ0KDQpjb2xuYW1lcyhEVE0pPW5hbWVzJHdvcmQNCg0Kc3VtbWFyeShEVE1bLDE6N10pDQoNCmBgYA0KDQoNCiMjIENyZWF0ZSB0cmFpbmluZyBhbmQgdGVzdGluZyBkYXRhIHNldA0KYGBge3J9DQpsaWJyYXJ5KGNhcmV0KQ0KDQppbmRleD1jcmVhdGVEYXRhUGFydGl0aW9uKERUTVssMV0scD0wLjgsbGlzdD1GQUxTRSkNCg0KDQpzbXNfdHJhaW49RFRNW2luZGV4LF0NCg0Kc21zX3Rlc3Q9RFRNWy1pbmRleCxdDQoNCnNtc190cmFpbl9jbD1zbXMkdHlwZVtpbmRleF0NCg0Kc21zX3Rlc3RfY2w9c21zJHR5cGVbLWluZGV4XQ0KDQpgYGANCg0KDQojIyBBcHBseSBuYWl2ZSBiYXllcyBjbGFzc2lmZXIgDQoNCmBgYHtyfQ0KbGlicmFyeShlMTA3MSkNCg0Kc21zX2NsPW5haXZlQmF5ZXMoc21zX3RyYWluLHNtc190cmFpbl9jbCxsYXBsYWNlID0gMCkNCg0KDQoNCnNtc19wcmVkPXByZWRpY3Qoc21zX2NsLHNtc190ZXN0LHR5cGU9ImNsYXNzIix0aHJlc2hvbGQgPSAwLjEpDQoNCg0KY29uZnVzaW9uTWF0cml4KHNtc19wcmVkLCBzbXNfdGVzdF9jbCkNCg0KYGBgDQoNCiMjIHdoZW4gSSBjaGFuZ2VkIHRoZSB0aHJlc29sZCB0byAwLjEgaXQgZ2l2ZXMgYSBtdWNoIG11Y2ggYmV0dGVyIHJlc3VsdCANCg0KDQo=