Needed Packages

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(caret)
## Warning: package 'caret' was built under R version 4.6.1
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following object is masked from 'package:purrr':
## 
##     lift
library(recipes)
## Warning: package 'recipes' was built under R version 4.6.1
## 
## Attaching package: 'recipes'
## 
## The following object is masked from 'package:stringr':
## 
##     fixed
## 
## The following object is masked from 'package:stats':
## 
##     step
library(xgboost)
## Warning: package 'xgboost' was built under R version 4.6.1
library(ranger)
## Warning: package 'ranger' was built under R version 4.6.1
library(naivebayes)
## Warning: package 'naivebayes' was built under R version 4.6.1
## naivebayes 1.0.0 loaded
## For more information please visit: 
## https://majkamichal.github.io/naivebayes/
library(pROC)
## Warning: package 'pROC' was built under R version 4.6.1
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## 
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.6.1
## corrplot 0.95 loaded
library(gbm)
## Warning: package 'gbm' was built under R version 4.6.1
## Loaded gbm 2.3.1
## This version of gbm is no longer under development. Consider transitioning to gbm3, https://github.com/gbm-developers/gbm3
library(kernlab)
## Warning: package 'kernlab' was built under R version 4.6.1
## 
## Attaching package: 'kernlab'
## 
## The following object is masked from 'package:purrr':
## 
##     cross
## 
## The following object is masked from 'package:ggplot2':
## 
##     alpha

Creation of alternative variables to help predict

library(readr)
fundraising <- read_csv("fundraising.csv")
## Rows: 3000 Columns: 21
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (7): zipconvert2, zipconvert3, zipconvert4, zipconvert5, homeowner, fem...
## dbl (14): num_child, income, wealth, home_value, med_fam_inc, avg_fam_inc, p...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
future_fundraising <- read_csv("future_fundraising.csv")
## Rows: 120 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (6): zipconvert2, zipconvert3, zipconvert4, zipconvert5, homeowner, female
## dbl (14): num_child, income, wealth, home_value, med_fam_inc, avg_fam_inc, p...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
fundraising_alt <- fundraising
future_fundraising_alt <- future_fundraising

# Adjusting Target to Factor
fundraising_alt$target <- factor(
  fundraising_alt$target,
  levels = c("Donor", "No Donor"),
  labels = c("Donor", "No_Donor")
)
# creating the zipconvert1
fundraising_alt <- fundraising_alt %>%
  mutate(
    zipconvert1 = if_else(
      zipconvert2 == "No" &
      zipconvert3 == "No" &
      zipconvert4 == "No" &
      zipconvert5 == "No",
      "Yes",
      "No"
    )
  )

future_fundraising_alt <- future_fundraising_alt %>%
  mutate(
    zipconvert1 = if_else(
      zipconvert2 == "No" &
      zipconvert3 == "No" &
      zipconvert4 == "No" &
      zipconvert5 == "No",
      "Yes",
      "No"
    )
  )

# Creating a unique zip variable

fundraising_alt <- fundraising_alt %>%
  mutate(
    zip_group = case_when(
      zipconvert1 == "Yes" ~ "zip1",
      zipconvert2 == "Yes" ~ "zip2",
      zipconvert3 == "Yes" ~ "zip3",
      zipconvert4 == "Yes" ~ "zip4",
      zipconvert5 == "Yes" ~ "zip5",
      TRUE ~ NA_character_
    ),
    zip_group = factor(zip_group)
  )

future_fundraising_alt <- future_fundraising_alt %>%
  mutate(
    zip_group = case_when(
      zipconvert1 == "Yes" ~ "zip1",
      zipconvert2 == "Yes" ~ "zip2",
      zipconvert3 == "Yes" ~ "zip3",
      zipconvert4 == "Yes" ~ "zip4",
      zipconvert5 == "Yes" ~ "zip5",
      TRUE ~ NA_character_
    ),
    zip_group = factor(
      zip_group,
      levels = levels(fundraising_alt$zip_group)
    )
  )

# Creating the num_don variable which is a variable to
# address the amount of donations an individual made

fundraising_alt <- fundraising_alt %>%
  mutate(
    num_don = if_else(
      avg_gift > 0,
      lifetime_gifts / avg_gift,
      0
    )
  )
future_fundraising_alt <- future_fundraising_alt %>%
  mutate(
    num_don = if_else(
      avg_gift > 0,
      lifetime_gifts / avg_gift,
      0
    )
  )
# Creating the don_by_promo variable
# to account for those who donate a lot but also receive a lot of promos

fundraising_alt <- fundraising_alt %>%
  mutate(
    don_by_promo = if_else(
      num_prom > 0,
      num_don / num_prom,
      0
    )
  )

future_fundraising_alt <- future_fundraising_alt %>%
  mutate(
    don_by_promo = if_else(
      num_prom > 0,
      num_don / num_prom,
      0
    )
  )

# Setting up num_child to be able to be used as a dummy variable
# to try to account for the overwhelming of them to be 1
fundraising_alt <- fundraising_alt %>%
  mutate(num_child = factor(num_child))

future_fundraising_alt <- future_fundraising_alt %>%
  mutate(
    num_child = factor(
      num_child,
      levels = levels(fundraising_alt$num_child)
    )
  )

# Creating a high-earner variable which is to
# highlight those who are above the median in income but
# live in areas with above median proverty

pct_lt15k_median <- median(
  fundraising_alt$pct_lt15k,
  na.rm = TRUE
)

pct_lt15k_median
## [1] 12
fundraising_alt <- fundraising_alt %>%
  mutate(
    high_earner = if_else(
      income >= 5 & pct_lt15k > pct_lt15k_median,
      "Yes",
      "No"
    ),
    high_earner = factor(
      high_earner,
      levels = c("No", "Yes")
    )
  )

future_fundraising_alt <- future_fundraising_alt %>%
  mutate(
    high_earner = if_else(
      income >= 5 & pct_lt15k > pct_lt15k_median,
      "Yes",
      "No"
    ),
    high_earner = factor(
      high_earner,
      levels = c("No", "Yes")
    )
  )

Models and Training

set.seed(12345)

cv_folds <- createMultiFolds(
  fundraising_alt$target,
  k = 5,
  times = 2
)

ctrl <- trainControl(
  method = "repeatedcv",
  number = 5,
  repeats = 2,
  index = cv_folds,
  classProbs = TRUE,
  summaryFunction = twoClassSummary,
  savePredictions = "final",
  allowParallel = TRUE,
  verboseIter = FALSE
)

fundraising_alt$target <- factor(
  fundraising_alt$target,
  levels = c("Donor", "No_Donor")
)

# this is to create the recipe I will be using for each of the models
# I wanted to account for the difference by zip and account for differences
# and correlations that might not be taken in account just running the model

fundraising_recipe <- recipe(
  target ~ .,
  data = fundraising_alt
) %>%

  step_rm(
    zipconvert1,
    zipconvert2,
    zipconvert3,
    zipconvert4,
    zipconvert5
  ) %>%

  step_string2factor(
    all_nominal_predictors()
  ) %>%

  step_novel(
    all_nominal_predictors()
  ) %>%

  step_unknown(
    all_nominal_predictors()
  ) %>%

  step_dummy(
    all_nominal_predictors()
  ) %>%

  step_normalize(
    last_gift,
    months_since_donate
  ) %>%

  step_mutate(
    donation_recency_score =
      last_gift - months_since_donate
  ) %>%

  step_zv(
    all_predictors()
  )

# Time to train some models, first I'm going with is the randome forest model

rf_grid <- expand.grid(
  mtry = c(4, 8, 12),
  splitrule = "gini",
  min.node.size = c(5, 15)
)


rf_fit <- train(
  target ~ .,
  data = fundraising_alt,
  method = "ranger",
  metric = "Accuracy",
  trControl = ctrl,
  tuneGrid = rf_grid,
  num.trees = 500,
  importance = "permutation"
)
## Warning in train.default(x, y, weights = w, ...): The metric "Accuracy" was not
## in the result set. ROC will be used instead.
rf_fit
## Random Forest 
## 
## 3000 samples
##   25 predictor
##    2 classes: 'Donor', 'No_Donor' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 2401, 2400, 2400, 2399, 2400, 2400, ... 
## Resampling results across tuning parameters:
## 
##   mtry  min.node.size  ROC        Sens       Spec     
##    4     5             0.5593125  0.5543445  0.5186910
##    4    15             0.5656558  0.5600212  0.5306833
##    8     5             0.5626473  0.5526767  0.5300100
##    8    15             0.5631776  0.5566823  0.5300111
##   12     5             0.5582993  0.5469989  0.5240233
##   12    15             0.5596418  0.5440000  0.5283477
## 
## Tuning parameter 'splitrule' was held constant at a value of gini
## ROC was used to select the optimal model using the largest value.
## The final values used for the model were mtry = 4, splitrule = gini
##  and min.node.size = 15.
plot(rf_fit)

rf_importance <- varImp(
  rf_fit,
  scale = TRUE
)

rf_importance
## ranger variable importance
## 
##   only 20 most important variables shown (out of 31)
## 
##                     Overall
## months_since_donate 100.000
## largest_gift         99.618
## don_by_promo         96.400
## num_don              95.148
## med_fam_inc          63.240
## avg_gift             59.389
## last_gift            58.661
## avg_fam_inc          55.636
## lifetime_gifts       46.004
## num_prom             40.481
## home_value           39.213
## pct_lt15k            38.066
## income               31.438
## wealth               17.833
## high_earnerYes       13.296
## time_lag             13.146
## homeownerYes         11.946
## num_child3           10.905
## zip_groupzip3         7.021
## zipconvert1Yes        6.466
plot(
  rf_importance,
  top = 20
)

# Second Model Naive Bayes

nb_grid <- expand.grid(
  laplace = c(0, 1),
  usekernel = c(TRUE, FALSE),
  adjust = c(0.5, 1)
)


nb_fit <- train(
  fundraising_recipe,
  data = fundraising_alt,
  method = "naive_bayes",
  metric = "ROC",
  trControl = ctrl,
  tuneGrid = nb_grid
)

nb_fit
## Naive Bayes 
## 
## 3000 samples
##   25 predictor
##    2 classes: 'Donor', 'No_Donor' 
## 
## Recipe steps: rm, string2factor, novel, unknown, dummy, normalize, mutate, zv 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 2401, 2400, 2400, 2399, 2400, 2400, ... 
## Resampling results across tuning parameters:
## 
##   laplace  usekernel  adjust  ROC        Sens       Spec     
##   0        FALSE      0.5     0.5541571  0.9178662  0.1093112
##   0        FALSE      1.0     0.5541571  0.9178662  0.1093112
##   0         TRUE      0.5     0.5723121  0.1939197  0.8370244
##   0         TRUE      1.0     0.5801272  0.1669130  0.8600033
##   1        FALSE      0.5     0.5541571  0.9178662  0.1093112
##   1        FALSE      1.0     0.5541571  0.9178662  0.1093112
##   1         TRUE      0.5     0.5723121  0.1939197  0.8370244
##   1         TRUE      1.0     0.5801272  0.1669130  0.8600033
## 
## ROC was used to select the optimal model using the largest value.
## The final values used for the model were laplace = 0, usekernel = TRUE
##  and adjust = 1.
plot(nb_fit)

# Final Model Gradient Boost
# Had to to the gmb instead of xgboost to get it to work in caret

gbm_grid <- expand.grid(
  n.trees = c(100, 250, 500),
  interaction.depth = c(1, 2, 3, 5),
  shrinkage = c(0.005, 0.01, 0.05),
  n.minobsinnode = c(5, 10)
)

gbm_fit <- train(
  fundraising_recipe,
  data = fundraising_alt,
  method = "gbm",
  metric = "ROC",
  trControl = ctrl,
  tuneGrid = gbm_grid,
  verbose = FALSE
)
## Warning: package 'plyr' was built under R version 4.6.1
## ------------------------------------------------------------------------------
## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)
## ------------------------------------------------------------------------------
## 
## Attaching package: 'plyr'
## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, mutate, rename, summarise, summarize
## The following object is masked from 'package:purrr':
## 
##     compact
gbm_fit
## Stochastic Gradient Boosting 
## 
## 3000 samples
##   25 predictor
##    2 classes: 'Donor', 'No_Donor' 
## 
## Recipe steps: rm, string2factor, novel, unknown, dummy, normalize, mutate, zv 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 2401, 2400, 2400, 2399, 2400, 2400, ... 
## Resampling results across tuning parameters:
## 
##   shrinkage  interaction.depth  n.minobsinnode  n.trees  ROC        Sens     
##   0.005      1                   5              100      0.5822641  0.5646878
##   0.005      1                   5              250      0.5851652  0.5663657
##   0.005      1                   5              500      0.5872155  0.5566957
##   0.005      1                  10              100      0.5805518  0.5583545
##   0.005      1                  10              250      0.5838632  0.5570201
##   0.005      1                  10              500      0.5868629  0.5570234
##   0.005      2                   5              100      0.5818108  0.5630290
##   0.005      2                   5              250      0.5844711  0.5586923
##   0.005      2                   5              500      0.5860007  0.5453411
##   0.005      2                  10              100      0.5837895  0.5596979
##   0.005      2                  10              250      0.5853329  0.5536845
##   0.005      2                  10              500      0.5857896  0.5483467
##   0.005      3                   5              100      0.5814290  0.5520033
##   0.005      3                   5              250      0.5836991  0.5493434
##   0.005      3                   5              500      0.5845476  0.5430100
##   0.005      3                  10              100      0.5816130  0.5566756
##   0.005      3                  10              250      0.5831740  0.5573445
##   0.005      3                  10              500      0.5829150  0.5463478
##   0.005      5                   5              100      0.5821805  0.5516689
##   0.005      5                   5              250      0.5833722  0.5450089
##   0.005      5                   5              500      0.5819621  0.5410100
##   0.005      5                  10              100      0.5810721  0.5506700
##   0.005      5                  10              250      0.5820638  0.5466800
##   0.005      5                  10              500      0.5822077  0.5436767
##   0.010      1                   5              100      0.5841452  0.5640223
##   0.010      1                   5              250      0.5864148  0.5596945
##   0.010      1                   5              500      0.5870920  0.5436845
##   0.010      1                  10              100      0.5835420  0.5687023
##   0.010      1                  10              250      0.5871074  0.5613579
##   0.010      1                  10              500      0.5872255  0.5466812
##   0.010      2                   5              100      0.5824910  0.5570256
##   0.010      2                   5              250      0.5833001  0.5423501
##   0.010      2                   5              500      0.5820735  0.5390111
##   0.010      2                  10              100      0.5842321  0.5540223
##   0.010      2                  10              250      0.5842267  0.5513489
##   0.010      2                  10              500      0.5831001  0.5406789
##   0.010      3                   5              100      0.5826597  0.5450089
##   0.010      3                   5              250      0.5839343  0.5406745
##   0.010      3                   5              500      0.5814735  0.5383423
##   0.010      3                  10              100      0.5817385  0.5503467
##   0.010      3                  10              250      0.5820008  0.5410145
##   0.010      3                  10              500      0.5804678  0.5390145
##   0.010      5                   5              100      0.5808976  0.5530212
##   0.010      5                   5              250      0.5797393  0.5460089
##   0.010      5                   5              500      0.5769186  0.5466800
##   0.010      5                  10              100      0.5802225  0.5476734
##   0.010      5                  10              250      0.5823451  0.5460123
##   0.010      5                  10              500      0.5775965  0.5430134
##   0.050      1                   5              100      0.5880296  0.5466845
##   0.050      1                   5              250      0.5802318  0.5313456
##   0.050      1                   5              500      0.5730885  0.5306789
##   0.050      1                  10              100      0.5864116  0.5476912
##   0.050      1                  10              250      0.5821620  0.5353378
##   0.050      1                  10              500      0.5748724  0.5306845
##   0.050      2                   5              100      0.5817226  0.5380212
##   0.050      2                   5              250      0.5759076  0.5316823
##   0.050      2                   5              500      0.5663843  0.5356867
##   0.050      2                  10              100      0.5819604  0.5413411
##   0.050      2                  10              250      0.5733330  0.5316734
##   0.050      2                  10              500      0.5633648  0.5370234
##   0.050      3                   5              100      0.5795347  0.5383411
##   0.050      3                   5              250      0.5708600  0.5413411
##   0.050      3                   5              500      0.5585885  0.5340111
##   0.050      3                  10              100      0.5779520  0.5426823
##   0.050      3                  10              250      0.5666138  0.5416812
##   0.050      3                  10              500      0.5555154  0.5380212
##   0.050      5                   5              100      0.5708157  0.5376589
##   0.050      5                   5              250      0.5595286  0.5363356
##   0.050      5                   5              500      0.5496128  0.5316711
##   0.050      5                  10              100      0.5744734  0.5393523
##   0.050      5                  10              250      0.5643107  0.5370056
##   0.050      5                  10              500      0.5533692  0.5340022
##   Spec     
##   0.5446633
##   0.5506512
##   0.5576456
##   0.5566434
##   0.5569801
##   0.5563101
##   0.5456523
##   0.5556489
##   0.5663101
##   0.5543178
##   0.5596456
##   0.5636401
##   0.5546567
##   0.5556489
##   0.5606512
##   0.5526567
##   0.5576445
##   0.5579801
##   0.5509900
##   0.5546534
##   0.5603178
##   0.5556567
##   0.5519845
##   0.5639779
##   0.5513289
##   0.5579790
##   0.5649801
##   0.5489967
##   0.5559756
##   0.5686423
##   0.5563189
##   0.5613145
##   0.5659767
##   0.5576523
##   0.5619823
##   0.5673112
##   0.5626401
##   0.5599956
##   0.5636467
##   0.5586434
##   0.5596523
##   0.5636489
##   0.5549856
##   0.5573245
##   0.5526600
##   0.5586545
##   0.5539911
##   0.5536656
##   0.5656379
##   0.5679701
##   0.5606534
##   0.5696235
##   0.5656268
##   0.5583112
##   0.5666246
##   0.5619635
##   0.5496467
##   0.5616390
##   0.5589856
##   0.5523145
##   0.5636445
##   0.5529911
##   0.5509856
##   0.5643234
##   0.5469967
##   0.5376667
##   0.5539900
##   0.5440011
##   0.5310000
##   0.5573234
##   0.5559823
##   0.5409978
## 
## ROC was used to select the optimal model using the largest value.
## The final values used for the model were n.trees = 100, interaction.depth =
##  1, shrinkage = 0.05 and n.minobsinnode = 5.
plot(gbm_fit)

# So I started with just 3 but NaiveBayes did real bad, RF did the best
# on the real data submission while GBM did best according to CV.
# I wanted to test a couple more I thought might work on this data
# Regularized Logistic Regression 

glmnet_grid <- expand.grid(
  alpha = c(0, 0.5, 1),
  lambda = seq(0.0001, 0.1, length = 15)
)


glmnet_fit <- train(
  fundraising_recipe,
  data = fundraising_alt,
  method = "glmnet",
  metric = "ROC",
  trControl = ctrl,
  tuneGrid = glmnet_grid
)
## Loading required namespace: glmnet
## Warning: package 'glmnet' was built under R version 4.6.1
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
## Loaded glmnet 5.0
# Second new model will be SVM

svm_grid <- expand.grid(
  sigma = c(0.001, 0.01),
  C = c(0.25, 0.5, 1, 2)
)

svm_fit <- train(
  fundraising_recipe,
  data = fundraising_alt,
  method = "svmRadial",
  metric = "ROC",
  trControl = ctrl,
  tuneGrid = svm_grid
)

# Removing the fundraising_recipe

rf_fit_raw <- train(
  target ~ .,
  data = fundraising_alt,
  method = "ranger",
  metric = "ROC",
  trControl = ctrl,
  tuneGrid = rf_grid,
  num.trees = 500,
  importance = "permutation"
)

# I tested this and it came out to essentially be like the
# other random forest model so I didn't include later
# however I wanted to include that I did it so there 
# won't be questions about if it was better this way

Model Comparison

model_resamples <- resamples(
  list(
    Random_Forest = rf_fit,
    Naive_Bayes = nb_fit,
    GBM = gbm_fit,
    Logistic = glmnet_fit,
    SVM = svm_fit
  )
)

summary(model_resamples)
## 
## Call:
## summary.resamples(object = model_resamples)
## 
## Models: Random_Forest, Naive_Bayes, GBM, Logistic, SVM 
## Number of resamples: 10 
## 
## ROC 
##                    Min.   1st Qu.    Median      Mean   3rd Qu.      Max. NA's
## Random_Forest 0.5216390 0.5631913 0.5742389 0.5656558 0.5804244 0.5834333    0
## Naive_Bayes   0.5236102 0.5736024 0.5807284 0.5801272 0.5918628 0.6261333    0
## GBM           0.5286268 0.5706942 0.5934250 0.5880296 0.6025681 0.6391056    0
## Logistic      0.5250055 0.5636133 0.5831079 0.5813754 0.6026917 0.6177000    0
## SVM           0.5315725 0.5694806 0.5918489 0.5846201 0.5987139 0.6157000    0
## 
## Sens 
##                    Min.    1st Qu.     Median      Mean    3rd Qu.      Max.
## Random_Forest 0.5317726 0.54333333 0.56500000 0.5600212 0.57583333 0.5866667
## Naive_Bayes   0.0100000 0.01666667 0.02166667 0.1669130 0.02918896 0.7966667
## GBM           0.5033333 0.52882107 0.54333333 0.5466845 0.56500000 0.6000000
## Logistic      0.5400000 0.57250000 0.58430881 0.5860624 0.59983835 0.6300000
## SVM           0.4800000 0.52797938 0.55833333 0.5476990 0.56333333 0.6033333
##               NA's
## Random_Forest    0
## Naive_Bayes      0
## GBM              0
## Logistic         0
## SVM              0
## 
## Spec 
##                    Min.   1st Qu.    Median      Mean   3rd Qu.      Max. NA's
## Random_Forest 0.4617940 0.4966667 0.5450000 0.5306833 0.5591667 0.5800000    0
## Naive_Bayes   0.3133333 0.9758333 0.9916667 0.8600033 0.9958472 1.0000000    0
## GBM           0.5315615 0.5441667 0.5483333 0.5656379 0.5937043 0.6300000    0
## Logistic      0.5049834 0.5133333 0.5341307 0.5396578 0.5591667 0.6166667    0
## SVM           0.5348837 0.5433333 0.5650000 0.5729756 0.5958333 0.6500000    0
bwplot(
  model_resamples,
  metric = "ROC"
)

model_differences <- diff(
  model_resamples
)

summary(model_differences)
## 
## Call:
## summary.diff.resamples(object = model_differences)
## 
## p-value adjustment: bonferroni 
## Upper diagonal: estimates of the difference
## Lower diagonal: p-value for H0: difference = 0
## 
## ROC 
##               Random_Forest Naive_Bayes GBM       Logistic  SVM      
## Random_Forest               -0.014471   -0.022374 -0.015720 -0.018964
## Naive_Bayes   0.40715                   -0.007902 -0.001248 -0.004493
## GBM           0.02441       0.98398                0.006654  0.003409
## Logistic      0.25139       1.00000     1.00000             -0.003245
## SVM           0.10247       1.00000     1.00000   1.00000            
## 
## Sens 
##               Random_Forest Naive_Bayes GBM       Logistic  SVM      
## Random_Forest                0.393108    0.013337 -0.026041  0.012322
## Naive_Bayes   0.039474                  -0.379771 -0.419149 -0.380786
## GBM           0.976903      0.045982              -0.039378 -0.001014
## Logistic      0.311629      0.023409    0.007466             0.038363
## SVM           1.000000      0.031751    1.000000  0.044060           
## 
## Spec 
##               Random_Forest Naive_Bayes GBM       Logistic  SVM      
## Random_Forest               -0.329320   -0.034955 -0.008975 -0.042292
## Naive_Bayes   0.045440                   0.294365  0.320346  0.287028
## GBM           0.044065      0.067723               0.025980 -0.007338
## Logistic      1.000000      0.054037    0.204167            -0.033318
## SVM           0.005028      0.080486    1.000000  0.010416
comparison_table <- tibble(

  Model = c(
    "Random Forest",
    "Naive Bayes",
    "GBM",
    "Regularized Logistic",
    "SVM"
  ),

  ROC = c(

    max(rf_fit$results$ROC),

    max(nb_fit$results$ROC),

    max(gbm_fit$results$ROC),

    max(glmnet_fit$results$ROC),

    max(svm_fit$results$ROC)

  ),

  Sensitivity = c(

    rf_fit$results$Sens[
      which.max(rf_fit$results$ROC)
    ],

    nb_fit$results$Sens[
      which.max(nb_fit$results$ROC)
    ],

    gbm_fit$results$Sens[
      which.max(gbm_fit$results$ROC)
    ],

    glmnet_fit$results$Sens[
      which.max(glmnet_fit$results$ROC)
    ],

    svm_fit$results$Sens[
      which.max(svm_fit$results$ROC)
    ]

  ),

  Specificity = c(

    rf_fit$results$Spec[
      which.max(rf_fit$results$ROC)
    ],

    nb_fit$results$Spec[
      which.max(nb_fit$results$ROC)
    ],

    gbm_fit$results$Spec[
      which.max(gbm_fit$results$ROC)
    ],

    glmnet_fit$results$Spec[
      which.max(glmnet_fit$results$ROC)
    ],

    svm_fit$results$Spec[
      which.max(svm_fit$results$ROC)
    ]

  )

) %>%
  arrange(desc(ROC))

comparison_table
best_model <- rf_fit

future_predictions <- predict(
  best_model,
  newdata = future_fundraising_alt,
  type = "raw"
)

table(future_predictions)
## future_predictions
##    Donor No_Donor 
##       61       59
submission <- tibble(
  target = if_else(
    future_predictions == "No_Donor",
    "No Donor",
    "Donor"
  )
)

write_csv(
  submission,
  "fundraising_submission.csv"
)