1 Activity volume

1.1 All activity

# Time series by speciality 
national_data %>% 
  group_by(der_activity_month, speciality) %>% 
  summarise(n_spells_IP = sum(n_spells_IP, na.rm = TRUE),
            n_spells_OP = sum(n_spells_OP, na.rm = TRUE)) %>%
  group_by(der_activity_month, speciality) %>% 
  mutate(all_activity = sum(n_spells_IP, n_spells_OP)) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>%
  
  ggplot(aes(x = der_activity_month, y = all_activity)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "loess", span = 0.2, colour = "#5881c1") +
  facet_grid(~speciality, scales = "free") +
  scale_color_SU() +
  scale_y_continuous(labels = comma, oob = squish) +
  theme(strip.background = element_rect(fill = NA, colour = "grey"),
        strip.text = element_text(face = "bold")
        ) +
  labs(x = "", y = "Admissions",
       title = "Trends in activity by speciality",
       subtitle = "Monthly elective inpatient and outpatient activity | National | 2017-22")

create_dt(
  national_data %>% 
  group_by(der_activity_month, speciality) %>% 
  summarise(n_spells_IP = sum(n_spells_IP, na.rm = TRUE),
            n_spells_OP = sum(n_spells_OP, na.rm = TRUE)) %>%
  group_by(der_activity_month, speciality) %>% 
  mutate(all_activity = sum(n_spells_IP, n_spells_OP)) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01")
)

In considering the trends in all activity we include both elective inpatient and outpatient contacts and both NHS and independent sector activity. We note the comparative volumes of activity by speciality and we note the different levels of post-pandemic recovery; ophthalmic activity has returned to pre-pandemic levels where orthopaedic activity has not.

In recent months, monthly orthopaedic activity counts have remained consistent while ophthalmic activity appears to be increased since the start of 2022.

1.2 By sector

# Time series by speciality and sector
national_data %>% 
  group_by(der_activity_month, type, speciality) %>% 
  summarise(n_spells_IP = sum(n_spells_IP, na.rm = TRUE),
            n_spells_OP = sum(n_spells_OP, na.rm = TRUE)) %>%
  group_by(der_activity_month, type, speciality) %>% 
  mutate(all_activity = sum(n_spells_IP, n_spells_OP)) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>%
  
  ggplot(aes(x = der_activity_month, y = all_activity)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "loess", span = 0.2, colour = "#5881c1") +
  facet_grid(type~speciality, scales = "free") +
  scale_color_SU() +
  scale_y_continuous(labels = comma, oob = squish) +
  theme(strip.background = element_rect(fill = NA, colour = "grey"),
        strip.text = element_text(face = "bold")
        ) +
  labs(x = "", y = "Activity",
       title = "Trends in activity by speciality and sector",
       subtitle = "Monthly elective inpatient and outpatient activity | National | 2018-22",
       caption = "Note: Independent sector activity consists of only NHS-funded care in the independent secetor")

create_dt(
national_data %>% 
  group_by(der_activity_month, type, speciality) %>% 
  summarise(n_spells_IP = sum(n_spells_IP, na.rm = TRUE),
            n_spells_OP = sum(n_spells_OP, na.rm = TRUE)) %>%
  group_by(der_activity_month, type, speciality) %>% 
  mutate(all_activity = sum(n_spells_IP, n_spells_OP)) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01")
)

National trends in ophthalmic and orthopaedic activity show vastly different post-pandemic recoveries. Orthopaedic activity in both NHS and independent sector settings have had consistent monthly volumes from early 2018 until the onset of the pandemic and have regained that consistency post-pandemic, albeit at slightly lower monthly rates; i.e. pre-pandemic levels have not yet been achieved.

Post-pandemic ophthalmic activity is most notably changed in the independent sector, where activity has continued to grow, at a faster rate that in was before the pandemic. The rate of ophthalmic activity in NHS settings has plateaued since early 2021 at near pre-pandemic levels.

1.3 Inc. costs

1.3.1 Orthopadeic

# Orthopaedic
national_data %>% 
  group_by(der_activity_month, type, speciality) %>% 
  sum_spells_function(.) %>%  
  pivot_longer(cols = c(-der_activity_month, -type, -speciality)) %>% 
  mutate(name = case_when(str_detect(name, "IP") ~ "Inpatient admissions", 
                          str_detect(name, "OP") ~ "Outpatient appointments",
                          TRUE ~ "Cost (£)")) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>% 
  filter(speciality == "Orthopaedic") %>% 
  
  ggplot(aes(x = der_activity_month, y = value, colour = name, group = name)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "loess", span = 0.2) +
  facet_grid(str_wrap(name,15) ~ type, scales = "free") +
  scale_color_SU() +
  scale_y_continuous(labels = comma, oob = squish) +
  theme(strip.background = element_rect(fill = NA, colour = "grey"),
        strip.text = element_text(face = "bold"),
        legend.position = "none"
        ) +
  labs(x = "", y = "", colour = "Activity",
       title = "Trends in activity and cost by speciality and sector: Orthopaedic",
       subtitle = "Monthly elective activity | National | 2018-22")

create_dt(
  national_data %>% 
  group_by(der_activity_month, type, speciality) %>% 
  sum_spells_function(.) %>%  
  pivot_longer(cols = c(-der_activity_month, -type, -speciality)) %>% 
  mutate(name = case_when(str_detect(name, "IP") ~ "Inpatient admissions", 
                          str_detect(name, "OP") ~ "Outpatient appointments",
                          TRUE ~ "Cost (£)")) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>% 
  filter(speciality == "Orthopaedic")
)

1.3.2 Ophthalmology

# Ophthalmology
national_data %>% 
  group_by(der_activity_month, type, speciality) %>% 
  sum_spells_function(.) %>% 
  pivot_longer(cols = c(-der_activity_month, -type, -speciality)) %>% 
  mutate(name = case_when(str_detect(name, "IP") ~ "Inpatient admissions", 
                          str_detect(name, "OP") ~ "Outpatient appointments",
                          TRUE ~ "Cost (£)")) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>% 
  filter(speciality == "Ophthalmology") %>% 
  
  ggplot(aes(x = der_activity_month, y = value, colour = name, group = name)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "loess", span = 0.2) +
  facet_grid(str_wrap(name,15) ~ type, scales = "free") +
  scale_color_SU() +
  scale_y_continuous(labels = comma, oob = squish) +
  theme(strip.background = element_rect(fill = NA, colour = "grey"),
        strip.text = element_text(face = "bold"),
        legend.position = "none"
        ) +
  labs(x = "", y = "", colour = "Activity",
       title = "Trends in activity and cost by speciality and sector: Ophthalmology",
       subtitle = "Monthly elective activity | National | 2018-22")

create_dt(
  national_data %>% 
  group_by(der_activity_month, type, speciality) %>% 
  sum_spells_function(.) %>% 
  pivot_longer(cols = c(-der_activity_month, -type, -speciality)) %>% 
  mutate(name = case_when(str_detect(name, "IP") ~ "Inpatient admissions", 
                          str_detect(name, "OP") ~ "Outpatient appointments",
                          TRUE ~ "Cost (£)")) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>% 
  filter(speciality == "Ophthalmology")
)

The predominant type of ophthalmic care varies by sector; in NHS settings, more than 2 in every 3 contacts are delivered via outpatient attendances, where as care in the independent sector is most often provided in the form of inpatients admissions. These differences are likely a function of the types of procedures considered suitable to outsource from the NHS to independent providers.

Activity volumes between care types are much more similar for orthopaedic care; the monthly volumes of activity in both inpatient and outpatient settings were between 30-40 thousand contacts per month before the pandemic and have reduced to near 20-30 thousand in the post-pandemic period. Provision of orthopaedic care in the independent sector has been more stable - approx. 10,000 monthly inpatient contacts before and after the pandemic.

2 Independent sector share

national_data %>%
  group_by(der_activity_month, type, speciality) %>% 
  sum_spells_function(.) %>% 
  group_by(der_activity_month, type, speciality) %>% 
  mutate(total_activity = sum(n_spells_IP, n_spells_OP)) %>% 
  pivot_longer(cols = c(-der_activity_month, -type, -speciality)) %>% 
  pivot_wider(id_cols = c(der_activity_month, speciality, name), 
              names_from = type,
              values_from = value
              ) %>% 
  group_by(der_activity_month, speciality, name) %>% 
  mutate(prop = `Independent Sector`/ sum(`Independent Sector`, `NHS`) * 100) %>% 
  mutate(name = case_when(str_detect(name, "IP") ~ "Inpatient", 
                          str_detect(name, "OP") ~ "Outpatient",
                          str_detect(name, "cost") ~ "Cost",
                          TRUE ~ "All activity")) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>%
  filter(name %in% c("Inpatient", "Outpatient")) %>% 
  
  ggplot(aes(x = der_activity_month, y = prop, colour = name, group = name)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "loess", span = 0.2) +
  facet_wrap(~speciality#, scales = "free_y"
             ) +
  scale_color_SU() +
  scale_y_continuous(labels = comma, oob = squish) +
  theme(strip.background = element_rect(fill = NA, colour = "grey"),
        strip.text = element_text(face = "bold"),
        legend.position = "bottom"
        ) +
  labs(x = "", y = "Independent sector market share (%)", colour = "Activity type", 
       title = "Share of activity delivered by the independent sector",
       subtitle = "Monthly elective inpatient and outpatient activity | National | 2017-22")

create_dt(
  national_data %>%
  group_by(der_activity_month, type, speciality) %>% 
  sum_spells_function(.) %>% 
  group_by(der_activity_month, type, speciality) %>% 
  mutate(total_activity = sum(n_spells_IP, n_spells_OP)) %>% 
  pivot_longer(cols = c(-der_activity_month, -type, -speciality)) %>% 
  pivot_wider(id_cols = c(der_activity_month, speciality, name), 
              names_from = type,
              values_from = value
              ) %>% 
  group_by(der_activity_month, speciality, name) %>% 
  mutate(prop = `Independent Sector`/ sum(`Independent Sector`, `NHS`) * 100) %>% 
  mutate(name = case_when(str_detect(name, "IP") ~ "Inpatient", 
                          str_detect(name, "OP") ~ "Outpatient",
                          str_detect(name, "cost") ~ "Cost",
                          TRUE ~ "All activity")) %>% 
  filter(der_activity_month > "2018-01-01" &
           der_activity_month < "2022-11-01") %>%
  filter(name %in% c("Inpatient", "Outpatient"))
)

In considering the changing independent sector market share in both ophthalmic and orthopaedic care, we can see that inpatient activity is the dominate care type.

In ophthalmic care, the proportion of care delievered by the IS has grown at a steadily increasing rate through our data collection period, excluding the COVID-19; this is in contrast to the outpatient ratio, which has grown at a lesser rate. Is it the case that the increase in the proportion of care delivered by the IS through inpatient activity is driven by cataract surgeries and the growth in the outpatient trend is a result of the increasing share of Vitreous Retinal procedures?

The independent sector’s market share of orthopaedic care is larger and more consistent than in ophthalmic procedures. The growth in independent sector provision is less pronounced in orthopaedic care. A large spike in inpatient independent sector activity was seen during the immediate COVID-19 pandemic recovery. Independent sector provision proportion then returned to closer to pre-pandemic levels and has been steadily growing since mid-2021.


5 Wait time

The proportion of patients by the duration of their wait to be seen/treated is displayed below. Patients are presented according to the care type (inpatient or outpatient) and by the setting in which they received care (NHS or independent sector). The larger the yellow and gold bars, the lower the waiting time generally across that service type.

5.1 Orthopaedics

# Stacked bar chart proportions
national_data_ortho %>% 
  wrangle_function(., duration_elective_wait_range) %>% 
  filter(var_1 != "500+") %>% 
  pivot_longer(cols = c(`Independent Sector`, NHS),
               names_to = "sector",
               values_to = "value"
               ) %>% 
  mutate(year = lubridate::year(der_activity_month)) %>% 
  group_by(year, var_1, name, sector) %>% 
  summarise(value = sum(value)) %>% 
  group_by(year, name, sector) %>% 
  mutate(prop = value/sum(value)*100) %>% 
  
  ggplot(aes(x = year, y = prop, fill = var_1)) +
  geom_col(position = "stack", colour = "grey", alpha = 0.9, width = 0.7) +
  facet_grid(name~sector) +
  scale_fill_SU() +
  theme(#legend.position = "none",
        strip.background = element_rect(fill = NA, colour = "grey"),
        strip.text = element_text(face = "bold"),
        axis.title.x = element_blank()
        ) +
  labs(y = "Proportion (%)",
       fill = "Wait duration (days)",
       title = "Change in wait time for treatment",
       subtitle = "Proportion of elective orthopaedic care contacts by wait time | National | 2018-22"
       )

create_dt(
  national_data_ortho %>% 
  wrangle_function(., duration_elective_wait_range) %>% 
  filter(var_1 != "500+") %>% 
  pivot_longer(cols = c(`Independent Sector`, NHS),
               names_to = "sector",
               values_to = "value"
               ) %>% 
  mutate(year = lubridate::year(der_activity_month)) %>% 
  group_by(year, var_1, name, sector) %>% 
  summarise(value = sum(value)) %>% 
  group_by(year, name, sector) %>% 
  mutate(prop = value/sum(value)*100)
)

For elective orthopaedic care over the last 5 years, lower waiting times are seen in the independent sector for inpatient admissions and in the NHS for outpatient appointments.

While waiting times for inpatient admissions have been lower in the independent sector, this appears to be changing. The proportion of patients waiting 100 days or more for an inpatient admission has been increasing since 2019; the waiting time profile for inpatient admissions in the independent sector is now very similar to NHS.

For outpatient appointments, the proportion of patients waiting less than 100 days is much higher in NHS patients compared to those treated in the independent sector. It may be that those NHS-funded patients treated in the independent sector, were offered care in the independent sector after a period of time spent waiting for treatment at an NHS site, explaining their increased waiting times.

5.2 Ophthalmology

national_data_ophthal %>% 
  wrangle_function(., duration_elective_wait_range) %>% 
  filter(var_1 != "500+") %>% 
  pivot_longer(cols = c(`Independent Sector`, NHS),
               names_to = "sector",
               values_to = "value"
               ) %>% 
  mutate(year = lubridate::year(der_activity_month)) %>% 
  group_by(year, var_1, name, sector) %>% 
  summarise(value = sum(value)) %>% 
  group_by(year, name, sector) %>% 
  mutate(prop = value/sum(value)*100) %>% 
  
  ggplot(aes(x = year, y = prop, fill = var_1)) +
  geom_col(position = "stack", colour = "grey", alpha = 0.9, width = 0.7) +
  facet_grid(name~sector) +
  scale_fill_SU() +
  theme(#legend.position = "none",
    strip.background = element_rect(fill = NA, colour = "grey"),
    strip.text = element_text(face = "bold"),
    axis.title.x = element_blank()
    ) +
  labs(y = "Proportion (%)",
       fill = "Wait duration (days)",
       title = "Change in wait time for treatment",
       subtitle = "Proportion of elective ophthalmology care contacts by wait time | National | 2018-22"
  )

create_dt(
  national_data_ophthal %>% 
  wrangle_function(., duration_elective_wait_range) %>% 
  filter(var_1 != "500+") %>% 
  pivot_longer(cols = c(`Independent Sector`, NHS),
               names_to = "sector",
               values_to = "value"
               ) %>% 
  mutate(year = lubridate::year(der_activity_month)) %>% 
  group_by(year, var_1, name, sector) %>% 
  summarise(value = sum(value)) %>% 
  group_by(year, name, sector) %>% 
  mutate(prop = value/sum(value)*100)
)

The time in which patients wait for elective inpatient ophthalmic treatment is similar in those treated in NHS sites and those sent to independent sector sites. Over the last 5 years, approximately 75% inpatient admissions in NHS sites have had less that 100 days waiting times; this was the case in the independent sector up to 2019 however waiting times have been increasing for NHS-funded inpatient admissions in independent sector sites in recent years.

The waiting time for outpatient appointments has generally been lower in NHS-funded patients in the independent sector compared to those receiving appointments in NHS sites. On average, less than half the patients in NHS sites waited for 100 days or less to be seen/treated, whereas the figure is approx. 60% for independent sector sites.