Skip to main content

R β€” NHS Quickstart

πŸ§ͺ Statistics Β· Epidemiology Β· Shiny dashboards Β· SQL Server
Why R in the NHS

R has a deep statistics ecosystem (survival, time series, epidemiology) and first-class reporting (R Markdown/Quarto) with Shiny for interactive apps. The NHS-R community provides patterns, training, and reusable code.

Great for: Clinician-Researchers Β· BI Analysts (stats/QA) Β· Data Scientists.


βš™οΈ 10-minute install​

  1. Install R (4.3+) from CRAN and RStudio Desktop.
  2. Open RStudio β†’ Console:
install.packages(c("tidyverse","DBI","odbc","shiny","ggplot2","janitor","readxl"))

For SQL Server access, install Microsoft ODBC Driver 18 for SQL Server on Windows.


πŸš€ β€œHello NHS” analysis​

Create a new R script hello_nhs.R:

hello_nhs.R
library(tidyverse)

df <- tibble::tibble(
date = as.Date("2025-01-01") + 0:4,
attendances = c(120, 135, 128, 142, 131)
)

cat("Admissions summary\n")
print(summary(df$attendances))

ggplot(df, aes(date, attendances)) +
geom_line() +
geom_point() +
labs(title = "Daily Attendances", x = "Date", y = "Count")

Run in RStudio (Ctrl/Cmd+Enter) β€” a plot window appears.


πŸ”— Query SQL Server (DBI + odbc)​

Store connection settings in .Renviron (project root or home):

.Renviron
SQLSERVER_SERVER=YOURSERVER
SQLSERVER_DATABASE=NHS_Analytics

Then in R:

query_sqlserver.R
library(DBI)
library(odbc)
library(dplyr)

con <- dbConnect(odbc::odbc(),
Driver = "ODBC Driver 18 for SQL Server",
Server = Sys.getenv("SQLSERVER_SERVER"),
Database = Sys.getenv("SQLSERVER_DATABASE"),
Trusted_Connection = "Yes",
Encrypt = "Yes",
TrustServerCertificate = "Yes" # set per Trust policy
)

df <- dbGetQuery(con, "
SELECT TOP (100)
practice_id,
total_appointments,
attendance_rate
FROM dbo.vw_PracticeKPI
ORDER BY total_appointments DESC
")

print(head(df))
dbDisconnect(con)

πŸ“Š Minimal Shiny dashboard (15 min)​

Create app.R:

app.R
library(shiny)
library(dplyr)
library(ggplot2)

df <- tibble::tibble(
practice_id = rep(c("A","B","C"), each = 3),
month = rep(c("2025-05","2025-06","2025-07"), times = 3),
appointments = c(120,135,128, 100,110,115, 95,102,108)
)

ui <- fluidPage(
tags$h2("NHS KPI (Demo)"),
selectInput("m", "Month", choices = unique(df$month)),
plotOutput("chart")
)

server <- function(input, output, session){
output$chart <- renderPlot({
d <- filter(df, month == input$m)
ggplot(d, aes(practice_id, appointments)) +
geom_col(fill = "#005EB8") +
labs(title = paste("Appointments by Practice β€”", input$m),
x = "Practice", y = "Appointments")
})
}

shinyApp(ui, server)

Run:

shiny::runApp()

🧰 NHS-ready packages​

PackageUse case
tidyversedata wrangling (dplyr/tidyr/readr)
ggplot2charts and statistical graphics
DBI + odbcconnect to SQL Server
janitorclean names, quick QA checks
shinyinteractive dashboards for clinicians
rmarkdown / quartoreproducible reports
arrowfast Parquet/Feather IO

🧱 Reproducible reports (R Markdown / Quarto)​

Create report.Rmd:

---
title: "Weekly KPI"
output: html_document
---

```{r}
library(tidyverse)
df <- tibble::tibble(
month = c("2025-05","2025-06","2025-07"),
appointments = c(355, 380, 351)
)
knitr::kable(df)
```

```{r, fig.height=3}
library(ggplot2)
ggplot(df, aes(month, appointments, group=1)) +
geom_line() + geom_point() +
labs(title="Monthly Appointments")
```

Render with Knit in RStudio.


πŸ”’ IG & safety checklist​

  • Use synthetic/de-identified data in examples.
  • Keep secrets out of code; prefer .Renviron locally and a secret store in prod.
  • Avoid free-text PHI in logs/plots; aggregate and apply suppression rules.
  • Document dataset sources, owners, and refresh cadence in the repo README.
  • For Shiny in production, put behind SSO (Entra ID/NHS Login) and add usage logging.

πŸ“ Measuring impact​

  • Velocity: time from data pull β†’ plot/report.
  • Reliability: refresh success rate for scheduled scripts/apps.
  • Quality: peer review via PRs; validation checks.
  • Adoption: weekly active users for Shiny; report opens.

πŸ”— See also​

See also: Shiny Β· SQL Server Β· Python Β· VS Code Β· GitHub Β· Secrets & .env

What’s next?

You’ve completed the Learn β€” R stage. Keep momentum: