Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 46

Binary Logistic Regression: From Fit to Evaluation

Recommended resources

Hello! Welcome to our practical session on binary logistic regression.

In our last few lessons, we've built a solid theoretical foundation. We learned how to formulate a logistic regression model, interpret its coefficients as log-odds and odds ratios, and evaluate its performance using tools like the confusion matrix, sensitivity, specificity, and most recently, ROC curves and AUC.

Today, we will put all of that theory into practice. Our goal is to walk through a complete data analysis workflow: taking a real dataset, preparing it, fitting a logistic regression model in R, interpreting the output, and rigorously evaluating its performance. This hands-on experience will solidify your understanding and show you how these concepts are applied in a real-world data science context.

1. The Workflow: From Raw Data to Model Evaluation

A typical modeling project follows several key steps. We'll go through each one using a classic dataset on heart disease.

First, let's watch how to get and prepare the data. This involves loading the data, inspecting it, cleaning up missing or miscoded values, and ensuring variables have the correct data type (e.g., numeric, factor). These steps are crucial for any successful analysis.

Logistic Regression in R, Clearly Explained!!!!

This first part of the StatQuest video 'Logistic Regression in R, Clearly Explained!!!!' provides an excellent walkthrough of the data preparation process.

Please watch the video from the beginning to 06:41. Focus on the practical R code used to: Load data from a URL. Inspect the data structure with head() and str(). Identify and clean problematic values (e.g., changing '?' to NA). Convert variables to the correct factor type. Handle rows with missing data (NA values). Perform basic checks using xtabs() to ensure data integrity.

As you saw, data preparation is a detailed process that requires careful attention. For our lesson, the key steps were:

  • The dependent variable HD (heart disease) was converted into a factor with two levels: "Healthy" and "Unhealthy".
  • Predictor variables like Sex, CP (Chest Pain), etc., were converted into factors with meaningful labels.
  • Rows containing missing values (NAs) were removed from the dataset.

Now that our data is clean, we can move on to the modeling itself.


2. Fitting the Model in R

We'll use the glm() function in R, which stands for Generalized Linear Models. By specifying family = binomial, we tell glm() to perform a logistic regression.

Let's start by fitting a model that uses all available predictors to predict the probability of heart disease. The video continues right where we left off, showing how to fit both a simple (one-predictor) and a more complex (multi-predictor) model.

Logistic Regression in R, Clearly Explained!!!!

The next segment of the StatQuest video demonstrates how to fit the logistic regression model and, most importantly, how to interpret the coefficients.

Please watch from 06:41 to 10:35, and then from 12:47 to 14:26. The first part (06:41-10:35) covers fitting a simple model with one predictor and explains how to interpret the intercept and coefficient as log-odds. The second part (12:47-14:26) fits a full model with all predictors and introduces McFadden's Pseudo R-squared.


3. Interpreting the Model Output

As the video explained, the output of summary(model) contains a wealth of information. Let's focus on interpreting the coefficients from a multivariable model.

Here's a typical R code sequence to fit the model and get the summary:




# Assuming 'heart_data_clean' is the prepared dataframe
# The formula 'HD ~ .' means "predict HD using all other variables"
logistic_model <- glm(HD ~ ., data = heart_data_clean, family = binomial)

summary(logistic_model)

The most important part of the output is the Coefficients table. Remember these key points for interpretation:

  • Estimate (Log-Odds): The values in the Estimate column are the regression coefficients (). For a continuous predictor like Age, a positive coefficient means the log-odds of having heart disease increase with age. For a categorical predictor like Sex (with 'Female' as the reference), a positive coefficient for SexMale means the log-odds are higher for males compared to females.
  • Pr(>|z|) (p-value): This tells you if the coefficient is statistically significant. A low p-value (typically < 0.05) suggests that the predictor has a genuine association with the outcome.
  • Odds Ratios (OR): To make the coefficients more intuitive, we exponentiate them: exp(coef(logistic_model)).
    • An OR > 1 indicates a risk factor. For every one-unit increase in the predictor, the odds of the outcome increase.
    • An OR < 1 indicates a protective factor. The odds of the outcome decrease.
    • An OR = 1 indicates no association.

For example, if the coefficient for Age is 0.05, the OR is . This means that for each additional year of age, the odds of having heart disease increase by about 5%, holding all other variables constant.


4. Evaluating Model Performance

Fitting a model and interpreting its coefficients is only half the story. We need to evaluate how well it actually works. We'll use the methods we've learned in previous lessons.

A. Goodness of Fit

The summary() output provides the Null Deviance and Residual Deviance.

  • Null Deviance: Measures how well the outcome is predicted by a model with only an intercept (no predictors).
  • Residual Deviance: Measures how well the outcome is predicted by your full model.

A large drop from null to residual deviance indicates that your predictors are adding significant value. These values can be used to calculate a pseudo R-squared value (like McFadden's ), which gives a rough idea of the proportion of variance explained by the model.

B. Predictive Accuracy (Threshold-Dependent)

To assess accuracy, we first get predicted probabilities from our model and then apply a classification threshold (commonly 0.5).

Binary logistic regression in R

The article 'Binary logistic regression in R' provides clear R code for evaluating a model's predictive accuracy. We'll use this as a practical guide.

Please read the subsection 'Validity of the predictions' within the 'Quality of a model' section. Focus on the R code used to generate predicted probabilities, create a confusion matrix with a 0.5 threshold, and calculate accuracy, sensitivity, and specificity.

Let's walk through the code described in the article.

  1. Generate Predictions:

    
    
    
    # Get predicted probabilities
    predicted_probs <- predict(logistic_model, type = "response")
    
  2. Apply Threshold and Create Confusion Matrix:

    
    
    
    # Classify as 'Unhealthy' if probability > 0.5
    predicted_class <- ifelse(predicted_probs > 0.5, "Unhealthy", "Healthy")
    
    
    
    # Convert to factor with same levels as original data
    predicted_class <- factor(predicted_class, levels = levels(heart_data_clean$HD))
    
    
    
    
    # Create the confusion matrix
    conf_matrix <- table(Observed = heart_data_clean$HD, Predicted = predicted_class)
    print(conf_matrix)
    
  3. Calculate Metrics: From this conf_matrix, you can calculate:

    • Accuracy:
    • Sensitivity (TPR):
    • Specificity (TNR):

These metrics give you a snapshot of performance at a single cutoff, which is useful but incomplete.

C. Overall Discriminative Power (Threshold-Independent)

As we learned in the last lesson, the ROC curve and AUC give us a complete picture of model performance across all thresholds. We can use the {pROC} package in R to do this easily.

The 'Binary logistic regression in R' article also demonstrates this. Here is the code from the subsection "AUC and ROC curve" to generate the plot and calculate the value.




# Install and load the pROC package if you haven't already
# install.packages("pROC")
library(pROC)




# Create the ROC object
roc_obj <- roc(heart_data_clean$HD, predicted_probs)




# Plot the ROC curve
plot(roc_obj, main = "ROC Curve", print.auc = TRUE)




# Get the AUC value
auc_value <- auc(roc_obj)
print(paste("AUC:", round(auc_value, 3)))

The resulting AUC gives you a single, robust number to quantify your model's ability to distinguish between healthy and unhealthy patients. An AUC of 0.85, for example, would mean your model has an 85% chance of ranking a randomly chosen unhealthy patient as more likely to have heart disease than a randomly chosen healthy patient. This is a strong indicator of a good model.


5. Reporting Your Findings

Once your analysis is complete, you need to present the results clearly. Manually creating tables of coefficients and odds ratios can be tedious. Packages like {gtsummary} can automate this beautifully.

Binary logistic regression in R

The final section of the 'Binary logistic regression in R' article shows how to create professional-looking summary tables for your model.

Please read the subsection '{gtsummary} package' under 'Reporting results'. The tbl_regression() function is a powerful tool for this.

Using a single line of code, you can generate a publication-ready table that includes odds ratios, 95% confidence intervals, and p-values, all correctly formatted for categorical and continuous variables.




# install.packages("gtsummary")
library(gtsummary)




# Create and print the summary table
tbl_regression(logistic_model, exponentiate = TRUE)

This simple command transforms a standard R model output into a professional table, saving you significant time and effort.


Conclusion

In this lesson, we bridged the gap between theory and practice, working through a complete binary logistic regression analysis.

Key Takeaways:

  • Workflow: A successful analysis involves a clear workflow: Data Preparation -> Model Fitting -> Interpretation -> Evaluation.
  • Fitting in R: The glm() function with family = binomial is the standard tool for fitting logistic regression models.
  • Interpretation: Focus on odds ratios (exp(coefficient)) and their confidence intervals to understand the magnitude and significance of each predictor's effect.
  • Evaluation: A comprehensive evaluation uses multiple metrics.
    • Goodness-of-fit stats like deviance give a high-level view.
    • Accuracy, sensitivity, and specificity provide performance details at a specific threshold.
    • AUC offers the most robust, threshold-independent measure of a model's discriminative power.
  • Reporting: Tools like {gtsummary} can streamline the creation of professional summary tables.

Preview of the Next Lesson:

We've mastered the case where the outcome has two categories. But what if the outcome is nominal with more than two categories, like choosing between three different brands of a product? In our next lesson, we will explore multinomial logistic regression, which extends the principles we've learned to handle these multi-category dependent variables.