library(caret)Loading required package: ggplot2
Loading required package: lattice
options(show.signif.stars = FALSE)
# import
df <- read.csv("insurance-testing-data2.csv", stringsAsFactors = FALSE, na.strings = c("", "NA"))
# clean up the money columns, they come in as text like "$18,755"
df$INCOME <- as.numeric(gsub("[$,]", "", df$INCOME))
df$HOME_VAL <- as.numeric(gsub("[$,]", "", df$HOME_VAL))
df$BLUEBOOK <- as.numeric(gsub("[$,]", "", df$BLUEBOOK))
df$OLDCLAIM <- as.numeric(gsub("[$,]", "", df$OLDCLAIM))
df$INDEX <- NULL
df$TARGET_AMT <- NULL
# fill NAs with the median
df$AGE[is.na(df$AGE)] <- median(df$AGE, na.rm = TRUE)
df$YOJ[is.na(df$YOJ)] <- median(df$YOJ, na.rm = TRUE)
df$INCOME[is.na(df$INCOME)] <- median(df$INCOME, na.rm = TRUE)
df$HOME_VAL[is.na(df$HOME_VAL)] <- median(df$HOME_VAL, na.rm = TRUE)
df$BLUEBOOK[is.na(df$BLUEBOOK)] <- median(df$BLUEBOOK, na.rm = TRUE)
df$OLDCLAIM[is.na(df$OLDCLAIM)] <- median(df$OLDCLAIM, na.rm = TRUE)
df$CAR_AGE[is.na(df$CAR_AGE)] <- median(df$CAR_AGE, na.rm = TRUE)
# make the text columns factors
df$PARENT1 <- factor(df$PARENT1)
df$MSTATUS <- factor(df$MSTATUS)
df$SEX <- factor(df$SEX)
df$EDUCATION <- factor(df$EDUCATION)
df$JOB <- factor(df$JOB)
df$CAR_USE <- factor(df$CAR_USE)
df$CAR_TYPE <- factor(df$CAR_TYPE)
df$RED_CAR <- factor(df$RED_CAR)
df$REVOKED <- factor(df$REVOKED)
df$URBANICITY <- factor(df$URBANICITY)
df$TARGET_FLAG <- factor(df$TARGET_FLAG, levels = c(0, 1))
# split into train and test
set.seed(42)
split <- createDataPartition(df$TARGET_FLAG, p = 0.75, list = FALSE)
train <- df[split, ]
test <- df[-split, ]
# build the logistic model on train, using every predictor
model <- glm(TARGET_FLAG ~ ., data = train, family = binomial)
summary(model)
Call:
glm(formula = TARGET_FLAG ~ ., family = binomial, data = train)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -1.712e-01 7.569e-01 -0.226 0.821042
KIDSDRIV 2.775e-02 1.730e-01 0.160 0.872605
AGE 5.208e-03 1.121e-02 0.464 0.642318
HOMEKIDS 1.192e-02 9.925e-02 0.120 0.904426
YOJ -5.605e-03 2.403e-02 -0.233 0.815527
INCOME -5.387e-06 3.437e-06 -1.567 0.117031
PARENT1Yes 3.780e-01 3.073e-01 1.230 0.218719
HOME_VAL -3.670e-06 1.003e-06 -3.658 0.000254
MSTATUSz_No 3.311e-01 2.279e-01 1.453 0.146167
SEXz_F 3.368e-01 3.204e-01 1.051 0.293117
EDUCATIONBachelors -3.207e-01 3.216e-01 -0.997 0.318623
EDUCATIONMasters -6.953e-01 5.342e-01 -1.302 0.193053
EDUCATIONPhD 2.417e-01 6.563e-01 0.368 0.712703
EDUCATIONz_High School -6.722e-02 2.626e-01 -0.256 0.797933
JOBDoctor -4.646e-01 7.617e-01 -0.610 0.541901
JOBHome Maker -5.526e-01 4.017e-01 -1.376 0.168976
JOBLawyer 3.047e-01 5.505e-01 0.554 0.579840
JOBManager -1.360e+00 3.940e-01 -3.451 0.000559
JOBProfessional -4.247e-01 3.481e-01 -1.220 0.222508
JOBStudent -7.930e-01 3.655e-01 -2.170 0.030037
JOBz_Blue Collar -5.654e-01 2.974e-01 -1.901 0.057339
TRAVTIME 2.119e-02 5.402e-03 3.923 8.75e-05
CAR_USEPrivate -1.092e+00 2.493e-01 -4.378 1.20e-05
BLUEBOOK -2.763e-05 1.439e-05 -1.920 0.054871
TIF -3.625e-02 1.981e-02 -1.830 0.067214
CAR_TYPEPanel Truck 1.116e+00 4.527e-01 2.465 0.013698
CAR_TYPEPickup 6.233e-01 2.870e-01 2.172 0.029887
CAR_TYPESports Car 1.214e+00 3.549e-01 3.422 0.000621
CAR_TYPEVan 8.214e-01 3.496e-01 2.350 0.018789
CAR_TYPEz_SUV 5.202e-01 3.067e-01 1.696 0.089910
RED_CARyes 1.041e-02 2.532e-01 0.041 0.967223
OLDCLAIM -1.687e-05 1.233e-05 -1.369 0.171065
CLM_FREQ 2.318e-01 8.188e-02 2.831 0.004646
REVOKEDYes 7.447e-01 2.753e-01 2.705 0.006830
MVR_PTS 9.847e-02 3.796e-02 2.594 0.009478
CAR_AGE -8.597e-03 2.158e-02 -0.398 0.690284
URBANICITYz_Highly Rural/ Rural -2.544e+00 3.038e-01 -8.372 < 2e-16
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 1317.3 on 1141 degrees of freedom
Residual deviance: 978.3 on 1105 degrees of freedom
(84 observations deleted due to missingness)
AIC: 1052.3
Number of Fisher Scoring iterations: 5
# predict onto test data
prob <- predict(model, newdata = test, type = "response")
pred <- ifelse(prob > 0.5, 1, 0)
# confusion matrix on test data, actual on rows and predicted on columns
cm <- table(Actual = test$TARGET_FLAG, Predicted = pred)
cm Predicted
Actual 0 1
0 253 28
1 53 50
accuracy <- sum(diag(cm)) / sum(cm)
sensitivity <- cm["1", "1"] / sum(cm["1", ]) # recall, TP / (TP + FN)
precision <- cm["1", "1"] / sum(cm[, "1"]) # TP / (TP + FP)
f1 <- 2 * (precision * sensitivity) / (precision + sensitivity)
accuracy[1] 0.7890625
sensitivity[1] 0.4854369
precision[1] 0.6410256
f1[1] 0.5524862