Skip to content

Commit 7a80e1f

Browse files
committed
Graphs for events and conditions added
1 parent 2824469 commit 7a80e1f

File tree

8 files changed

+138
-71
lines changed

8 files changed

+138
-71
lines changed

analysis/report_measures.py

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@
1515
# Pharmacy First service (qualifier value)
1616
"pharmacy_first_service": ["983341000000102"],
1717
}
18+
# The following codes come from codelists/user-chriswood-pharmacy-first-clinical-pathway-conditions.csv file.
19+
# Currently written as a hardcoded dictionary to allow for easy for looping (ln66-83), but will be imported from codelist csv in future commits.
20+
# Pharmacy First seven clinical conditions codelist
21+
pharmacy_first_conditions_codes = {
22+
# Community Pharmacy (CP) Blood Pressure (BP) Check Service (procedure)
23+
"acute_otitis_media": ["3110003"],
24+
# Community Pharmacy (CP) Contraception Service (procedure)
25+
"herpes_zoster": ["4740000"],
26+
# Community Pharmacist (CP) Consultation Service for minor illness (procedure)
27+
"acute_sinusitis": ["15805002"],
28+
# Pharmacy First service (qualifier value)
29+
"impetigo": ["48277006"],
30+
# Community Pharmacy (CP) Contraception Service (procedure)
31+
"infected_insect_bite": ["262550002"],
32+
# Community Pharmacist (CP) Consultation Service for minor illness (procedure)
33+
"acute_pharyngitis": ["363746003"],
34+
# Pharmacy First service (qualifier value)
35+
"uncomplicated_urinary_tract_infection": ["1090711000000102"],
36+
}
1837

1938
registration = practice_registrations.for_patient_on(INTERVAL.end_date)
2039

@@ -24,7 +43,7 @@
2443
)
2544

2645
# Loop through each condition to create a measure
27-
for condition_name, codelist in pharmacy_first_event_codes.items():
46+
for pharmacy_first_event, codelist in pharmacy_first_event_codes.items():
2847
condition_events = selected_events.where(
2948
clinical_events.snomedct_code.is_in(codelist)
3049
)
@@ -36,33 +55,29 @@
3655
# Define the denominator as the number of patients registered
3756
denominator = registration.exists_for_patient()
3857

39-
# Define the measure
4058
measures.define_measure(
41-
name=f"count_{condition_name}",
59+
name=f"count_{pharmacy_first_event}",
4260
numerator=numerator,
4361
denominator=denominator,
4462
intervals=months(8).starting_on("2023-11-01")
4563
)
4664

47-
# # Count pharmacy first codes
48-
# pharmacy_first_code_counts = {}
65+
# Loop through each CLINICAL condition to create a measure
66+
for condition_name, condition_code in pharmacy_first_conditions_codes.items():
67+
condition_events = selected_events.where(
68+
clinical_events.snomedct_code.is_in(condition_code)
69+
)
4970

50-
# for code_desc, code in pharmacy_first_event_codes.items():
51-
# count_codes_query = selected_events.where(
52-
# selected_events.snomedct_code.is_in(code)
53-
# ).count_for_patient()
54-
# pharmacy_first_code_counts[f"count_{code_desc}"] = count_codes_query
71+
# Define the numerator as the count of events for the condition
72+
numerator = condition_events.count_for_patient()
5573

5674

57-
# for measures_name, code_counts in pharmacy_first_code_counts.items():
58-
# measures.define_measure(
59-
# name=measures_name,
60-
# numerator=code_counts,
61-
# group_by={
62-
# "practice_region": registration.practice_nuts1_region_name
63-
# },
64-
# denominator=patients.exists_for_patient(),
65-
# intervals=intervals,
66-
# )
75+
# Define the denominator as the number of patients registered
76+
denominator = registration.exists_for_patient()
6777

68-
78+
measures.define_measure(
79+
name=f"count_{condition_name}",
80+
numerator=numerator,
81+
denominator=denominator,
82+
intervals=months(8).starting_on("2023-11-01")
83+
)

analysis/reports/pf_report.Rmd

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ pre[class] {
2424
</style>
2525

2626

27-
2827
```{r setup, include=FALSE}
2928
knitr::opts_chunk$set(echo = FALSE)
3029
@@ -34,13 +33,13 @@ library(readr)
3433
3534
3635
```
37-
$~$
36+
<br>
3837

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

4140
Add background here.
4241

43-
$~$
42+
<br>
4443

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

@@ -58,8 +57,7 @@ Links to the codelist for each analysis can be found beneath the relevant sectio
5857

5958
This report contains the following sections:
6059

61-
62-
60+
* [Clinical Services](#services)
6361
* [Clinical Pathways](#pathways)
6462
* [Clinical condition](#condition)
6563
* [Days of the week](#dotw)
@@ -82,9 +80,11 @@ This report contains the following sections:
8280
* [Age](#contra_age)
8381
* [Region](#contra_region)
8482

85-
$~$
83+
<br>
8684

87-
## Clinical services
85+
## Clinical Services <a name="services"></a>
86+
87+
<br>
8888

8989
```{r, message=FALSE, warning=FALSE}
9090
# Load plotting function
@@ -94,12 +94,15 @@ df_measures <- readr::read_csv(
9494
here::here("output", "report", "conditions_measures.csv")
9595
)
9696
97-
plot1_conditions <- plot_measures(df_measures,
97+
plot_services <- plot_measures(df_measures,
9898
title = "Number of consultations for each clinical service per month",
99-
x_label = "Month",
100-
y_label = "Number of Consultations",
101-
color_label = "Clinical Service")
102-
print(plot1_conditions)
99+
measure_names = c("count_blood_pressure_service",
100+
"count_contraception_service",
101+
"count_consultation_service",
102+
"count_pharmacy_first_service"),
103+
y_label = "Number of codes for consultations",
104+
)
105+
print(plot_services)
103106
```
104107

105108
## Clinical Pathways <a name="pathways"></a>
@@ -116,6 +119,22 @@ Here we show the number of consultations for each of the Pharmacy First Clinical
116119

117120
> LINE CHART WITH COUNT OF EACH CLINICAL CONDITION
118121
122+
```{r, message=FALSE, warning=FALSE}
123+
124+
plot_conditions <- plot_measures(df_measures,
125+
title = "Number of consultations for each clinical condition per month",
126+
measure_names = c("count_acute_otitis_media",
127+
"count_herpes_zoster",
128+
"count_acute_sinusitis",
129+
"count_impetigo",
130+
"count_infected_insect_bite",
131+
"count_acute_pharyngitis",
132+
"count_uncomplicated_urinary_tract_infection"),
133+
y_label = "Number of codes for consultations",
134+
)
135+
print(plot_conditions)
136+
```
137+
119138
### Counts by day of the week <a name="dotw"></a>
120139
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).
121140

analysis/reports/pf_report.html

Lines changed: 2 additions & 1 deletion
Large diffs are not rendered by default.

codelists/codelists.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
{
2-
"files": {}
2+
"files": {
3+
"user-chriswood-pharmacy-first-clinical-pathway-conditions.csv": {
4+
"id": "user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762",
5+
"url": "https://www.opencodelists.org/codelist/user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762/",
6+
"downloaded_at": "2024-08-22 12:53:00.167017Z",
7+
"sha": "bed7f74add5c2d2ac6f7120d89f5ba94e57a28cb"
8+
}
9+
}
310
}

codelists/codelists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
user/chriswood/pharmacy-first-clinical-pathway-conditions/7ec97762
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
code,term
2+
1090711000000102,Uncomplicated urinary tract infection
3+
15805002,Acute sinusitis
4+
262550002,Infected insect bite
5+
3110003,Acute otitis media
6+
363746003,Acute pharyngitis
7+
4740000,Herpes zoster
8+
48277006,Impetigo

lib/functions/function_plot_measures.R

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#' Creates a line plot of measures over time, with customisable labels and colours.
44
#'
55
#' @param data A dataframe containing the data to plot.
6+
#' @param measure_names Strings specifiying the names of measure columns to be plotted.
67
#' @param title A string specifying the title of the plot. Default is NULL.
78
#' @param x_label A string specifying the label for the x-axis. Default is NULL.
89
#' @param y_label A string specifying the label for the y-axis. Default is NULL.
@@ -13,42 +14,80 @@
1314
#'
1415
#' @return A ggplot object.
1516

17+
# Define the function
1618
plot_measures <- function(
1719
data,
20+
measure_names,
1821
date_col = "interval_end",
1922
value_col = "numerator",
2023
measure_col = "measure",
2124
title = NULL,
2225
x_label = NULL,
2326
y_label = NULL,
24-
color_label = NULL) {
27+
color_label = NULL,
28+
axis_x_text_size = 7) {
29+
30+
# Check if the necessary columns exist in the data
31+
if (date_col %in% names(data) == FALSE) {
32+
stop("Data does not have a column with the name '", date_col, "'")
33+
} else if (value_col %in% names(data) == FALSE) {
34+
stop("Data does not have a column with the name '", value_col, "'")
35+
} else if (measure_col %in% names(data) == FALSE) {
36+
stop("Data does not have a column with the name '", measure_col, "'")
37+
}
38+
39+
# Convert column names to symbols
40+
date_sym <- sym(date_col)
41+
value_sym <- sym(value_col)
42+
measure_sym <- sym(measure_col)
43+
44+
# Ensure the date column is of Date type
45+
data <- data %>%
46+
mutate(!!date_sym := as.Date(!!date_sym))
47+
48+
# Filter measures column for user-specified measure names
49+
data <- data %>%
50+
filter(!!measure_sym %in% measure_names)
2551

2652
# Create plot
2753
plot1 <- ggplot(
2854
data,
2955
aes(
30-
x = {{date_col}},
31-
y = {{value_col}},
32-
color = {{measure_col}},
33-
group = {{measure_col}}
56+
x = !!date_sym,
57+
y = !!value_sym,
58+
color = !!measure_sym,
59+
group = !!measure_sym
3460
)
3561
) +
3662
geom_line() +
3763
labs(
3864
title = title,
3965
x = x_label,
4066
y = y_label,
41-
color = "Condition"
67+
color = color_label
68+
) +
69+
scale_y_continuous(
70+
limits = c(0, NA),
4271
) +
43-
# Setting the minimum y-value
44-
ylim(0, NA) +
45-
# Applying the minimal theme
4672
theme_minimal() +
73+
theme(axis.text.x = element_text(size = axis_x_text_size),
74+
legend.position="bottom",
75+
legend.key.size = unit(0.5, "cm"),
76+
legend.text = element_text(size = 6),
77+
legend.title = element_text(size = 8)) +
78+
guides(
79+
color = guide_legend(nrow = 2) # Adjust number of rows in the legend
80+
) +
81+
geom_vline(
82+
xintercept = lubridate::as_date("2024-02-01"),
83+
linetype = "dotted",
84+
colour = "orange",
85+
linewidth = .7) +
4786
scale_x_date(
48-
date_breaks = "1 month",
49-
date_labels = "%b %Y",
87+
date_breaks = "1 month",
88+
date_labels = "%b %Y"
5089
)
5190

52-
# Return plot
91+
5392
plot1
54-
}
93+
}

lib/functions/sketch.R

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)