Skip to content

Commit 3769d37

Browse files
committed
The source for the original dataset is no longer available so I have completely rebuilt the dataset, and included the whole of GM, from a new verifiable source: NHS England.
1 parent ae5cfa1 commit 3769d37

10 files changed

Lines changed: 4975 additions & 229 deletions

pharmacies/README.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,39 @@
1-
[<img src="thumbnail.png">](trafford_pharmacies_styled.geojson)
2-
</br>
3-
41
<table>
52
<tr>
63
<td>Dataset name</td>
7-
<td>Trafford pharmacies</td>
4+
<td>Pharmacies</td>
85
</tr>
96
<tr>
107
<td>Dataset description</td>
11-
<td>Dataset containing the location of pharmacies in Trafford.</td>
8+
<td>Location of pharmacies Trafford and Greater Manchester.</td>
129
</tr>
1310
<tr>
1411
<td>Source</td>
15-
<td>Trafford Council</td>
12+
<td>NHS England</td>
1613
</tr>
1714
<tr>
1815
<td>Publisher</td>
19-
<td>Trafford Council</td>
16+
<td>NHS Business Services Authority (NHSBSA) Master Data Replacement (MDR)</td>
2017
</tr>
2118
<tr>
2219
<td>Publisher URL</td>
23-
<td><a href="http://www.trafford.gov.uk/about-your-council/children-families-and-wellbeing/children-families-and-wellbeing.aspx"></a>http://www.trafford.gov.uk/about-your-council/children-families-and-wellbeing/children-families-and-wellbeing.aspx</td>
20+
<td><a href="https://opendata.nhsbsa.net/dataset/consolidated-pharmaceutical-list">https://opendata.nhsbsa.net/dataset/consolidated-pharmaceutical-list</a></td>
2421
</tr>
2522
<tr>
2623
<td>Geography</td>
2724
<td>Points</td>
2825
</tr>
2926
<tr>
3027
<td>Geographic coverage</td>
31-
<td>Trafford</td>
28+
<td>Trafford, Greater Manchester</td>
3229
</tr>
3330
<tr>
3431
<td>Temporal coverage</td>
35-
<td>May 2018</td>
32+
<td>2024-25 Q4 (2025-03-31)</td>
3633
</tr>
3734
<tr>
3835
<td>Update frequency</td>
39-
<td>Unknown</td>
36+
<td>Quarterly</td>
4037
</tr>
4138
<tr>
4239
<td>Licence</td>
@@ -52,7 +49,7 @@
5249
</tr>
5350
<tr>
5451
<td>Last updated</td>
55-
<td>May 2018</td>
52+
<td>2025-06-11</td>
5653
</tr>
5754
<tr>
5855
<td>Notes</td>

pharmacies/gm_pharmacies.csv

Lines changed: 632 additions & 0 deletions
Large diffs are not rendered by default.

pharmacies/gm_pharmacies.geojson

Lines changed: 638 additions & 0 deletions
Large diffs are not rendered by default.

pharmacies/index.Rmd

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
pagetitle: "Pharmacies in Trafford and Greater Manchester"
3+
lang: "en-GB"
4+
output:
5+
html_document:
6+
css: ../guidance/template/styles.css
7+
self_contained: TRUE
8+
---
9+
10+
```{r setup, include=FALSE}
11+
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
12+
library(tidyverse) ; library(htmltools) ; library(DT)
13+
14+
df <- read_csv("trafford_pharmacies.csv") %>%
15+
rename_all(. %>% str_to_title() %>% str_replace_all("_", " "))
16+
```
17+
<header>
18+
<span id="a11yNav"><a href="#downloads" class="themeBlockDark">Skip to downloads</a></span>
19+
<a href="https://www.trafforddatalab.io/data.html"><img src="https://www.trafforddatalab.io/assets/logo/trafforddatalab_logo.svg" alt="Trafford Data Lab" aria-label="Return to Trafford Data Lab data page" width="100" class="traffordDataLabLogo"/></a>
20+
21+
<h1>Pharmacies in Trafford and Greater Manchester</h1>
22+
*Dataset containing the locations of pharmacies in Trafford and Greater Manchester (based on postcode centroid), including opening times.*
23+
</header>
24+
25+
<main>
26+
<h2>Metadata</h2>
27+
28+
<table id="metadata" class="table table-condensed">
29+
<thead>
30+
<tr class="header">
31+
<th>Source</th>
32+
<th>Publisher</th>
33+
<th>Time period</th>
34+
<th>Geography</th>
35+
<th>Licence</th>
36+
<th>Attribution</th>
37+
<th>Last updated</th>
38+
</tr>
39+
</thead>
40+
<tr>
41+
<td>NHS England</td>
42+
<td><a href="https://opendata.nhsbsa.net/dataset/consolidated-pharmaceutical-list" target="_blank">NHS Business Services Authority (NHSBSA) Master Data Replacement (MDR)</a></td>
43+
<td><time datetime="2025-03-31">2025-03-31</time></td>
44+
<td>Electoral ward, Local Authority</td>
45+
<td><a href="http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" target="_blank">OGL v3.0</a></td>
46+
<td>Contains public sector information licensed under the Open Government Licence v3.0</td>
47+
<td><time datetime="2025-06-11">2025-06-11</time></td>
48+
</tr>
49+
</table>
50+
51+
<h2>Preview</h2>
52+
Sort, filter and export a selection of the data using the table.
53+
54+
```{r preview}
55+
datatable(df,
56+
class = 'cell-border stripe',
57+
rownames = FALSE,
58+
extensions = c('Scroller', 'Buttons', 'KeyTable'),
59+
options = list(
60+
keys = TRUE,
61+
search = list(regex = TRUE),
62+
searchHighlight = TRUE,
63+
dom = 'ftB',
64+
buttons = list(
65+
list(extend = "csv",
66+
text = "Download selection")),
67+
deferRender = TRUE,
68+
scrollX = TRUE,
69+
scrollY = 300,
70+
scroller = TRUE,
71+
columnDefs = list(
72+
list(className = 'dt-left', targets = "_all")
73+
)))
74+
```
75+
<div id="tableFooterTitle">Pharmacies within Trafford.</div>
76+
77+
<h2>Data</h2>
78+
<span id ="downloads">Download the complete dataset using the following links:</span>
79+
80+
|File name |Format |
81+
|---|---|
82+
|[trafford_pharmacies.csv](trafford_pharmacies.csv) |CSV |
83+
|[trafford_pharmacies.geojson](trafford_pharmacies.geojson) |GeoJSON |
84+
|[gm_pharmacies.csv](gm_pharmacies.csv) |CSV |
85+
|[gm_pharmacies.geojson](gm_pharmacies.geojson) |GeoJSON |
86+
87+
<h2>Pre-processing</h2>
88+
[The R script used to process the data](pre-processing.R) can be adapted to other areas. For information about R visit the <a href="https://cran.r-project.org" target="_blank">CRAN website</a>.
89+
90+
</main>
91+
92+
<script>
93+
// Fixes to dynamic elements created by DataTables to improve accessibility
94+
var removeElFn = setInterval(removeElement, 1000);
95+
96+
function removeElement() {
97+
try {
98+
var el = document.getElementsByClassName("dataTables_scrollBody")[0].childNodes[0];
99+
el.removeChild(el.childNodes[0]); // Remove unwanted hidden text element from table - causing accessibility alert as it has no label
100+
101+
el.parentNode.setAttribute('tabindex', '0'); // add attribute allowing keyboard users to access scrollable area
102+
103+
clearInterval(removeElFn); // cancel any further calls to this function as we have completed all actions
104+
}
105+
catch(e) {
106+
// form element 'el' doesn't exist yet so setInterval will call the function again until it does
107+
}
108+
}
109+
</script>

pharmacies/index.html

Lines changed: 3425 additions & 0 deletions
Large diffs are not rendered by default.

pharmacies/pre-processing.R

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,60 @@
1-
## Pharmacies in Trafford ##
1+
## Pharmacies in Trafford and Greater Manchester ##
2+
3+
# Source: NHS Business Services Authority (NHSBSA) Master Data Replacement (MDR)
4+
# Publisher URL: https://opendata.nhsbsa.net/dataset/consolidated-pharmaceutical-list
5+
# - Consolidated Pharmaceutical List - 2024-25 Quarter 4
26

3-
# Source: Trafford Council
4-
# Publisher URL: http://www.trafford.gov.uk/about-your-council/children-families-and-wellbeing/children-families-and-wellbeing.aspx
57
# Licence: Open Government Licence
68

7-
# load libraries
9+
# Load required packages ---------------------------
810
library(tidyverse) ; library(sf)
911

10-
# load data ---------------------------
11-
df <- read_csv("trafford_pharmacies.csv")
1212

13-
# load local authorities ---------------------------
14-
la <- st_read("https://github.com/traffordDataLab/spatial_data/raw/master/local_authority/2016/gm_local_authority_full_resolution.geojson") %>%
15-
select(area_code, area_name)
13+
# Load raw data and clean ---------------------------
14+
df_raw <- read_csv("https://opendata.nhsbsa.net/dataset/240d142d-df82-4e97-b051-12371519e4e1/resource/545609ba-8f93-4adf-8f5a-7a34a1a31881/download/consol_pharmacy_list_202425q4.csv")
1615

17-
# match with ONS postcodes ---------------------------
18-
postcodes <- read_csv("https://www.traffordDataLab.io/spatial_data/postcodes/GM_postcodes_2018-02.csv")
19-
df_postcodes <- left_join(df, postcodes, by = "postcode")
16+
df <- df_raw %>%
17+
filter(HEALTH_AND_WELLBEING_BOARD %in% c("BOLTON","BURY","MANCHESTER","OLDHAM","ROCHDALE","SALFORD","STOCKPORT","TAMESIDE","TRAFFORD","WIGAN")) %>%
18+
mutate(address = str_to_title(str_replace_all(paste0(ADDRESS_FIELD_1, ", ", ADDRESS_FIELD_2, ", ", ADDRESS_FIELD_3, ", ", ADDRESS_FIELD_4), ", NA", "")),
19+
HEALTH_AND_WELLBEING_BOARD = str_to_title(HEALTH_AND_WELLBEING_BOARD),
20+
PHARMACY_TRADING_NAME = str_to_title(PHARMACY_TRADING_NAME),
21+
ORGANISATION_NAME = str_to_title(ORGANISATION_NAME)) %>%
22+
arrange(HEALTH_AND_WELLBEING_BOARD, PHARMACY_TRADING_NAME) %>%
23+
select(pharmacy_name = PHARMACY_TRADING_NAME,
24+
address,
25+
postcode = POST_CODE,
26+
opening_hours_monday = PHARMACY_OPENING_HOURS_MONDAY,
27+
opening_hours_tuesday = PHARMACY_OPENING_HOURS_TUESDAY,
28+
opening_hours_wednesday = PHARMACY_OPENING_HOURS_WEDNESDAY,
29+
opening_hours_thursday = PHARMACY_OPENING_HOURS_THURSDAY,
30+
opening_hours_friday = PHARMACY_OPENING_HOURS_FRIDAY,
31+
opening_hours_saturday = PHARMACY_OPENING_HOURS_SATURDAY,
32+
opening_hours_sunday = PHARMACY_OPENING_HOURS_SUNDAY,
33+
organisation_data_service_code = `PHARMACY_ODS_CODE_(F-CODE)`,
34+
health_and_wellbeing_board = HEALTH_AND_WELLBEING_BOARD)
2035

21-
# convert to spatial object and creat spatial join ---------------------------
22-
sf <- df_postcodes %>%
23-
filter(!is.na(lat)) %>%
24-
st_as_sf(coords = c("long", "lat")) %>%
25-
st_set_crs(4326) %>%
26-
st_join(la, join = st_within, left = FALSE)
2736

28-
# write data ---------------------------
29-
write_csv(st_set_geometry(sf, value = NULL), "trafford_pharmacies.csv")
30-
st_write(sf, "trafford_pharmacies.geojson")
37+
# Match pharmacy data with ONS postcodes to obtain spatial coordinates, ward and la information ---------------------------
38+
postcodes <- read_csv("https://www.trafforddatalab.io/spatial_data/postcodes/gm_postcodes.csv") %>%
39+
select(postcode, ward_code, ward_name, la_code, la_name, lon, lat)
40+
41+
df_with_coords <- left_join(df, postcodes, by = "postcode")
3142

3243

44+
# Convert to spatial object ---------------------------
45+
sf <- df_with_coords %>%
46+
filter(!is.na(lat)) %>%
47+
st_as_sf(coords = c("lon", "lat")) %>%
48+
st_set_crs(4326)
49+
3350

51+
# Write data ---------------------------
52+
file.remove(c("gm_pharmacies.geojson",
53+
"trafford_pharmacies.geojson"))
3454

55+
# NOTE: There are a few pharmacies where the value of health_and_wellbeing_board differs from la_name, therefore I'm using the former as the filter.
56+
write_sf(sf, "gm_pharmacies.geojson", driver = "GeoJSON")
57+
write_sf(sf %>% filter(health_and_wellbeing_board == "Trafford"), "trafford_pharmacies.geojson", driver = "GeoJSON")
3558

59+
write_csv(st_set_geometry(sf, value = NULL), "gm_pharmacies.csv")
60+
write_csv(st_set_geometry(sf, value = NULL) %>% filter(health_and_wellbeing_board == "Trafford"), "trafford_pharmacies.csv")

pharmacies/thumbnail.png

-923 KB
Binary file not shown.

0 commit comments

Comments
 (0)