Semaglutide Consistently Reduces Alzheimer’s Risk

Alzheimer' Disease
GLP-1
Data Visualization
R Programming

This analysis compares the risk of Alzheimer’s disease across antidiabetic treatments in individuals with type 2 diabetes. The visualization presents hazard ratios and relative risk reductions for semaglutide versus other therapies, accompanied by a brief interpretive summary of the findings.

Author

Prince Agyapong

Published

July 4, 2025

Visualization

Semaglutide Risk Plot

Semaglutide seems to be linked to a lower risk of being diagnosed with Alzheimer’s disease compared to several other diabetes medications. This was seen in people with type 2 diabetes, a group already known to have a higher risk of Alzheimer’s. The benefit wasn’t just in comparison to insulin, which is often associated with cognitive decline, but also when semaglutide was compared to commonly used non-insulin drugs like metformin, SGLT2 inhibitors, and even other GLP-1 receptor agonists.

The difference was especially large when comparing semaglutide to insulin and sulfonylureas, with over 60% relative risk reduction in Alzheimer’s diagnosis. That might reflect the harmful effects of those drugs on the brain, especially insulin, which can cause low blood sugar episodes. But the fact that semaglutide also outperformed metformin, a drug sometimes thought to have cognitive benefits, makes the case even stronger.

What stands out is that semaglutide did better than older GLP-1RAs too. That suggests the effect isn’t just about the drug class, but something specific to semaglutide—possibly how it works in the brain, its stronger overall effects, or how long it stays active in the body.

Altogether, this real-world evidence points to semaglutide offering more than just blood sugar control. It may also help reduce the risk of Alzheimer and dementia in people with type 2 diabetes. It’s not proof of prevention, but it’s a strong signal that deserves more research in future clinical trials.

Steps to Make Plot

Load Packages

Show code
suppressPackageStartupMessages({
  if (!require("pacman")) install.packages("pacman")
  pacman::p_load(
    tidyverse,   
    ggtext,      # Improved text rendering support for 'ggplot2'
    showtext,    # Use custom fonts more easily in R graphics
    janitor,     # Simple tools for examining and cleaning dirty data
    scales,      # Scale functions for visualization
    glue,        # Interpreted string literals
    patchwork,   # Combine multiple plots into a single layout
    ggpubr,       # Publication-ready 'ggplot2' visualizations
    grid
  )
})

Read in the data

Show code
semag_data <- tribble(
  ~Comparison,              ~HR,  ~Lower_CI, ~Upper_CI,
  ~N_Sema, ~Cases_Sema, ~Risk_Sema, ~N_Comp, ~Cases_Comp, ~Risk_Comp,
  "Insulin",            0.33, 0.21, 0.51, 17087, 27, 0.16, 17087, 73, 0.43,
  "Metformin",          0.38, 0.24, 0.59, 17080, 27, 0.16, 17080, 68, 0.40,
  "DPP-4i",             0.40, 0.26, 0.63, 15878, 27, 0.17, 15878, 62, 0.39,
  "SGLT2i",             0.60, 0.37, 0.98, 15288, 26, 0.17, 15288, 40, 0.26,
  "Sulfonylureas (SU)", 0.31, 0.20, 0.48, 16503, 27, 0.16, 16503, 80, 0.49,
  "TZD",                0.43, 0.26, 0.70, 10847, 24, 0.22, 10847, 51, 0.47,
  "Other GLP-1RAs",     0.59, 0.37, 0.95, 17029, 27, 0.16, 17029, 44, 0.26
) |>
  mutate(
    RRR = (Risk_Comp - Risk_Sema) / Risk_Comp * 100,
    Comparison = fct_reorder(Comparison, HR)   # order by HR
  )

Build Forest plot

Show code
p <- ggplot(semag_data,
            aes(x = HR, y = Comparison)) +
   # CI bars
  geom_errorbarh(aes(xmin = Lower_CI, xmax = Upper_CI),
                 height = 0.25, linewidth = 1.2) +
  
  # Point estimate
  geom_point(size = 5, colour = "#085cbc") +
  
  # Vertical reference line at HR = 1
  geom_vline(xintercept = 1, linetype = "dashed", colour = "grey60",
             linewidth = 1.2) +
  geom_text(
    aes(label = paste0(round(RRR, 1), "%")),
    vjust = -0.9,
    size = 6,
    family = "sans",
    fontface = "bold",
    color = "#008755" 
  ) +
  scale_x_continuous(
    trans = "log10",
    breaks = c(0.1, 0.25, 0.5, 1, 2, 5),
    limits = c(0.1, 5.5)
  ) +
  scale_y_discrete(expand = expansion(add = c(1.2, 0.5))) +
coord_cartesian(clip = "off") +                             
  labs(
     title = "Semaglutide comparison with other antidiabetic drugs",
    subtitle = "Target-trial emulation, Wang et al, 2025",
     caption = "<span style='color:#008755;'>Percentages are relative risk reduction</span><br>Source: Wang 2025, Alzheimer’s & Dementia",
    x = "Hazard Ratio for Alzheimer’s Disease"
  ) + 
  theme_bw() +
  theme(
    axis.title.y = element_blank(),
    legend.title = element_text(size = 14, face = "bold"),
    legend.text = element_text(size = 14),
    axis.text.x = element_text(size = 16, face = "bold"),
    axis.text.y = element_text(size = 16, face = "bold"),
    axis.title = element_text(size = 16, face = "bold", hjust = 0.55),
    plot.title = element_text(size = 20, face = "bold"),
    plot.subtitle = element_text(size = 20, face = "bold"),
    plot.caption = ggtext::element_markdown(size = 16, face = "bold", hjust = 0.5))

y_annot <- 0.3   
p <- p +
  annotate(
    "segment",
    x = 1, xend = 0.45,
    y = y_annot, yend = y_annot,
    arrow = arrow(type = "closed", length = unit(0.15, "inches")),
    colour = "#008755", linewidth = 1.2 
  ) +
  annotate(
    "text",
    x = 0.7, y = y_annot - 0.15,    
    label = "Favors Semaglutide",
    hjust = 0.5, size = 6, fontface = "bold",
    colour = "#ff3c38"
  ) +
  annotate(
    "segment",
    x = 1, xend = 2.25,
    y = y_annot, yend = y_annot,
    arrow = arrow(type = "closed", length = unit(0.15, "inches")),
    colour = "gray30", linewidth = 1.2  
  ) +
  annotate(
    "text",
    x = 1.45, y = y_annot - 0.15,      
    label = "Favors Comparator",
    hjust = 0.5, size = 6, fontface = "bold",
    colour = "#ff3c38"
  ) +
  coord_cartesian(clip = "off")