Painting a portrait
How do COVID-19 admissions evolve over time?
‘Protect the NHS’ is the appeal from the UK government, ordering people to stay at home. Pressure on healthcare services is important to understand during a pandemic.

How do COVID-19 admissions and patient levels change over time?
Evolving over time
We can plot COVID-19 admissions and COVID-19 patients in hospitals in England. NHS England use the following definitions:
- COVID-19 admission: admissions with positive tests plus in-patient diagnoses. For hospital admissions, the person must have a positive SARS-CoV-2 test in the prior 14 days. NHS England counts in-patient diagnoses against the day before their diagnosis.
- COVID-19 patients (or hospital cases): the number of confirmed COVID-19 patients in hospital at 8am. This measure includes all hospitals.
Prof Johnson (Bristol) produces graphs showing admissions and patients over time.
Using R, we are going to produce a similar graph using ggplot2
.
Straight from the API
Public Health England provide an interface for their data-set. That means we can download an R package, rather than upload data via spreadsheets.
library(tidyverse)
library(lubridate)
library(scales)
library(ukcovid19)
Depending on your version, you may need to use remotes
to install the PHE package:
library(remotes)
remotes::install_github("publichealthengland/coronavirus-dashboard-api-R-sdk")
That allows to draw numbers straight from the interface.
First, we have to set the ‘structure’ of our data request:
covid19_structure <- list(
date = "date",
areaType = "areaType",
areaName = "areaName",
areaCode = "areaCode",
newAdmissions = "newAdmissions",
hospitalCases = "hospitalCases")
The two measures of interest are newAdmissions
and hospitalCases
.
Next, we draw data for the UK total, four nations, and English regions. For brevity, this is what the draw for the four nations looks like:
covid19_hospital_nations_df <- ukcovid19::get_data(
filters = c("areaType=nation"),
structure = covid19_structure)
We then bind those three draws together, transforming the date column and dropping missing rows.
covid19_hospital_df <- bind_rows(
covid19_hospital_uk_df,
covid19_hospital_nations_df,
covid19_hospital_regions_df) %>%
mutate(date = as_date(date)) %>%
drop_na()
Making the graphs
We can create a static graph for England.
We set the caption, and create the breaks for the colourful scale:
covid19_hospital_caption <- "Source: Public Health England COVID-19 Dashboard API."
covid19_scale_breaks <- c("2020-04-01", "2020-07-01", "2020-10-01", "2021-01-01")
covid19_scale_breaks <- covid19_scale_breaks %>% as_date()
This ‘phase portrait’ graph shows COVID-19 admissions and patients. The graph shows the third dimension — time — through colour.
This is the core of the graph:
covid19_hospital_eng_gg <- covid19_hospital_df %>%
filter(areaName == "England") %>%
ggplot(aes(x = newAdmissions,
y = hospitalCases)) +
geom_point(aes(color = date),
size = 3,
alpha = 0.2) +
Graphs need labels, which what the labs
function is for:
labs(title = "There were over 4,000 COVID-19 admissions in England on 12 January 2021.",
subtitle = "Plot of COVID-19 admissions versus COVID-19 patients in English hospitals over time.",
x = "COVID-19 admissions (new admissions plus in-patient diagnoses)",
y = "COVID-19 patients in hospital",
caption = covid19_hospital_caption) +
Scales then allow us to set limits. Since we are using a colour scale, we want the legend to be long. We can amend that through the guides
function:
scale_x_continuous(expand = c(0,0),
limits = c(0, 4500)) +
scale_y_continuous(expand = c(0,0),
limits = c(0, 35000)) +
scale_color_gradientn(name = "Date",
colors = rainbow(6),
breaks = covid19_scale_breaks,
labels = date_format("%b-%y")) +
guides(color = guide_colorbar(barwidth = unit(10, "cm")))
That code produces this graph:

We could also create an animated graph:

Since we are drawing data straight from the PHE interface, these graphs are easy to replicate.