Wine Case Purchase Prediction

Load necessary libraries

library(dplyr) library(ggplot2) library(readr) library(stargazer) library(corrplot) library(MASS)

Load the dataset

Ensure that the data is correctly loaded; if the file is not found, set the correct working directory.

wine_data <- read_csv(“wine-data-1.csv”)

Data Exploration

1.1 Load the Data

Display the first few rows of the dataset to understand its structure and check for any obvious data issues.

head(wine_data)

INDEX TARGET FixedAcidity VolatileAcidity CitricAcid ResidualSugar Chlorides 1 1 3 3.2 1.160 -0.98 54.2 -0.567 2 2 3 4.5 0.160 -0.81 26.1 -0.425 3 4 5 7.1 2.640 -0.88 14.8 0.037 4 5 3 5.7 0.385 0.04 18.8 -0.425 5 6 4 8.0 0.330 -1.26 9.4 NA 6 7 0 11.3 0.320 0.59 2.2 0.556 FreeSulfurDioxide TotalSulfurDioxide Density pH Sulphates Alcohol LabelAppeal AcidIndex 1 NA 268 0.99280 3.33 -0.59 9.9 0 8 2 15 -327 1.02792 3.38 0.70 NA -1 7 3 214 142 0.99518 3.12 0.48 22.0 -1 8 4 22 115 0.99640 2.24 1.83 6.2 -1 6 5 -167 108 0.99457 3.12 1.77 13.7 0 9 6 -37 15 0.99940 3.20 1.29 15.4 0 11 STARS 1 2 2 3 3 3 4 1 5 2 6 NA

1.2 Summary Statistics

Generate a professional summary of the dataset using stargazer.

This includes the mean, standard deviation, min, max, and other relevant statistics.

stargazer(wine_data, type = “text”, title = “Summary Statistics”, digits = 2)

1.3 Correlation Matrix

Replace any NA/NaN/Inf values to avoid errors in the correlation calculation.

wine_data_clean <- wine_data %>% mutate_all(~ifelse(is.infinite(.), NA, .)) %>% na.omit()

Recalculate the correlation matrix after cleaning the data.

cor_matrix <- cor(wine_data_clean[ , !(names(wine_data_clean) %in% c(“INDEX”))])

Plot the correlation matrix

The hclust method helps in clustering variables that are highly correlated, making the plot more interpretable.

corrplot(cor_matrix, method = “color”, order = “hclust”, addCoef.col = “black”, tl.cex = 0.7)

Discuss the key takeaways from the correlation matrix:

Data Preparation

2.1 Handling Missing Values and Feature Engineering

Check for negative values in the Alcohol column

Alcohol content should not be negative; this step ensures data integrity before applying transformations.

negative_alcohols <- wine_data %>% filter(Alcohol < 0)

Display any rows with negative Alcohol values

If any negative values exist, they are likely data entry errors and should be addressed.

print(negative_alcohols)

INDEX TARGET FixedAcidity VolatileAcidity CitricAcid ResidualSugar Chlorides 1 49 0 6.9 0.300 0.29 1.30 NA 2 480 3 -4.2 0.470 -0.58 30.40 0.556 3 594 3 6.5 0.550 0.44 -5.00 0.043 4 842 5 5.9 0.190 0.26 7.40 1.153 5 855 3 1.6 0.280 1.71 3.00 0.028 6 1422 3 15.1 -0.470 0.43 7.50 0.834 7 1798 0 4.1 0.240 0.20 15.80 0.447 8 1806 5 9.4 0.250 0.36 NA -0.378 9 1817 2 9.9 1.005 1.08 1.40 0.046 10 1852 3 8.2 -0.310 0.60 3.00 -0.456 11 1862 3 1.5 -1.500 0.09 -3.80 -0.106 12 1944 3 15.7 -1.710 0.33 1.40 0.028 13 2207 4 -4.2 -0.060 0.32 1.90 -0.311 14 2637 5 5.1 -0.040 1.58 2.30 -0.260 15 2733 4 9.4 0.930 0.93 4.45 0.149 16 2792 4 6.9 -1.040 0.36 1.30 0.036 17 2831 0 -2.8 0.230 0.36 17.20 0.039 18 2914 4 20.9 0.270 0.33 -62.50 0.064 19 3298 4 15.7 1.760 -0.16 -52.60 0.043 20 3503 0 17.1 0.270 0.53 38.80 0.882 21 3530 0 16.3 1.340 0.40 -60.60 0.068 22 3728 0 6.6 0.500 -0.84 1.50 0.060 23 3866 4 -4.8 0.100 0.50 NA 0.053 24 3879 0 10.5 1.040 0.75 1.70 0.050 25 3919 3 7.7 0.410 1.10 4.80 0.052 26 4039 5 -2.1 0.430 1.84 67.80 -0.340 27 4046 3 -1.9 -0.070 -0.58 11.00 0.538 28 4109 5 4.1 0.690 2.10 -38.70 0.219 29 4135 4 7.8 0.300 0.29 7.45 0.054 30 4169 2 -1.7 0.755 0.50 -109.60 0.084 31 4214 0 8.9 0.620 0.05 -19.50 -0.513 32 4889 0 7.2 0.200 0.26 4.50 0.316 33 5074 4 11.0 2.910 0.93 NA 0.055 34 5113 2 1.3 0.230 0.35 10.30 0.042 35 5169 3 1.8 -0.765 0.00 -65.90 NA 36 5598 4 -2.6 0.130 -0.97 12.85 0.042 37 5730 2 9.2 -0.990 1.59 2.00 0.047 38 5753 4 1.2 -0.490 -0.14 -38.40 0.050 39 5773 3 5.2 -0.290 0.82 11.70 0.084 40 5860 3 7.3 0.670 0.59 -11.60 0.401 41 5934 3 6.7 -0.310 0.37 48.50 0.043 42 6097 6 8.1 0.140 0.35 1.70 0.030 43 6181 5 -0.7 -1.260 0.44 11.30 0.046 44 6258 3 6.8 0.230 1.45 -28.70 -0.201 45 6304 4 10.0 0.565 -0.44 46.00 0.093 46 6369 5 6.5 -0.150 1.32 55.10 0.158 47 6632 3 8.6 0.485 0.67 4.10 NA 48 6659 0 24.4 1.510 -0.91 111.50 0.019 49 7081 6 3.3 -0.630 0.40 NA 0.055 50 7185 3 7.5 -0.720 -0.64 1.60 0.079 51 7228 4 13.5 0.300 0.42 14.30 0.045 52 7331 2 5.8 -2.510 1.38 -50.00 -0.288 53 7339 3 6.9 0.200 0.34 12.40 -0.372 54 7504 7 8.1 0.170 1.82 14.10 0.249 55 7568 2 14.3 0.340 -0.66 44.60 -0.040 56 7630 3 7.6 0.790 -0.02 1.50 0.248 57 7664 4 7.3 0.260 1.86 9.70 -0.414 58 7828 4 1.7 0.555 -1.99 4.50 0.399 59 7930 5 0.8 0.220 0.37 15.00 -0.382 60 8435 0 19.8 1.540 0.40 1.30 0.044 61 8576 5 7.6 0.300 0.47 -35.30 0.039 62 8618 2 -0.2 -0.010 0.63 -25.60 NA FreeSulfurDioxide TotalSulfurDioxide Density pH Sulphates Alcohol LabelAppeal AcidIndex 1 24 189 1.02393 3.29 -0.83 -3.1 1 7 2 11 77 0.99560 4.38 NA -1.1 0 8 3 NA -30 0.98659 4.38 0.48 -0.2 0 7 4 -39 -99 1.02112 3.49 -0.50 -2.1 1 6 5 19 98 0.99303 2.05 1.17 -0.3 -1 7 6 65 243 1.02995 3.70 0.34 -4.3 0 7 7 11 65 0.97091 3.54 2.15 -2.5 -1 8 8 -65 402 1.01323 3.39 1.55 -3.1 2 7 9 34 NA 0.99308 3.25 -0.53 -3.6 0 11 10 10 22 0.99828 4.20 NA -0.5 0 9 11 210 211 1.00542 2.86 1.35 -3.3 0 7 12 169 99 0.99280 3.23 NA -0.2 -1 7 13 27 253 1.00527 1.91 0.49 -1.8 0 8 14 40 -468 0.98944 3.55 0.94 -1.2 1 6 15 33 182 0.99240 2.60 NA -1.1 0 9 16 126 381 1.01811 2.17 0.95 -1.6 -1 7 17 37 510 0.99946 3.65 0.01 -0.1 0 7 18 200 45 1.01879 2.70 0.40 -1.7 0 7 19 34 142 0.96901 3.14 0.48 -1.7 1 6 20 255 -336 0.99620 2.92 1.13 -1.6 1 10 21 41 54 0.99754 3.38 0.86 -1.9 -1 11 22 -122 369 0.95309 2.61 0.58 -1.8 1 7 23 22 118 0.99685 4.40 NA -2.4 0 8 24 40 -111 0.96999 2.59 0.52 -4.4 0 8 25 49 142 0.99460 1.05 0.04 -2.0 0 7 26 143 118 0.99452 3.03 0.37 -0.9 1 7 27 -42 178 0.99760 4.30 1.89 -4.4 0 8 28 18 425 0.97167 3.76 0.36 -1.7 1 7 29 208 135 1.02541 3.16 0.38 -4.0 0 8 30 114 12 1.01938 NA 1.73 -3.0 0 8 31 11 -244 0.96903 2.81 0.66 -0.2 2 9 32 NA 133 0.95970 2.24 1.53 -1.1 -1 8 33 168 536 0.99170 2.12 -0.63 -1.1 0 8 34 54 140 1.04285 4.46 0.04 -2.5 -1 7 35 79 348 0.96214 3.16 -0.16 -3.8 -1 8 36 23 105 0.99581 4.01 NA -2.1 0 8 37 175 104 0.99517 5.43 0.66 -3.7 0 10 38 -116 140 0.99526 4.21 0.40 -2.7 1 7 39 -27 -94 1.01458 2.91 0.02 -0.4 0 8 40 16 -194 0.98723 3.16 NA -3.6 0 8 41 64 NA 0.98216 2.28 1.33 -1.7 -1 7 42 38 -238 0.99255 4.23 0.80 -2.7 0 9 43 65 146 1.01929 3.93 1.41 -2.4 1 8 44 -223 21 0.97232 2.16 NA -0.2 -1 8 45 16 112 0.99980 3.38 0.61 -0.8 1 10 46 270 NA 0.94286 3.06 0.37 -0.2 1 7 47 209 -66 0.99180 3.85 -0.31 -1.1 0 9 48 50 280 0.99629 2.29 0.63 -2.1 -1 7 49 41 167 0.99668 2.77 0.40 -0.5 1 9 50 264 58 0.95521 3.34 0.58 -1.6 0 8 51 -367 439 0.99910 3.58 0.63 -3.3 1 8 52 -12 317 0.99560 NA 0.42 -2.0 -2 6 53 25 NA 1.02819 4.25 -0.94 -0.2 1 7 54 43 -75 1.00060 3.80 NA -0.1 1 9 55 49 198 0.94717 3.23 0.84 -0.7 -1 7 56 114 NA 0.96339 3.80 0.51 -3.0 0 8 57 30 374 0.99620 3.64 0.47 -4.5 0 7 58 17 -245 0.99430 3.98 0.46 -4.1 1 7 59 -179 -129 0.99920 2.62 0.16 -0.2 0 7 60 -43 -368 0.96673 2.13 0.61 -2.2 -1 10 61 31 111 1.02599 3.27 -0.69 -1.9 1 8 62 50 179 0.99790 2.65 -1.11 -2.3 0 9 STARS 1 1 2 1 3 1 4 3 5 1 6 2 7 NA 8 2 9 1 10 1 11 1 12 2 13 1 14 3 15 2 16 1 17 NA 18 1 19 1 20 NA 21 NA 22 NA 23 1 24 NA 25 NA 26 2 27 2 28 2 29 3 30 2 31 NA 32 NA 33 1 34 2 35 2 36 1 37 2 38 2 39 2 40 1 41 2 42 3 43 3 44 1 45 NA 46 2 47 2 48 NA 49 4 50 2 51 3 52 1 53 3 54 4 55 1 56 2 57 2 58 1 59 2 60 1 61 4 62 2 [ reached ‘max’ / getOption(“max.print”) – omitted 56 rows ]

Replace negative values with zero and apply necessary transformations.

wine_data <- wine_data %>% mutate(Alcohol = ifelse(Alcohol < 0, 0, Alcohol), # Replace negative values with 0 SquareRoot_Alcohol = sqrt(Alcohol), # Square root transformation to stabilize variance Log_ResidualSugar = log1p(ResidualSugar), # Log-transform to handle skewness in ResidualSugar Inverse_AcidIndex = 1 / AcidIndex, # Inverse transformation to handle high values in AcidIndex Alcohol_bucket = cut(Alcohol, breaks = c(-Inf, 8, 10, 12, 15, Inf), labels = 1:5), # Binning alcohol content pH_bucket = cut(pH, breaks = c(-Inf, 2.8, 3.0, 3.3, 3.6, Inf), labels = 1:5), # Binning pH levels SulfurRatio = FreeSulfurDioxide / TotalSulfurDioxide) # Create a ratio of sulfur dioxide levels

Justify the transformations:

Logarithmic and square root transformations reduce skewness and stabilize variance, which helps in making the predictors more normally distributed and suitable for modeling.

Handle missing values by imputing with the mean and creating flags for missingness.

wine_data <- wine_data %>% mutate(ResidualSugar_missing = ifelse(is.na(ResidualSugar), 1, 0), Chlorides_missing = ifelse(is.na(Chlorides), 1, 0), FreeSulfurDioxide_missing = ifelse(is.na(FreeSulfurDioxide), 1, 0), TotalSulfurDioxide_missing = ifelse(is.na(TotalSulfurDioxide), 1, 0), pH_missing = ifelse(is.na(pH), 1, 0), Sulphates_missing = ifelse(is.na(Sulphates), 1, 0), Alcohol_missing = ifelse(is.na(Alcohol), 1, 0), STARS_missing = ifelse(is.na(STARS), 1, 0)) %>% mutate(ResidualSugar = ifelse(is.na(ResidualSugar), mean(ResidualSugar, na.rm = TRUE), ResidualSugar), Chlorides = ifelse(is.na(Chlorides), mean(Chlorides, na.rm = TRUE), Chlorides), FreeSulfurDioxide = ifelse(is.na(FreeSulfurDioxide), mean(FreeSulfurDioxide, na.rm = TRUE), FreeSulfurDioxide), TotalSulfurDioxide = ifelse(is.na(TotalSulfurDioxide), mean(TotalSulfurDioxide, na.rm = TRUE), TotalSulfurDioxide), pH = ifelse(is.na(pH), mean(pH, na.rm = TRUE), pH), Sulphates = ifelse(is.na(Sulphates), mean(Sulphates, na.rm = TRUE), Sulphates), Alcohol = ifelse(is.na(Alcohol), mean(Alcohol, na.rm = TRUE), Alcohol), STARS = ifelse(is.na(STARS), mean(STARS, na.rm = TRUE), STARS))

Updated summary statistics should be provided here to show that missing values have been handled properly.

Model Building

3.1 Poisson Regression Models

Poisson Model 1

Before fitting the model, it’s important to ensure that no NA, NaN, or Inf values exist in the data.

summary(wine_data)

INDEX TARGET FixedAcidity VolatileAcidity CitricAcid
Min. : 1 Min. :0.000 Min. :-18.100 Min. :-2.7900 Min. :-3.2400
1st Qu.: 4038 1st Qu.:2.000 1st Qu.: 5.200 1st Qu.: 0.1300 1st Qu.: 0.0300
Median : 8110 Median :3.000 Median : 6.900 Median : 0.2800 Median : 0.3100
Mean : 8070 Mean :3.029 Mean : 7.076 Mean : 0.3241 Mean : 0.3084
3rd Qu.:12106 3rd Qu.:4.000 3rd Qu.: 9.500 3rd Qu.: 0.6400 3rd Qu.: 0.5800
Max. :16129 Max. :8.000 Max. : 34.400 Max. : 3.6800 Max. : 3.8600

ResidualSugar Chlorides FreeSulfurDioxide TotalSulfurDioxide Density
Min. :-127.800 Min. :-1.17100 Min. :-555.00 Min. :-823.0 Min. :0.8881
1st Qu.: 0.900 1st Qu.: 0.00000 1st Qu.: 5.00 1st Qu.: 34.0 1st Qu.:0.9877
Median : 4.900 Median : 0.04800 Median : 30.85 Median : 120.7 Median :0.9945
Mean : 5.419 Mean : 0.05482 Mean : 30.85 Mean : 120.7 Mean :0.9942
3rd Qu.: 14.900 3rd Qu.: 0.12800 3rd Qu.: 64.00 3rd Qu.: 198.0 3rd Qu.:1.0005
Max. : 141.150 Max. : 1.35100 Max. : 623.00 Max. :1057.0 Max. :1.0992

   pH          Sulphates          Alcohol       LabelAppeal          AcidIndex     

Min. :0.480 Min. :-3.1300 Min. : 0.00 Min. :-2.000000 Min. : 4.000
1st Qu.:2.970 1st Qu.: 0.3400 1st Qu.: 9.10 1st Qu.:-1.000000 1st Qu.: 7.000
Median :3.208 Median : 0.5271 Median :10.50 Median : 0.000000 Median : 8.000
Mean :3.208 Mean : 0.5271 Mean :10.51 Mean :-0.009066 Mean : 7.773
3rd Qu.:3.450 3rd Qu.: 0.7700 3rd Qu.:12.20 3rd Qu.: 1.000000 3rd Qu.: 8.000
Max. :6.130 Max. : 4.2400 Max. :26.50 Max. : 2.000000 Max. :17.000

 STARS       SquareRoot_Alcohol Log_ResidualSugar Inverse_AcidIndex Alcohol_bucket

Min. :1.000 Min. :0.000 Min. : -Inf Min. :0.05882 1 :2241
1st Qu.:2.000 1st Qu.:3.000 1st Qu.:1.224 1st Qu.:0.12500 2 :3244
Median :2.000 Median :3.225 Median :2.270 Median :0.12500 3 :3264
Mean :2.042 Mean :3.175 Mean : -Inf Mean :0.13189 4 :2080
3rd Qu.:2.042 3rd Qu.:3.521 3rd Qu.:3.411 3rd Qu.:0.14286 5 :1313
Max. :4.000 Max. :5.148 Max. :4.957 Max. :0.25000 NA’s: 653
NA’s :653 NA’s :3719
pH_bucket SulfurRatio ResidualSugar_missing Chlorides_missing 1 :2506 Min. : -Inf Min. :0.00000 Min. :0.00000
2 : 949 1st Qu.:-0.2411 1st Qu.:0.00000 1st Qu.:0.00000
3 :4332 Median : 0.1445 Median :0.00000 Median :0.00000
4 :2089 Mean : NaN Mean :0.04814 Mean :0.04986
5 :2524 3rd Qu.: 0.4317 3rd Qu.:0.00000 3rd Qu.:0.00000
NA’s: 395 Max. : Inf Max. :1.00000 Max. :1.00000
NA’s :1283
FreeSulfurDioxide_missing TotalSulfurDioxide_missing pH_missing Sulphates_missing Min. :0.00000 Min. :0.0000 Min. :0.00000 Min. :0.00000
1st Qu.:0.00000 1st Qu.:0.0000 1st Qu.:0.00000 1st Qu.:0.00000
Median :0.00000 Median :0.0000 Median :0.00000 Median :0.00000
Mean :0.05057 Mean :0.0533 Mean :0.03087 Mean :0.09457
3rd Qu.:0.00000 3rd Qu.:0.0000 3rd Qu.:0.00000 3rd Qu.:0.00000
Max. :1.00000 Max. :1.0000 Max. :1.00000 Max. :1.00000

Alcohol_missing STARS_missing
Min. :0.00000 Min. :0.0000
1st Qu.:0.00000 1st Qu.:0.0000
Median :0.00000 Median :0.0000
Mean :0.05104 Mean :0.2625
3rd Qu.:0.00000 3rd Qu.:1.0000
Max. :1.00000 Max. :1.0000

Check specifically for Inf or NaN values

inf_check <- sapply(wine_data, function(x) sum(is.infinite(x))) print(inf_check)

INDEX TARGET FixedAcidity 0 0 0 VolatileAcidity CitricAcid ResidualSugar 0 0 0 Chlorides FreeSulfurDioxide TotalSulfurDioxide 0 0 0 Density pH Sulphates 0 0 0 Alcohol LabelAppeal AcidIndex 0 0 0 STARS SquareRoot_Alcohol Log_ResidualSugar 0 0 4 Inverse_AcidIndex Alcohol_bucket pH_bucket 0 0 0 SulfurRatio ResidualSugar_missing Chlorides_missing 7 0 0 FreeSulfurDioxide_missing TotalSulfurDioxide_missing pH_missing 0 0 0 Sulphates_missing Alcohol_missing STARS_missing 0 0 0

nan_check <- sapply(wine_data, function(x) sum(is.nan(x))) print(nan_check)

INDEX TARGET FixedAcidity 0 0 0 VolatileAcidity CitricAcid ResidualSugar 0 0 0 Chlorides FreeSulfurDioxide TotalSulfurDioxide 0 0 0 Density pH Sulphates 0 0 0 Alcohol LabelAppeal AcidIndex 0 0 0 STARS SquareRoot_Alcohol Log_ResidualSugar 0 0 3103 Inverse_AcidIndex Alcohol_bucket pH_bucket 0 0 0 SulfurRatio ResidualSugar_missing Chlorides_missing 0 0 0 FreeSulfurDioxide_missing TotalSulfurDioxide_missing pH_missing 0 0 0 Sulphates_missing Alcohol_missing STARS_missing 0 0 0

Remove rows with any NA/NaN/Inf values to ensure a clean dataset for modeling.

wine_data_clean <- wine_data %>% filter_all(all_vars(!is.na(.))) %>% filter_all(all_vars(!is.infinite(.))) %>% filter_all(all_vars(!is.nan(.)))

Fit Poisson Model 1

model_poisson1 <- glm(TARGET ~ FixedAcidity + VolatileAcidity + CitricAcid + ResidualSugar + Chlorides + FreeSulfurDioxide + TotalSulfurDioxide + Density + pH + Sulphates + Alcohol + LabelAppeal + AcidIndex + STARS + SulfurRatio, family = poisson(link = “log”), data = wine_data_clean) summary(model_poisson1)

Call: glm(formula = TARGET ~ FixedAcidity + VolatileAcidity + CitricAcid + ResidualSugar + Chlorides + FreeSulfurDioxide + TotalSulfurDioxide + Density + pH + Sulphates + Alcohol + LabelAppeal + AcidIndex + STARS + SulfurRatio, family = poisson(link = “log”), data = wine_data_clean)

Coefficients: Estimate Std. Error z value Pr(>|z|)
(Intercept) 2.036e+00 2.560e-01 7.952 1.83e-15 FixedAcidity 8.844e-06 1.082e-03 0.008 0.993477
VolatileAcidity -5.138e-02 8.532e-03 -6.022 1.72e-09
CitricAcid 8.611e-03 7.712e-03 1.117 0.264184
ResidualSugar 1.612e-04 2.752e-04 0.586 0.557973
Chlorides -7.320e-02 2.159e-02 -3.391 0.000697 FreeSulfurDioxide 1.570e-04 4.511e-05 3.481 0.000500 TotalSulfurDioxide 9.824e-05 2.894e-05 3.395 0.000687 Density -4.622e-01 2.506e-01 -1.845 0.065096 .
pH -2.044e-02 9.779e-03 -2.090 0.036579

Sulphates -1.461e-02 7.485e-03 -1.952 0.050990 .
Alcohol 6.084e-03 1.827e-03 3.329 0.000871
LabelAppeal 1.976e-01 7.837e-03 25.219 < 2e-16 AcidIndex -1.223e-01 5.792e-03 -21.119 < 2e-16 STARS 2.129e-01 8.566e-03 24.859 < 2e-16 ** SulfurRatio 2.460e-04 7.999e-04 0.308 0.758442
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for poisson family taken to be 1)

Null deviance: 13396  on 7517  degrees of freedom

Residual deviance: 10830 on 7502 degrees of freedom AIC: 29631

Number of Fisher Scoring iterations: 5

# Interpretation of Poisson Model 1:The intercept represents the expected log count of the target variable (wine purchases) when all predictors are at their baseline (0 or average values). FixedAcidity has a very small and non-significant effect on the target variable, implying it’s not a major determinant of wine purchases. VolatileAcidity has a negative and significant coefficient, suggesting that higher levels of this variable reduce the expected number of wine purchases. Chlorides and pH both negatively impact the number of purchases, while FreeSulfurDioxide and TotalSulfurDioxide positively influence it. Alcohol content shows a positive and significant impact, meaning that wines with higher alcohol content are associated with a higher number of cases purchased. LabelAppeal and STARS are highly significant and positively associated with the number of purchases, indicating that consumer perceptions and ratings strongly influence sales. The SulfurRatio, however, does not significantly affect the outcome, which may suggest that this ratio is not a critical factor in purchasing decisions.

Poisson Model 2

Similar data checks as before to ensure that the predictors do not contain NA, NaN, or Inf values.

summary(wine_data)

INDEX TARGET FixedAcidity VolatileAcidity CitricAcid
Min. : 1 Min. :0.000 Min. :-18.100 Min. :-2.7900 Min. :-3.2400
1st Qu.: 4038 1st Qu.:2.000 1st Qu.: 5.200 1st Qu.: 0.1300 1st Qu.: 0.0300
Median : 8110 Median :3.000 Median : 6.900 Median : 0.2800 Median : 0.3100
Mean : 8070 Mean :3.029 Mean : 7.076 Mean : 0.3241 Mean : 0.3084
3rd Qu.:12106 3rd Qu.:4.000 3rd Qu.: 9.500 3rd Qu.: 0.6400 3rd Qu.: 0.5800
Max. :16129 Max. :8.000 Max. : 34.400 Max. : 3.6800 Max. : 3.8600

ResidualSugar Chlorides FreeSulfurDioxide TotalSulfurDioxide Density
Min. :-127.800 Min. :-1.17100 Min. :-555.00 Min. :-823.0 Min. :0.8881
1st Qu.: 0.900 1st Qu.: 0.00000 1st Qu.: 5.00 1st Qu.: 34.0 1st Qu.:0.9877
Median : 4.900 Median : 0.04800 Median : 30.85 Median : 120.7 Median :0.9945
Mean : 5.419 Mean : 0.05482 Mean : 30.85 Mean : 120.7 Mean :0.9942
3rd Qu.: 14.900 3rd Qu.: 0.12800 3rd Qu.: 64.00 3rd Qu.: 198.0 3rd Qu.:1.0005
Max. : 141.150 Max. : 1.35100 Max. : 623.00 Max. :1057.0 Max. :1.0992

   pH          Sulphates          Alcohol       LabelAppeal          AcidIndex     

Min. :0.480 Min. :-3.1300 Min. : 0.00 Min. :-2.000000 Min. : 4.000
1st Qu.:2.970 1st Qu.: 0.3400 1st Qu.: 9.10 1st Qu.:-1.000000 1st Qu.: 7.000
Median :3.208 Median : 0.5271 Median :10.50 Median : 0.000000 Median : 8.000
Mean :3.208 Mean : 0.5271 Mean :10.51 Mean :-0.009066 Mean : 7.773
3rd Qu.:3.450 3rd Qu.: 0.7700 3rd Qu.:12.20 3rd Qu.: 1.000000 3rd Qu.: 8.000
Max. :6.130 Max. : 4.2400 Max. :26.50 Max. : 2.000000 Max. :17.000

 STARS       SquareRoot_Alcohol Log_ResidualSugar Inverse_AcidIndex Alcohol_bucket

Min. :1.000 Min. :0.000 Min. : -Inf Min. :0.05882 1 :2241
1st Qu.:2.000 1st Qu.:3.000 1st Qu.:1.224 1st Qu.:0.12500 2 :3244
Median :2.000 Median :3.225 Median :2.270 Median :0.12500 3 :3264
Mean :2.042 Mean :3.175 Mean : -Inf Mean :0.13189 4 :2080
3rd Qu.:2.042 3rd Qu.:3.521 3rd Qu.:3.411 3rd Qu.:0.14286 5 :1313
Max. :4.000 Max. :5.148 Max. :4.957 Max. :0.25000 NA’s: 653
NA’s :653 NA’s :3719
pH_bucket SulfurRatio ResidualSugar_missing Chlorides_missing 1 :2506 Min. : -Inf Min. :0.00000 Min. :0.00000
2 : 949 1st Qu.:-0.2411 1st Qu.:0.00000 1st Qu.:0.00000
3 :4332 Median : 0.1445 Median :0.00000 Median :0.00000
4 :2089 Mean : NaN Mean :0.04814 Mean :0.04986
5 :2524 3rd Qu.: 0.4317 3rd Qu.:0.00000 3rd Qu.:0.00000
NA’s: 395 Max. : Inf Max. :1.00000 Max. :1.00000
NA’s :1283
FreeSulfurDioxide_missing TotalSulfurDioxide_missing pH_missing Sulphates_missing Min. :0.00000 Min. :0.0000 Min. :0.00000 Min. :0.00000
1st Qu.:0.00000 1st Qu.:0.0000 1st Qu.:0.00000 1st Qu.:0.00000
Median :0.00000 Median :0.0000 Median :0.00000 Median :0.00000
Mean :0.05057 Mean :0.0533 Mean :0.03087 Mean :0.09457
3rd Qu.:0.00000 3rd Qu.:0.0000 3rd Qu.:0.00000 3rd Qu.:0.00000
Max. :1.00000 Max. :1.0000 Max. :1.00000 Max. :1.00000

Alcohol_missing STARS_missing
Min. :0.00000 Min. :0.0000
1st Qu.:0.00000 1st Qu.:0.0000
Median :0.00000 Median :0.0000
Mean :0.05104 Mean :0.2625
3rd Qu.:0.00000 3rd Qu.:1.0000
Max. :1.00000 Max. :1.0000

inf_check <- sapply(wine_data, function(x) sum(is.infinite(x))) print(inf_check)

INDEX TARGET FixedAcidity 0 0 0 VolatileAcidity CitricAcid ResidualSugar 0 0 0 Chlorides FreeSulfurDioxide TotalSulfurDioxide 0 0 0 Density pH Sulphates 0 0 0 Alcohol LabelAppeal AcidIndex 0 0 0 STARS SquareRoot_Alcohol Log_ResidualSugar 0 0 4 Inverse_AcidIndex Alcohol_bucket pH_bucket 0 0 0 SulfurRatio ResidualSugar_missing Chlorides_missing 7 0 0 FreeSulfurDioxide_missing TotalSulfurDioxide_missing pH_missing 0 0 0 Sulphates_missing Alcohol_missing STARS_missing 0 0 0

nan_check <- sapply(wine_data, function(x) sum(is.nan(x))) print(nan_check)

INDEX TARGET FixedAcidity 0 0 0 VolatileAcidity CitricAcid ResidualSugar 0 0 0 Chlorides FreeSulfurDioxide TotalSulfurDioxide 0 0 0 Density pH Sulphates 0 0 0 Alcohol LabelAppeal AcidIndex 0 0 0 STARS SquareRoot_Alcohol Log_ResidualSugar 0 0 3103 Inverse_AcidIndex Alcohol_bucket pH_bucket 0 0 0 SulfurRatio ResidualSugar_missing Chlorides_missing 0 0 0 FreeSulfurDioxide_missing TotalSulfurDioxide_missing pH_missing 0 0 0 Sulphates_missing Alcohol_missing STARS_missing 0 0 0

wine_data_clean <- wine_data %>% filter_all(all_vars(!is.na(.))) %>% filter_all(all_vars(!is.infinite(.))) %>% filter_all(all_vars(!is.nan(.)))

Fit Poisson Model 2

model_poisson2 <- glm(TARGET ~ Log_ResidualSugar + SquareRoot_Alcohol + Inverse_AcidIndex + LabelAppeal + STARS + Alcohol_bucket + pH_bucket + SulfurRatio, family = poisson(link = “log”), data = wine_data_clean) summary(model_poisson2)

Call: glm(formula = TARGET ~ Log_ResidualSugar + SquareRoot_Alcohol + Inverse_AcidIndex + LabelAppeal + STARS + Alcohol_bucket + pH_bucket + SulfurRatio, family = poisson(link = “log”), data = wine_data_clean)

Coefficients: Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.3450635 0.0713375 -4.837 1.32e-06 Log_ResidualSugar 0.0165665 0.0056535 2.930 0.003386 SquareRoot_Alcohol 0.0044710 0.0223046 0.200 0.841129
Inverse_AcidIndex 6.7516718 0.3383954 19.952 < 2e-16
LabelAppeal 0.1961789 0.0078298 25.055 < 2e-16 STARS 0.2159868 0.0085874 25.152 < 2e-16 Alcohol_bucket2 -0.0213746 0.0284926 -0.750 0.453147
Alcohol_bucket3 0.0294120 0.0325836 0.903 0.366705
Alcohol_bucket4 0.0610276 0.0393964 1.549 0.121367
Alcohol_bucket5 0.0409623 0.0507706 0.807 0.419775
pH_bucket2 0.0453727 0.0281432 1.612 0.106917
pH_bucket3 0.0461659 0.0184874 2.497 0.012519 *
pH_bucket4 -0.0740284 0.0222845 -3.322 0.000894
* pH_bucket5 -0.0313298 0.0210316 -1.490 0.136315
SulfurRatio 0.0007363 0.0007673 0.960 0.337253
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for poisson family taken to be 1)

Null deviance: 13396  on 7517  degrees of freedom

Residual deviance: 10997 on 7503 degrees of freedom AIC: 29796

Number of Fisher Scoring iterations: 5

Interpretation of Poisson Model 2: The intercept here is negative, indicating that the baseline log count of purchases is lower when considering the transformed and bucketed variables.Log_ResidualSugar shows a small positive effect, suggesting that higher sugar content slightly increases the likelihood of purchase, though the effect is modest. Inverse_AcidIndex has a large and highly significant positive coefficient, meaning that wines with lower acid indexes (higher Inverse_AcidIndex) are more likely to be purchased. LabelAppeal and STARS remain strong positive predictors of purchases, consistent with Model 1. Alcohol buckets show mixed effects; none are statistically significant, indicating that once alcohol content is bucketed, its influence on purchases becomes less clear. The pH_bucket variable has some significant coefficients, particularly for the middle ranges, indicating a non-linear effect of pH on purchases. SulfurRatio, as in Model 1, does not show a significant effect, reaffirming its limited role in predicting wine purchases.

Compare both models: Poisson Model 1 has a slightly better pseudo R-squared value than Model 2, indicating that it explains more of the variance in the data. Model 1 includes the raw variables, which might provide more direct and interpretable insights into the effects of the predictors on wine purchases. Model 2, which includes transformed and bucketed variables, tries to capture non-linear effects but does not outperform Model 1. Therefore, Model 1 is selected for deployment due to its higher explanatory power and more straightforward interpretation of predictors like Alcohol, LabelAppeal, and STARS.

Justify the selection of the model: The choice of Model 1 over Model 2 is driven by the need for interpretability and the model’s performance metrics. While Model 2 attempts to capture non-linearities, it does not provide significantly better predictive power. The coefficients in Model 1 align well with domain knowledge, and the model’s simplicity makes it a better choice for practical deployment.