1. Introduction

Type 2 diabetes is a major public health concern, and identifying the clinical factors most strongly associated with it is a routine but essential exercise in medical statistics. This report analyzes the Pima Indians Diabetes Dataset (768 female patients, 9 variables) to identify which clinical measurements are independently associated with a diabetes diagnosis.

Research question: Which clinical variables (glucose, BMI, age, blood pressure, insulin) are independently associated with diabetes status in this population?

2. Data Import and Overview

mydata <- read.csv("diabetes.csv")
str(mydata)
## 'data.frame':    768 obs. of  9 variables:
##  $ Pregnancies             : int  6 1 8 1 0 5 3 10 2 8 ...
##  $ Glucose                 : int  148 85 183 89 137 116 78 115 197 125 ...
##  $ BloodPressure           : int  72 66 64 66 40 74 50 0 70 96 ...
##  $ SkinThickness           : int  35 29 0 23 35 0 32 0 45 0 ...
##  $ Insulin                 : int  0 0 0 94 168 0 88 0 543 0 ...
##  $ BMI                     : num  33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
##  $ DiabetesPedigreeFunction: num  0.627 0.351 0.672 0.167 2.288 ...
##  $ Age                     : int  50 31 32 21 33 30 26 29 53 54 ...
##  $ Outcome                 : int  1 0 1 0 1 0 1 0 1 1 ...

The dataset contains 768 observations and 9 variables, all numeric. The outcome variable, Outcome, is binary (1 = diabetic, 0 = non-diabetic).

3. Data Cleaning

Several variables (Glucose, BloodPressure, SkinThickness, Insulin, BMI) contained biologically implausible zero values, which almost certainly represent missing data recorded as 0 rather than NA. These were recoded as missing prior to analysis.

mydata$Glucose[mydata$Glucose == 0] <- NA
mydata$BloodPressure[mydata$BloodPressure == 0] <- NA
mydata$SkinThickness[mydata$SkinThickness == 0] <- NA
mydata$Insulin[mydata$Insulin == 0] <- NA
mydata$BMI[mydata$BMI == 0] <- NA

summary(mydata)
##   Pregnancies        Glucose      BloodPressure    SkinThickness  
##  Min.   : 0.000   Min.   : 44.0   Min.   : 24.00   Min.   : 7.00  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 64.00   1st Qu.:22.00  
##  Median : 3.000   Median :117.0   Median : 72.00   Median :29.00  
##  Mean   : 3.845   Mean   :121.7   Mean   : 72.41   Mean   :29.15  
##  3rd Qu.: 6.000   3rd Qu.:141.0   3rd Qu.: 80.00   3rd Qu.:36.00  
##  Max.   :17.000   Max.   :199.0   Max.   :122.00   Max.   :99.00  
##                   NAs    :5       NAs    :35       NAs    :227    
##     Insulin            BMI        DiabetesPedigreeFunction      Age       
##  Min.   : 14.00   Min.   :18.20   Min.   :0.0780           Min.   :21.00  
##  1st Qu.: 76.25   1st Qu.:27.50   1st Qu.:0.2437           1st Qu.:24.00  
##  Median :125.00   Median :32.30   Median :0.3725           Median :29.00  
##  Mean   :155.55   Mean   :32.46   Mean   :0.4719           Mean   :33.24  
##  3rd Qu.:190.00   3rd Qu.:36.60   3rd Qu.:0.6262           3rd Qu.:41.00  
##  Max.   :846.00   Max.   :67.10   Max.   :2.4200           Max.   :81.00  
##  NAs    :374      NAs    :11                                              
##     Outcome     
##  Min.   :0.000  
##  1st Qu.:0.000  
##  Median :0.000  
##  Mean   :0.349  
##  3rd Qu.:1.000  
##  Max.   :1.000  
## 

Note that Insulin retained a very high proportion of missing values (374 of 768, ~49%) even after cleaning, which informed a modeling decision made later in this report.

4. Normality Assessment

Before selecting statistical tests, the Shapiro-Wilk test was used to assess normality for all numeric variables.

numeric_cols <- c("Pregnancies", "Glucose", "BloodPressure", "SkinThickness",
                   "Insulin", "BMI", "DiabetesPedigreeFunction", "Age")

for (col in numeric_cols) {
  result <- shapiro.test(mydata[[col]])
  cat(col, ": p-value =", format(result$p.value, scientific = TRUE), "\n")
}
## Pregnancies : p-value = 1.609257e-21 
## Glucose : p-value = 1.720326e-11 
## BloodPressure : p-value = 9.45138e-05 
## SkinThickness : p-value = 1.775691e-09 
## Insulin : p-value = 1.698218e-21 
## BMI : p-value = 8.557785e-09 
## DiabetesPedigreeFunction : p-value = 2.477506e-27 
## Age : p-value = 2.402274e-24

All variables significantly deviated from a normal distribution (p < 0.05 in every case). Consequently, non-parametric tests (Mann-Whitney U) and median (rather than mean) summaries were used throughout this analysis.

5. Univariate Comparisons: Diabetic vs. Non-Diabetic

Each candidate predictor was first compared between diabetic and non-diabetic patients using the Mann-Whitney U test.

wilcox.test(Glucose ~ Outcome, data = mydata)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  Glucose by Outcome
## W = 27394, p-value < 2.2e-16
## alternative hypothesis: true location shift is not equal to 0
tapply(mydata$Glucose, mydata$Outcome, median, na.rm = TRUE)
##   0   1 
## 107 140
wilcox.test(BMI ~ Outcome, data = mydata)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  BMI by Outcome
## W = 40875, p-value < 2.2e-16
## alternative hypothesis: true location shift is not equal to 0
tapply(mydata$BMI, mydata$Outcome, median, na.rm = TRUE)
##    0    1 
## 30.1 34.3
wilcox.test(Age ~ Outcome, data = mydata)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  Age by Outcome
## W = 41950, p-value < 2.2e-16
## alternative hypothesis: true location shift is not equal to 0
tapply(mydata$Age, mydata$Outcome, median, na.rm = TRUE)
##  0  1 
## 27 36
wilcox.test(BloodPressure ~ Outcome, data = mydata)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  BloodPressure by Outcome
## W = 47567, p-value = 1.629e-06
## alternative hypothesis: true location shift is not equal to 0
tapply(mydata$BloodPressure, mydata$Outcome, median, na.rm = TRUE)
##    0    1 
## 70.0 74.5
wilcox.test(Insulin ~ Outcome, data = mydata)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  Insulin by Outcome
## W = 9210.5, p-value = 7.477e-14
## alternative hypothesis: true location shift is not equal to 0
tapply(mydata$Insulin, mydata$Outcome, median, na.rm = TRUE)
##     0     1 
## 102.5 169.5

Summary of univariate results

Variable Median (Non-diabetic) Median (Diabetic) p-value
Glucose 107 140 < 0.001
BMI 30.1 34.3 < 0.001
Age 27 36 < 0.001
Blood Pressure 70.0 74.5 < 0.001
Insulin 102.5 169.5 < 0.001

All five variables were significantly higher in the diabetic group at the univariate level.

6. Multivariable Logistic Regression

To identify which variables remained independently associated with diabetes after adjusting for one another, a multivariable logistic regression model was built.

6.1 Initial model (all five predictors)

model <- glm(Outcome ~ Glucose + BMI + Age + BloodPressure + Insulin,
             data = mydata, family = binomial)
summary(model)
## 
## Call:
## glm(formula = Outcome ~ Glucose + BMI + Age + BloodPressure + 
##     Insulin, family = binomial, data = mydata)
## 
## Coefficients:
##                 Estimate Std. Error z value Pr(>|z|)    
## (Intercept)   -9.7208551  1.1674617  -8.326  < 2e-16 ***
## Glucose        0.0379725  0.0057177   6.641 3.11e-11 ***
## BMI            0.0812731  0.0212529   3.824 0.000131 ***
## Age            0.0550397  0.0138266   3.981 6.87e-05 ***
## BloodPressure -0.0027008  0.0114185  -0.237 0.813025    
## Insulin       -0.0007491  0.0012984  -0.577 0.563979    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 498.10  on 391  degrees of freedom
## Residual deviance: 353.99  on 386  degrees of freedom
##   (376 observations deleted due to missingness)
## AIC: 365.99
## 
## Number of Fisher Scoring iterations: 5

This model retained only 392 of 768 observations, because Insulin alone carried 374 missing values, and glm() excludes any row with a missing value in any included predictor (listwise deletion). In this model, Insulin and BloodPressure were not statistically significant.

6.2 Refined model (removing Insulin)

Since Insulin was not significant and was responsible for the majority of missing data, it was removed to preserve sample size.

model2 <- glm(Outcome ~ Glucose + BMI + Age + BloodPressure,
              data = mydata, family = binomial)
summary(model2)
## 
## Call:
## glm(formula = Outcome ~ Glucose + BMI + Age + BloodPressure, 
##     family = binomial, data = mydata)
## 
## Coefficients:
##                Estimate Std. Error z value Pr(>|z|)    
## (Intercept)   -8.673701   0.795070 -10.909  < 2e-16 ***
## Glucose        0.034909   0.003523   9.910  < 2e-16 ***
## BMI            0.092529   0.015315   6.042 1.52e-09 ***
## Age            0.034352   0.008418   4.081 4.49e-05 ***
## BloodPressure -0.008317   0.008422  -0.988    0.323    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 931.94  on 723  degrees of freedom
## Residual deviance: 695.17  on 719  degrees of freedom
##   (44 observations deleted due to missingness)
## AIC: 705.17
## 
## Number of Fisher Scoring iterations: 4

Removing Insulin restored the usable sample to 724 observations. BloodPressure remained non-significant (p = 0.323) even without Insulin in the model, indicating its univariate association was likely confounded by glucose, BMI, and age rather than reflecting an independent effect.

6.3 Final model

BloodPressure was subsequently removed, yielding a final, parsimonious three-predictor model.

model_final <- glm(Outcome ~ Glucose + BMI + Age,
                    data = mydata, family = binomial)
summary(model_final)
## 
## Call:
## glm(formula = Outcome ~ Glucose + BMI + Age, family = binomial, 
##     data = mydata)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -9.032377   0.711037 -12.703  < 2e-16 ***
## Glucose      0.035548   0.003481  10.212  < 2e-16 ***
## BMI          0.089753   0.014377   6.243  4.3e-10 ***
## Age          0.028699   0.007809   3.675 0.000238 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 974.75  on 751  degrees of freedom
## Residual deviance: 724.96  on 748  degrees of freedom
##   (16 observations deleted due to missingness)
## AIC: 732.96
## 
## Number of Fisher Scoring iterations: 4
exp(coef(model_final))
##  (Intercept)      Glucose          BMI          Age 
## 0.0001194781 1.0361873320 1.0939041273 1.0291149212
exp(confint(model_final))
##                    2.5 %       97.5 %
## (Intercept) 2.820409e-05 0.0004596464
## Glucose     1.029326e+00 1.0434890533
## BMI         1.064055e+00 1.1258354595
## Age         1.013524e+00 1.0450856242

This final model used 752 of 768 observations (98%).

Final model — Odds Ratios

Variable OR 95% CI p-value
Glucose 1.036 1.029 – 1.043 < 0.001
BMI 1.094 1.064 – 1.126 < 0.001
Age 1.029 1.014 – 1.045 < 0.001

7. Visualization of Final Model

or_data <- data.frame(
  Variable = c("Glucose", "BMI", "Age"),
  OR = c(1.036, 1.094, 1.029),
  Lower = c(1.029, 1.064, 1.014),
  Upper = c(1.043, 1.126, 1.045)
)

ggplot(or_data, aes(x = OR, y = Variable)) +
  geom_point(size = 3, color = "steelblue") +
  geom_errorbar(aes(xmin = Lower, xmax = Upper), width = 0.2, color = "steelblue") +
  geom_vline(xintercept = 1, linetype = "dashed", color = "red") +
  labs(title = "Odds Ratios for Diabetes Risk Factors",
       x = "Odds Ratio (95% CI)", y = "") +
  theme_minimal()

8. Conclusion

In this analysis of 768 female patients from the Pima Indians Diabetes Dataset, glucose, BMI, and age were each independently and significantly associated with increased odds of diabetes, even after adjusting for one another. Blood pressure and insulin, despite showing significant univariate associations, did not remain independent predictors once glucose, BMI, and age were accounted for — illustrating the difference between a crude and an adjusted association.

In the final multivariable logistic regression model (n = 752), glucose (OR = 1.04, 95% CI: 1.03–1.04), BMI (OR = 1.09, 95% CI: 1.06–1.13), and age (OR = 1.03, 95% CI: 1.01–1.05) were all independently and significantly associated with increased odds of diabetes (all p < 0.001).

Limitations

  • Insulin was excluded from the final model due to a high proportion (49%) of missing values, rather than true absence of effect.
  • This is a cross-sectional dataset; causal direction cannot be inferred.
  • The population is limited to female patients of Pima Indian heritage, which may limit generalizability to other populations.

Analysis conducted in R (base R + ggplot2). Dataset: Pima Indians Diabetes Database, publicly available via Kaggle.