generated from opensafely/research-template
-
Notifications
You must be signed in to change notification settings - Fork 0
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
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
e0a66cd
Phamarcy First event measures & graph
viv3ckj f6eb975
added measures action
viv3ckj 25fa351
Delete unused files from template
milanwiedemann c8544c1
Restructure and rename plotting fun
milanwiedemann 988bb1f
Merge pull request #4 from opensafely/milanwiedemann/measures-suggest…
viv3ckj 2824469
Tidied and documented function and measures.
viv3ckj 7a80e1f
Graphs for events and conditions added
viv3ckj ed865e7
Modified legend key and created dictionary for codelist
viv3ckj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
|
||
<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* |
Large diffs are not rendered by default.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762 |
8 changes: 8 additions & 0 deletions
8
codelists/user-chriswood-pharmacy-first-clinical-pathway-conditions.csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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?