Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Counts by Pharmacy First Service #3

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions analysis/dataset_definition.py

This file was deleted.

75 changes: 75 additions & 0 deletions analysis/report_measures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from ehrql import INTERVAL, create_measures, months, codelist_from_csv
from ehrql.tables.tpp import clinical_events, patients, practice_registrations

measures = create_measures()
measures.configure_dummy_data(population_size=1000)

# Dictionary of pharmacy first codes
pharmacy_first_event_codes = {
# Community Pharmacy (CP) Blood Pressure (BP) Check Service (procedure)
"blood_pressure_service": ["1659111000000107"],
# Community Pharmacy (CP) Contraception Service (procedure)
"contraception_service": ["1659121000000101"],
# Community Pharmacist (CP) Consultation Service for minor illness (procedure)
"consultation_service": ["1577041000000109"],
# Pharmacy First service (qualifier value)
"pharmacy_first_service": ["983341000000102"],
}

# Import the codelist from CSV
pharmacy_first_codelist = codelist_from_csv(
"codelists/user-chriswood-pharmacy-first-clinical-pathway-conditions.csv",
column="code", category_column = "term"
)

pharmacy_first_conditions_codes = {}
# Iterate through codelist, forming a dictionary
for codes, term in pharmacy_first_codelist.items():
normalised_term = term.lower().replace(" ", "_")
codes = [codes]
pharmacy_first_conditions_codes[normalised_term] = codes

registration = practice_registrations.for_patient_on(INTERVAL.end_date)

# Select clinical events in interval date range
selected_events = clinical_events.where(
clinical_events.date.is_on_or_between(INTERVAL.start_date, INTERVAL.end_date)
)

# Loop through each CLINICAL SERVICE to create a measure
for pharmacy_first_event, codelist in pharmacy_first_event_codes.items():
condition_events = selected_events.where(
clinical_events.snomedct_code.is_in(codelist)
)

# Define the numerator as the count of events for the condition
numerator = condition_events.count_for_patient()

# Define the denominator as the number of patients registered
denominator = registration.exists_for_patient()

measures.define_measure(
name=f"count_{pharmacy_first_event}",
numerator=numerator,
denominator=denominator,
intervals=months(8).starting_on("2023-11-01")
)

# Loop through each CLINICAL CONDITION to create a measure
for condition_name, condition_code in pharmacy_first_conditions_codes.items():
condition_events = selected_events.where(
clinical_events.snomedct_code.is_in(condition_code)
)

# Define the numerator as the count of events for the condition
numerator = condition_events.count_for_patient()

# Define the denominator as the number of patients registered
denominator = registration.exists_for_patient()

measures.define_measure(
name=f"count_{condition_name}",
numerator=numerator,
denominator=denominator,
intervals=months(8).starting_on("2023-11-01")
)
236 changes: 236 additions & 0 deletions analysis/reports/pf_report.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
---
title: "Pharmacy First"
output:
html_document:
toc: true
toc_depth: 4
theme: journal
date: "01-01-2020 through 31-06-2024 by month"
---
```{css, echo=FALSE}
pre {
max-height: 300px;
overflow-y: auto;
}
pre[class] {
max-height: 200px;
}
```

<style>
body {
text-align: justify;
font-size: 11pt}
</style>


```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)

library(tidyverse)
library(here)
library(readr)


```
<br>

## Background <a name="background"></a>

Add background here.

<br>

## Methods <a name="methods"></a>

This study used data from OpenSAFELY-TPP, which covers 40% of the population of England. For a description of the representativeness of this sample, please see our manuscript [here](https://wellcomeopenresearch.org/articles/7-191/v1). Individuals were included if they were alive and registered at a TPP practice each month, across the study period. Patients were excluded if their listed age was not between 0 and 120 years.

Counts represent patients with at least one clinical code of relevance in that month. Patients with more than one of the same clinical code in a month were only counted once. Rates divide the count by the included study population and multiply by 1,000 to achieve a rate per 1,000 registered patients.

Counts <=7 have been redacted and all numbers rounded to the nearest 5 to avoid potential re-identification of individuals. The rates displayed were computed with these rounded counts.

Our data relies on a relevant Pharmacy First code being added to a patient's GP record. The Pharmacy First service relies on [GP Connect: Update Record](https://digital.nhs.uk/services/gp-connect/gp-connect-in-your-organisation/gp-connect-update-record) to update a patient's GP record with consultation information from the community pharmacy. Following the launch of the Pharmacy First service, there has been a [gradual roll-out of GP Connect: Update Record](https://cpe.org.uk/our-news/gp-connect-update-record-rollout-and-flow-of-information/) across the approved community pharmacy IT system suppliers.

*Need to complete this*

Links to the codelist for each analysis can be found beneath the relevant section.

This report contains the following sections:

* [Clinical Services](#services)
* [Clinical Pathways](#pathways)
* [Clinical condition](#condition)
* [Days of the week](#dotw)
* [NHS region](#region)
* [Ethnicity](#ethnicity)
* [IMD](#imd)
* [Shingles](#shingles)
+ [Sex](#shingles_sex)
+ [Age](#shingles_age)
+ [Ethnicity](#shingles_ethnicity)
+ [IMD](#shingles_imd)
+ [Region](#shingles_region)
+ [Medication supply](#shingles_supply)
* [Urinary tract infection etc.](#urt)
* [Hypertension](#hyp)
* [Age](#hyp_age)
* [Sex](#hyp_sex)
* [Region](#hyp_region)
* [Contraception](#contra)
* [Age](#contra_age)
* [Region](#contra_region)
Comment on lines +60 to +81
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@viv3ckj do you remember where this came from? I think Chris had a Jupyter notebook but I cant find it anywhere?


<br>

## Clinical Services <a name="services"></a>

<br>

```{r, message=FALSE, warning=FALSE}
# Load plotting function
source(here::here("lib", "functions", "function_plot_measures.R"))
# Load data
df_measures <- readr::read_csv(
here::here("output", "report", "conditions_measures.csv")
)

# Define the custom labels for clinical conditions
clinical_measure_labels <- c(
"count_acute_otitis_media" = "Acute Otitis Media",
"count_herpes_zoster" = "Herpes Zoster",
"count_acute_sinusitis" = "Acute Sinusitis",
"count_impetigo" = "Impetigo",
"count_infected_insect_bite" = "Infected Insect Bite",
"count_acute_pharyngitis" = "Acute Pharyngitis",
"count_uncomplicated_urinary_tract_infection" = "UTI"
)

# Define the custom labels for clinical services
clinical_service_labels <- c(
"count_blood_pressure_service" = "Blood Pressure Service",
"count_contraception_service" = "Contraception Service",
"count_consultation_service" = "Consultation Service",
"count_pharmacy_first_service" = "Pharmacy First Service"
)

```

```{r, message=FALSE, warning=FALSE}
plot_services <- plot_measures(df_measures,
title = "Number of consultations for each clinical service per month",
measure_names = names(clinical_service_labels),
custom_labels = clinical_service_labels,
y_label = "Number of codes for consultations",
)
print(plot_services)
```

## Clinical Pathways <a name="pathways"></a>

This section focuses on the Clinical Pathways element of that Pharmacy First service.


### Clinical Condition <a name="condition"></a>

This section focuses on the clinical conditions within the Clinical Pathways element of that Pharmacy First service:

#### Counts by clinical condition
Here we show the number of consultations for each of the Pharmacy First Clinical Pathways Clinical Conditions

> LINE CHART WITH COUNT OF EACH CLINICAL CONDITION

```{r, message=FALSE, warning=FALSE}

plot_conditions <- plot_measures(df_measures,
title = "Number of consultations for each clinical condition per month",
measure_names = names(clinical_measure_labels),
custom_labels = clinical_measure_labels,
y_label = "Number of codes for consultations",
)
print(plot_conditions)
```

### Counts by day of the week <a name="dotw"></a>
Here we show the number of consultations for the Pharmacy First Clinical Pathways by day of the week the consultation was conducted. (Mainly of interest to show what happens at weekends etc e.g. when GP practices are closed).

> BAR CHART WITH COUNT BY DAY OF THE WEEK

### Rates by region <a name="region"></a>
Here we show the rates of consultations for the Pharmacy First Clinical Pathways by the NHS Region in which the patient is registered. (Might not be the region where PF consultation conducted).

> RATES OF ANY PF CLINICAL PATHWAY BY REGION

### Rates by ethnicity <a name="ethnicity"></a>
Here we show the rates of consultations for the Pharmacy First Clinical Pathways by patient ethnicity

> RATES OF ANY PF CLINICAL PATHWAY BY ETHNICITY

### Rates by IMD <a name="imd"></a>
Here we show the rates of consultations for the Pharmacy First Clinical Pathways by IMD (based on patient address)

> RATES OF ANY PF CLINICAL PATHWAY BY IMD

### Shingles <a name="shingles"></a>
Here we show the rates specifically for consultations conducted under the Shingles clinical pathway:

#### Rates by sex <a name="shingles_sex"></a>
Here we show the rates of consultations for the Pharmacy First Shingles Clinical Pathways by sex

> RATES OF SHINGLES CLINICAL PATHWAY BY SEX

#### Rates by age <a name="shingles_age"></a>
Here we show the rates of consultations for the Pharmacy First Shingles Clinical Pathways by age. (Would need to consider age bands as different for each pathway)

> RATES OF SHINGLES CLINICAL PATHWAY BY AGE

#### Rates by ethnicity <a name="shingles_ethnicity"></a>
Here we show the rates of consultations for the Pharmacy First Shingles Clinical Pathways by ethnicity

> RATES OF SHINGLES CLINICAL PATHWAY BY ETHNICITY

#### Rates by IMD <a name="shingles_imd"></a>
Here we show the rates of consultations for the Pharmacy First Shingles Clinical Pathways by IMD

> RATES OF SHINGLES CLINICAL PATHWAY BY IMD

#### Rates by region <a name="shingles_region"></a>
Here we show the rates of consultations for the Pharmacy First Shingles Clinical Pathways by NHS region

> RATES OF SHINGLES CLINICAL PATHWAY BY REGION

#### Rates by medication supply <a name="shingles_supply"></a>
Here we show the percentage of consultations for the Pharmacy First Shingles Clinical Pathways with vs without medication supply. (Could also potentially show details of which medication issued)

> BAR PLOT OF PERCENTAGE OF SHINGLES CLINICAL PATHWAY WITH/WITHOUT MEDICATION SUPPLIED

### Urinary tract infection etc. <a name="urt"></a>

> *placeholder*

## Hypertension <a name="hyp"></a>

*description*

### Age <a name="hyp_age"></a>

> *placeholder*

### Sex <a name="hyp_sex"></a>

> *placeholder*

### Region <a name="hyp_region"></a>

> *placeholder*

## Contraception <a name="contra"></a>

*description*

### Age <a name="contra_age"></a>

> *placeholder*

### Region <a name="contra_region"></a>

> *placeholder*
718 changes: 718 additions & 0 deletions analysis/reports/pf_report.html

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion analysis/stata.do

This file was deleted.

9 changes: 8 additions & 1 deletion codelists/codelists.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
{
"files": {}
"files": {
"user-chriswood-pharmacy-first-clinical-pathway-conditions.csv": {
"id": "user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762",
"url": "https://www.opencodelists.org/codelist/user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762/",
"downloaded_at": "2024-08-22 12:53:00.167017Z",
"sha": "bed7f74add5c2d2ac6f7120d89f5ba94e57a28cb"
}
}
}
1 change: 1 addition & 0 deletions codelists/codelists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
code,term
1090711000000102,Uncomplicated urinary tract infection
15805002,Acute sinusitis
262550002,Infected insect bite
3110003,Acute otitis media
363746003,Acute pharyngitis
4740000,Herpes zoster
48277006,Impetigo
Loading