1 About

1.1 Contributions

Please note that authorship is alphabetical. Contributions are listed below - see github for details and who to blame for what :-).

1.3 Citation

If you wish to refer to any of the material from this report please cite as:

  • Anderson, B., (2020) Air Quality in Southampton (UK): Exploring the SSC and AURN data , University of Southampton: Southampton, UK.

Report circulation:

  • Public

Report purpose:

This work is (c) 2020 the University of Southampton.

2 Introduction

Data for Southampton downloaded from :

Southampton City Council collects various forms of air quality data at the sites shown in 2.1. Some of these sites feed data to AURN. The AURN data then undergoes a manual check and ratification process.

WHO publishes information on the health consequences and “acceptable” exposure levels for each of these.

Data health warning

The southampton.my-air.uk data used is not cleaned or tested for measurement error. The AURN from https://uk-air.defra.gov.uk/ has been ratified if it is mroe than 6 months old.

sotonAirDT[, `:=`(obsDate, lubridate::date(dateTimeUTC))]
sotonAirDT[, `:=`(site, ifelse(site == "Southampton A33", "Southampton A33 AURN data", site))]
sotonAirDT[, `:=`(site, ifelse(site == "Southampton Centre", "Southampton Centre AURN data", site))]
t <- sotonAirDT[!is.na(value), .(from = min(dateTimeUTC), to = max(dateTimeUTC), nObs = .N), keyby = .(site, 
    source, pollutant)]

kableExtra::kable(t, caption = "Dates data != NA available by site and measure", digits = 2) %>% kable_styling()
Table 2.1: Dates data != NA available by site and measure
site source pollutant from to nObs
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk no2 2016-01-26 11:00:00 2020-04-03 07:00:00 35525
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk pm10 2016-01-04 13:00:00 2020-04-03 06:00:00 34029
Southampton - Background (near city centre, AURN site) southampton.my-air.uk no2 2016-01-01 00:00:00 2020-04-03 07:00:00 30357
Southampton - Background (near city centre, AURN site) southampton.my-air.uk nox 2016-01-01 00:00:00 2019-01-01 00:00:00 20026
Southampton - Background (near city centre, AURN site) southampton.my-air.uk o3 2016-01-01 00:00:00 2020-04-03 07:00:00 30036
Southampton - Background (near city centre, AURN site) southampton.my-air.uk pm10 2016-01-01 00:00:00 2020-04-03 07:00:00 26611
Southampton - Background (near city centre, AURN site) southampton.my-air.uk pm2.5 2016-01-01 00:00:00 2020-04-03 07:00:00 28819
Southampton - Background (near city centre, AURN site) southampton.my-air.uk so2 2016-01-01 00:00:00 2020-04-03 07:00:00 29851
Southampton - Onslow Road (near RSH) southampton.my-air.uk no2 2016-01-01 00:00:00 2020-03-31 09:00:00 35697
Southampton - Onslow Road (near RSH) southampton.my-air.uk nox 2016-01-01 00:00:00 2020-03-31 09:00:00 35701
Southampton - Victoria Road (Woolston) southampton.my-air.uk no2 2016-01-01 00:00:00 2020-04-01 06:00:00 27533
Southampton - Victoria Road (Woolston) southampton.my-air.uk nox 2016-01-01 00:00:00 2020-04-01 06:00:00 27533
Southampton A33 AURN data AURN no 2016-01-01 00:00:00 2020-04-02 23:00:00 28152
Southampton A33 AURN data AURN no2 2016-01-01 00:00:00 2020-04-02 23:00:00 28150
Southampton A33 AURN data AURN nox 2016-01-01 00:00:00 2020-04-02 23:00:00 28152
Southampton A33 AURN data AURN nv10 2016-03-31 23:00:00 2020-02-20 06:00:00 21319
Southampton A33 AURN data AURN pm10 2016-03-31 23:00:00 2020-04-02 22:00:00 22071
Southampton A33 AURN data AURN v10 2016-03-31 23:00:00 2020-02-20 06:00:00 21316
Southampton A33 AURN data AURN wd 2016-07-21 00:00:00 2020-04-02 23:00:00 23472
Southampton A33 AURN data AURN ws 2016-07-21 00:00:00 2020-04-02 23:00:00 23472
Southampton Centre AURN data AURN no 2016-01-01 00:00:00 2020-04-02 23:00:00 22268
Southampton Centre AURN data AURN no2 2016-01-01 00:00:00 2020-04-02 23:00:00 22268
Southampton Centre AURN data AURN nox 2016-01-01 00:00:00 2020-04-02 23:00:00 22263
Southampton Centre AURN data AURN nv10 2016-01-01 00:00:00 2018-12-31 23:00:00 16602
Southampton Centre AURN data AURN nv2.5 2016-01-01 00:00:00 2018-12-31 23:00:00 18816
Southampton Centre AURN data AURN o3 2016-01-01 00:00:00 2020-04-02 23:00:00 22109
Southampton Centre AURN data AURN pm10 2016-01-01 00:00:00 2020-04-02 23:00:00 18808
Southampton Centre AURN data AURN pm2.5 2016-01-01 00:00:00 2020-04-02 23:00:00 21022
Southampton Centre AURN data AURN so2 2016-01-01 00:00:00 2020-04-02 23:00:00 21723
Southampton Centre AURN data AURN v10 2016-01-01 00:00:00 2018-12-31 23:00:00 16602
Southampton Centre AURN data AURN v2.5 2016-01-01 00:00:00 2018-12-31 23:00:00 18816
Southampton Centre AURN data AURN wd 2016-01-01 00:00:00 2020-04-02 23:00:00 28080
Southampton Centre AURN data AURN ws 2016-01-01 00:00:00 2020-04-02 23:00:00 28080

3 Summarise data

Summarise previously downloaded and processed data… Note that this may not be completely up to date.

t <- sotonAirDT[, .(mean = mean(value, na.rm = TRUE)), keyby = .(site, pollutant, source)]

kableExtra::kable(t, caption = "Mean values per site (NaN indicates not measured)") %>% kable_styling()
Table 3.1: Mean values per site (NaN indicates not measured)
site pollutant source mean
Southampton - A33 Roadside (near docks, AURN site) co southampton.my-air.uk NaN
Southampton - A33 Roadside (near docks, AURN site) no2 southampton.my-air.uk 35.331679
Southampton - A33 Roadside (near docks, AURN site) nox southampton.my-air.uk NaN
Southampton - A33 Roadside (near docks, AURN site) o3 southampton.my-air.uk NaN
Southampton - A33 Roadside (near docks, AURN site) pm10 southampton.my-air.uk 18.994646
Southampton - A33 Roadside (near docks, AURN site) pm2.5 southampton.my-air.uk NaN
Southampton - A33 Roadside (near docks, AURN site) so2 southampton.my-air.uk NaN
Southampton - Background (near city centre, AURN site) co southampton.my-air.uk NaN
Southampton - Background (near city centre, AURN site) no2 southampton.my-air.uk 29.278862
Southampton - Background (near city centre, AURN site) nox southampton.my-air.uk 50.789064
Southampton - Background (near city centre, AURN site) o3 southampton.my-air.uk 41.251658
Southampton - Background (near city centre, AURN site) pm10 southampton.my-air.uk 18.080685
Southampton - Background (near city centre, AURN site) pm2.5 southampton.my-air.uk 12.009050
Southampton - Background (near city centre, AURN site) so2 southampton.my-air.uk 2.998503
Southampton - Bitterne co southampton.my-air.uk NaN
Southampton - Bitterne no2 southampton.my-air.uk NaN
Southampton - Bitterne nox southampton.my-air.uk NaN
Southampton - Bitterne o3 southampton.my-air.uk NaN
Southampton - Bitterne pm10 southampton.my-air.uk NaN
Southampton - Bitterne pm2.5 southampton.my-air.uk NaN
Southampton - Bitterne so2 southampton.my-air.uk NaN
Southampton - Onslow Road (near RSH) co southampton.my-air.uk NaN
Southampton - Onslow Road (near RSH) no2 southampton.my-air.uk 42.253772
Southampton - Onslow Road (near RSH) nox southampton.my-air.uk 87.188250
Southampton - Onslow Road (near RSH) o3 southampton.my-air.uk NaN
Southampton - Onslow Road (near RSH) pm10 southampton.my-air.uk NaN
Southampton - Onslow Road (near RSH) pm2.5 southampton.my-air.uk NaN
Southampton - Onslow Road (near RSH) so2 southampton.my-air.uk NaN
Southampton - Redbridge co southampton.my-air.uk NaN
Southampton - Redbridge no2 southampton.my-air.uk NaN
Southampton - Redbridge nox southampton.my-air.uk NaN
Southampton - Redbridge o3 southampton.my-air.uk NaN
Southampton - Redbridge pm10 southampton.my-air.uk NaN
Southampton - Redbridge pm2.5 southampton.my-air.uk NaN
Southampton - Redbridge so2 southampton.my-air.uk NaN
Southampton - Victoria Road (Woolston) co southampton.my-air.uk NaN
Southampton - Victoria Road (Woolston) no2 southampton.my-air.uk 38.665561
Southampton - Victoria Road (Woolston) nox southampton.my-air.uk 79.539509
Southampton - Victoria Road (Woolston) o3 southampton.my-air.uk NaN
Southampton - Victoria Road (Woolston) pm10 southampton.my-air.uk NaN
Southampton - Victoria Road (Woolston) pm2.5 southampton.my-air.uk NaN
Southampton - Victoria Road (Woolston) so2 southampton.my-air.uk NaN
Southampton A33 AURN data no AURN 36.808106
Southampton A33 AURN data no2 AURN 38.462255
Southampton A33 AURN data nox AURN 94.897643
Southampton A33 AURN data nv10 AURN 16.409489
Southampton A33 AURN data pm10 AURN 19.114816
Southampton A33 AURN data v10 AURN 2.588633
Southampton A33 AURN data wd AURN 202.919913
Southampton A33 AURN data ws AURN 3.766586
Southampton Centre AURN data no AURN 13.140254
Southampton Centre AURN data no2 AURN 29.663491
Southampton Centre AURN data nox AURN 49.822409
Southampton Centre AURN data nv10 AURN 14.406614
Southampton Centre AURN data nv2.5 AURN 8.855697
Southampton Centre AURN data o3 AURN 43.126056
Southampton Centre AURN data pm10 AURN 17.041499
Southampton Centre AURN data pm2.5 AURN 11.184429
Southampton Centre AURN data so2 AURN 1.806094
Southampton Centre AURN data v10 AURN 3.300108
Southampton Centre AURN data v2.5 AURN 3.075356
Southampton Centre AURN data wd AURN 202.964138
Southampton Centre AURN data ws AURN 3.780880

Table 3.1 gives an indication of the availability of the different measures.

4 Analysis

In this section we present graphical analysis of the previoulsy downloaded data. Note this is just a snapshot of the data available.

4.1 Nitrogen Dioxide (no2)

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"As an air pollutant, NO2 has several correlated activities. At short-term, concentrations exceeding 200 μg/m3, it is a toxic gas which causes significant inflammation of the airways.

NO2 is the main source of nitrate aerosols, which form an important fraction of PM2.5 and, in the presence of ultraviolet light, of ozone. The major sources of anthropogenic emissions of NO2 are combustion processes (heating, power generation, and engines in vehicles and ships).

Health effects

Epidemiological studies have shown that symptoms of bronchitis in asthmatic children increase in association with long-term exposure to NO2. Reduced lung function growth is also linked to NO2 at concentrations currently measured (or observed) in cities of Europe and North America."

yLab <- "Nitrogen Dioxide (ug/m3)"
no2dt <- sotonAirDT[pollutant == "no2"]
t <- no2dt[!is.na(value), .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, 
    na.rm = TRUE), max = max(value, na.rm = TRUE), minDate = min(obsDate), maxDate = max(obsDate)), keyby = .(site, 
    source)]
kableExtra::kable(t, caption = "Summary of NO2 data") %>% kable_styling()
Table 4.1: Summary of NO2 data
site source mean sd min max minDate maxDate
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk 35.33168 24.78370 0.00000 164.3000 2016-01-26 2020-04-03
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 29.27886 16.93064 2.30000 144.2000 2016-01-01 2020-04-03
Southampton - Onslow Road (near RSH) southampton.my-air.uk 42.25377 21.18415 1.20000 241.3000 2016-01-01 2020-03-31
Southampton - Victoria Road (Woolston) southampton.my-air.uk 38.66556 23.82376 -1.30000 287.5000 2016-01-01 2020-04-01
Southampton A33 AURN data AURN 38.46225 26.05753 -2.14200 182.4893 2016-01-01 2020-04-02
Southampton Centre AURN data AURN 29.66349 16.95484 1.90581 130.0911 2016-01-01 2020-04-02

Table 4.1 suggests that there may be a few (14) negative values. These are summarised in 4.2 while Figure 4.1 shows the availability and levels of the pollutant data over time.

t <- head(no2dt[value < 0], 10)
kableExtra::kable(t, caption = "Negative NO2 values (up to first 10)") %>% kable_styling()
Table 4.2: Negative NO2 values (up to first 10)
dateTimeUTC pollutant source site value obsDate
2020-01-12 03:00:00 no2 AURN Southampton A33 AURN data -0.05498 2020-01-12
2020-01-15 00:00:00 no2 AURN Southampton A33 AURN data -0.53678 2020-01-15
2020-02-16 00:00:00 no2 AURN Southampton A33 AURN data -0.14599 2020-02-16
2020-02-16 01:00:00 no2 AURN Southampton A33 AURN data -2.03235 2020-02-16
2020-02-16 02:00:00 no2 AURN Southampton A33 AURN data -1.43533 2020-02-16
2020-02-16 03:00:00 no2 AURN Southampton A33 AURN data -1.33110 2020-02-16
2020-02-16 06:00:00 no2 AURN Southampton A33 AURN data -2.14200 2020-02-16
2020-02-16 07:00:00 no2 AURN Southampton A33 AURN data -0.48147 2020-02-16
2020-02-17 02:00:00 no2 AURN Southampton A33 AURN data -1.33540 2020-02-17
2016-01-29 04:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) -0.10000 2016-01-29
t <- table(no2dt[value < 0]$site)
kableExtra::kable(t, caption = "Negative NO2 values (count by site)") %>% kable_styling()
Table 4.2: Negative NO2 values (count by site)
Var1 Freq
Southampton - Victoria Road (Woolston) 5
Southampton A33 AURN data 9
# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(no2dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Nitrogen Dioxide data availability and levels over time

Figure 4.1: Nitrogen Dioxide data availability and levels over time

Figure 4.2 shows daily mean values for all sites over time and includes smoother trend lines for each site.

plotDT <- no2dt[!is.na(value), .(mean = mean(value, na.rm = TRUE)),
             keyby = .(obsDate, site)]

p <- makeDotPlot(plotDT, 
                 xVar = "obsDate", 
                 yVar = "mean", 
                 byVar = "site", 
                 yLab = paste0("Mean daily ", yLab)
                 )

p <- p +
  geom_smooth() + # add smoothed line
  guides(colour = guide_legend(ncol=2)) +
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
addLockdownDate(p)
Nitrogen Dioxide levels, Southampton (daily mean)

Figure 4.2: Nitrogen Dioxide levels, Southampton (daily mean)

plotDT <- no2dt[!is.na(value) & obsDate > myParams$recentCutDate, .(mean = mean(value, na.rm = TRUE)), 
    keyby = .(obsDate, site)]


p <- makeDotPlot(plotDT, xVar = "obsDate", yVar = "mean", byVar = "site", yLab = paste0("Mean daily ", 
    yLab))

p <- p + # geom_smooth(se = FALSE) + # add smoothed line
guides(colour = guide_legend(ncol = 2)) + scale_x_date(date_breaks = "2 day", date_labels = "%a %d %b") + 
    theme(axis.text.x = element_text(angle = 90, hjust = 1)) + labs(caption = paste0(myParams$gamCap, 
    myParams$lockdownCap, myParams$weekendCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
p <- addLockdownDate(p)
addWeekendsDate(p)
Nitrogen Dioxide levels, Southampton (daily mean, recent)

Figure 4.3: Nitrogen Dioxide levels, Southampton (daily mean, recent)

dt <- no2dt[!is.na(value) & dateTimeUTC > myParams$oneYearAgo]

t <- dt[value > myParams$hourlyNo2Threshold_WHO][order(-value)]

kableExtra::kable(caption = paste0("Values greater than WHO threshold (NO2 > ", 
                                   myParams$hourlyNo2Threshold_WHO , ", last 12 months)"), 
                  head(t, 10)) %>%
  kable_styling()
Table 4.3: Values greater than WHO threshold (NO2 > 200, last 12 months)
dateTimeUTC pollutant source site value obsDate
p <- makeDotPlot(dt, 
                 xVar = "dateTimeUTC", 
                 yVar = "value", 
                 byVar = "site", 
                 yLab = yLab)

p <- p + geom_hline(yintercept = myParams$hourlyNo2Threshold_WHO) +
  labs(caption = "Reference line = WHO hourly threshold")


p <- p +
  geom_smooth() + # add smoothed line
  guides(colour = guide_legend(ncol=2)) +
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(dt$value)
yMin <- min(dt$value)
addLockdownDateTime(p)
Nitrogen Dioxide levels, Southampton (hourly, last 12 months)

Figure 4.4: Nitrogen Dioxide levels, Southampton (hourly, last 12 months)

Figure 4.4 shows hourly values for all sites for the last 12 months. In this period there were 0 hours when the hourly Nitrogen Dioxide level breached the relevant WHO hourly threshold (200). The worst 10 cases (if any) are shown in Table 4.3.

Clearly there are spikes, the mean daily values show less variance (and less extremes) than the hourly data and there has also appears to have been a decreasing trend over time since early 2019.

Figure 4.5 shows the most recent hourly data.

recentDT <- no2dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

# final plot - adds annotations
yMin <- min(recentDT$value)
yMax <- max(recentDT$value)

p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Nitrogen Dioxide levels, Southampton (hourly, recent)

Figure 4.5: Nitrogen Dioxide levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

4.2 Oxides of Nitrogen (nox)

yLab <- "Oxides of Nitrogen (ug/m3)"
noxdt <- sotonAirDT[pollutant == "nox"]
t <- noxdt[!is.na(value), .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, 
    na.rm = TRUE), max = max(value, na.rm = TRUE), minDate = min(obsDate), maxDate = max(obsDate)), keyby = .(site, 
    source)]
kableExtra::kable(t, caption = "Summary of NOx data") %>% kable_styling()
Table 4.4: Summary of NOx data
site source mean sd min max minDate maxDate
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 50.78906 53.19406 3.20000 940.9000 2016-01-01 2019-01-01
Southampton - Onslow Road (near RSH) southampton.my-air.uk 87.18825 75.98176 0.60000 1059.6000 2016-01-01 2020-03-31
Southampton - Victoria Road (Woolston) southampton.my-air.uk 79.53951 81.82857 -1.40000 1431.8000 2016-01-01 2020-04-01
Southampton A33 AURN data AURN 94.89764 97.74383 0.19699 1007.7838 2016-01-01 2020-04-02
Southampton Centre AURN data AURN 49.82241 53.37435 2.29213 940.9061 2016-01-01 2020-04-02

Table 4.4 suggests that there may be a few (2) negative values. These are summarised in 4.5 while Figure 4.6 shows the availability and levels of the pollutant data over time.

t <- head(noxdt[value < 0], 10)
kableExtra::kable(t, caption = "Negative NOx values (up to first 10)") %>% kable_styling()
Table 4.5: Negative NOx values (up to first 10)
dateTimeUTC pollutant source site value obsDate
2017-08-19 02:00:00 nox southampton.my-air.uk Southampton - Victoria Road (Woolston) -0.2 2017-08-19
2017-10-18 01:00:00 nox southampton.my-air.uk Southampton - Victoria Road (Woolston) -1.4 2017-10-18
t <- table(noxdt[value < 0]$site)
kableExtra::kable(t, caption = "Negative NOx values (count by site)") %>% kable_styling()
Table 4.5: Negative NOx values (count by site)
Var1 Freq
Southampton - Victoria Road (Woolston) 2
# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(noxdt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Oxides of nitrogen data availability and levels over time

Figure 4.6: Oxides of nitrogen data availability and levels over time

Figure 4.7 shows daily mean values for all sites over time and includes smoother trend lines for each site.

plotDT <- noxdt[!is.na(value), .(mean = mean(value, na.rm = TRUE)),
             keyby = .(obsDate, site)]

p <- makeDotPlot(plotDT, 
                 xVar = "obsDate", 
                 yVar = "mean", 
                 byVar = "site", 
                 yLab = paste0("Mean daily ", yLab)
                 )

p <- p +
  geom_smooth() + # add smoothed line
  guides(colour = guide_legend(ncol=2)) +
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
addLockdownDate(p)
Oxides of nitrogen levels, Southampton (daily mean)

Figure 4.7: Oxides of nitrogen levels, Southampton (daily mean)

plotDT <- noxdt[!is.na(value) & obsDate > myParams$recentCutDate, .(mean = mean(value, na.rm = TRUE)), 
    keyby = .(obsDate, site)]


p <- makeDotPlot(plotDT, xVar = "obsDate", yVar = "mean", byVar = "site", yLab = paste0("Mean daily ", 
    yLab))

p <- p + # geom_smooth(se = FALSE) + # add smoothed line
guides(colour = guide_legend(ncol = 2)) + scale_x_date(date_breaks = "2 day", date_labels = "%a %d %b") + 
    theme(axis.text.x = element_text(angle = 90, hjust = 1)) + labs(caption = paste0(myParams$gamCap, 
    myParams$lockdownCap, myParams$weekendCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
p <- addLockdownDate(p)
addWeekendsDate(p)
Oxides of nitrogen levels, Southampton (daily mean, recent)

Figure 4.8: Oxides of nitrogen levels, Southampton (daily mean, recent)

dt <- noxdt[!is.na(value) & dateTimeUTC > myParams$oneYearAgo]

p <- makeDotPlot(dt, 
                 xVar = "dateTimeUTC", 
                 yVar = "value", 
                 byVar = "site", 
                 yLab = yLab)

p <- p + geom_hline(yintercept = myParams$hourlyNo2Threshold_WHO) +
  labs(caption = "Reference line = WHO hourly threshold")


p <- p +
  geom_smooth() + # add smoothed line
  guides(colour = guide_legend(ncol=2)) +
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(dt$value)
yMin <- min(dt$value)
addLockdownDateTime(p)
Oxides of nitrogen levels, Southampton (hourly, last 12 months)

Figure 4.9: Oxides of nitrogen levels, Southampton (hourly, last 12 months)

Figure 4.4 shows hourly values for all sites for the last 12 months.

Clearly there are peaks, the mean daily values show less variance (and less extremes) than the hourly data but it is difficult to discern any particular trend.

Figure 4.10 shows the most recent hourly data.

recentDT <- noxdt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

# final plot - adds annotations
yMin <- min(recentDT$value)
yMax <- max(recentDT$value)

p <- addLockdownDateTime(p)

addWeekendsDateTime(p)
Oxides of nitrogen levels, Southampton (hourly, recent)

Figure 4.10: Oxides of nitrogen levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

4.3 Sulphour Dioxide

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"SO2 is a colourless gas with a sharp odour. It is produced from the burning of fossil fuels (coal and oil) and the smelting of mineral ores that contain sulfur. The main anthropogenic source of SO2 is the burning of sulfur-containing fossil fuels for domestic heating, power generation and motor vehicles.

Health effects

SO2 can affect the respiratory system and the functions of the lungs, and causes irritation of the eyes. Inflammation of the respiratory tract causes coughing, mucus secretion, aggravation of asthma and chronic bronchitis and makes people more prone to infections of the respiratory tract. Hospital admissions for cardiac disease and mortality increase on days with higher SO2 levels. When SO2 combines with water, it forms sulfuric acid; this is the main component of acid rain which is a cause of deforestation."

yLab <- "Sulphour Dioxide (ug/m3)"
so2dt <- sotonAirDT[pollutant == "so2"]
t <- so2dt[, .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, na.rm = TRUE), 
    max = max(value, na.rm = TRUE)), keyby = .(site)]
kableExtra::kable(t, caption = "Summary of SO2 data") %>% kable_styling()
Table 4.6: Summary of SO2 data
site mean sd min max
Southampton - A33 Roadside (near docks, AURN site) NaN NA Inf -Inf
Southampton - Background (near city centre, AURN site) 2.998503 3.248132 -1.10000 50.50000
Southampton - Bitterne NaN NA Inf -Inf
Southampton - Onslow Road (near RSH) NaN NA Inf -Inf
Southampton - Redbridge NaN NA Inf -Inf
Southampton - Victoria Road (Woolston) NaN NA Inf -Inf
Southampton Centre AURN data 1.806094 1.761465 -3.12656 50.49723

Figure 4.11 shows the availability and levels of the pollutant data over time.

t <- head(so2dt[value < 0], 10)
kableExtra::kable(t, caption = "Negative SO2 values (up to first 10)") %>% kable_styling()
Table 4.7: Negative SO2 values (up to first 10)
dateTimeUTC pollutant source site value obsDate
2020-01-24 03:00:00 so2 AURN Southampton Centre AURN data -0.43905 2020-01-24
2020-01-24 04:00:00 so2 AURN Southampton Centre AURN data -0.29270 2020-01-24
2020-01-24 05:00:00 so2 AURN Southampton Centre AURN data -0.87810 2020-01-24
2020-01-24 06:00:00 so2 AURN Southampton Centre AURN data -0.36587 2020-01-24
2020-01-24 07:00:00 so2 AURN Southampton Centre AURN data -0.21952 2020-01-24
2020-01-24 09:00:00 so2 AURN Southampton Centre AURN data -0.51222 2020-01-24
2020-01-24 10:00:00 so2 AURN Southampton Centre AURN data -0.36587 2020-01-24
2020-02-26 08:00:00 so2 AURN Southampton Centre AURN data -0.19957 2020-02-26
2020-02-26 09:00:00 so2 AURN Southampton Centre AURN data -0.06652 2020-02-26
2020-02-26 20:00:00 so2 AURN Southampton Centre AURN data -0.66523 2020-02-26
t <- table(so2dt[value < 0]$site)
kableExtra::kable(t, caption = "Negative SO2 values (count by site)") %>% kable_styling()
Table 4.7: Negative SO2 values (count by site)
Var1 Freq
Southampton - Background (near city centre, AURN site) 14
Southampton Centre AURN data 27
# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(so2dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Sulphour Dioxide data availability and levels over time

Figure 4.11: Sulphour Dioxide data availability and levels over time

Figure 4.12 shows daily mean values for all sites over time and includes smoother trend lines for each site. The plot looks a bit odd… sensor issues?

plotDT <- so2dt[!is.na(value), .(mean = mean(value, na.rm = TRUE)),
             keyby = .(obsDate, site)]

p <- makeDotPlot(plotDT, 
                 xVar = "obsDate", 
                 yVar = "mean", 
                 byVar = "site", 
                 yLab = paste0("Mean daily ", yLab)
                 )

# dailySo2Threshold_WHO

p <- p + geom_hline(yintercept = myParams$dailySo2Threshold_WHO) +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
addLockdownDate(p)
Sulphour Dioxide levels, Southampton (daily mean

Figure 4.12: Sulphour Dioxide levels, Southampton (daily mean

plotDT <- so2dt[!is.na(value) & obsDate > myParams$recentCutDate, .(mean = mean(value, na.rm = TRUE)), 
    keyby = .(obsDate, site)]

p <- makeDotPlot(plotDT, xVar = "obsDate", yVar = "mean", byVar = "site", yLab = paste0("Mean daily ", 
    yLab))

# dailySo2Threshold_WHO

p <- p + geom_hline(yintercept = myParams$dailySo2Threshold_WHO) + scale_x_date(date_breaks = "2 day", 
    date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, hjust = 1)) + labs(caption = paste0(myParams$gamCap, 
    myParams$lockdownCap, myParams$weekendCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
p <- addLockdownDate(p)
addWeekendsDate(p)
Sulphour Dioxide levels, Southampton (daily mean, recent)

Figure 4.13: Sulphour Dioxide levels, Southampton (daily mean, recent)

There is no hourly SO2 threshold - it is 10 minutes (500).

so2dt <- so2dt[dateTimeUTC > myParams$oneYearAgo]

# t <- so2dt[value > myParams$myParams$tenMSo2Threshold_WHO][order(-value)]
# 
# kableExtra::kable(caption = paste0("Values greater than WHO 10 minute threshold (SO2 > ", 
#                                    myParams$tenMSo2Threshold_WHO , ", last 12 months)"), 
#                   head(t, 10)) %>%
#   kable_styling()


p <- makeDotPlot(so2dt[!is.na(value)], 
                 xVar = "dateTimeUTC", 
                 yVar = "value", 
                 byVar = "site", 
                 yLab = yLab)

p <- p +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(plotDT$value)
yMin <- min(plotDT$value)
p <- addLockdownDateTime(p)
p
Sulphour Dioxide levels, Southampton (hourly, last 12 months)

Figure 4.14: Sulphour Dioxide levels, Southampton (hourly, last 12 months)

Figure 4.15 shows the most recent hourly data.

recentDT <- so2dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Sulphour Dioxide levels, Southampton (hourly, recent)

Figure 4.15: Sulphour Dioxide levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

4.4 Ozone

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"Ozone at ground level – not to be confused with the ozone layer in the upper atmosphere – is one of the major constituents of photochemical smog. It is formed by the reaction with sunlight (photochemical reaction) of pollutants such as nitrogen oxides (NOx) from vehicle and industry emissions and volatile organic compounds (VOCs) emitted by vehicles, solvents and industry. As a result, the highest levels of ozone pollution occur during periods of sunny weather. Health effects

Excessive ozone in the air can have a marked effect on human health. It can cause breathing problems, trigger asthma, reduce lung function and cause lung diseases. "

yLab <- "Ozone (ug/m3)"
o3dt <- sotonAirDT[pollutant == "o3"]

t <- o3dt[, .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, na.rm = TRUE), 
    max = max(value, na.rm = TRUE)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Summary of o3 data") %>% kable_styling()
Table 4.8: Summary of o3 data
site source mean sd min max
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk NaN NA Inf -Inf
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 41.25166 23.24360 -0.20000 174.1000
Southampton - Bitterne southampton.my-air.uk NaN NA Inf -Inf
Southampton - Onslow Road (near RSH) southampton.my-air.uk NaN NA Inf -Inf
Southampton - Redbridge southampton.my-air.uk NaN NA Inf -Inf
Southampton - Victoria Road (Woolston) southampton.my-air.uk NaN NA Inf -Inf
Southampton Centre AURN data AURN 43.12606 24.20263 -0.19957 174.1041

Table 4.13 suggests that there may be a few (6) negative values. These are shown in 4.14 while 4.21 shows data availability and PM 10 levels over time at each site.

t <- head(o3dt[value < 0], nrow(o3dt[value < 0]))
kableExtra::kable(head(t), caption = "Negative 03 values - first 6") %>% kable_styling()
Table 4.9: Negative 03 values - first 6
dateTimeUTC pollutant source site value obsDate
2018-09-25 03:00:00 o3 AURN Southampton Centre AURN data -0.14968 2018-09-25
2018-09-25 04:00:00 o3 AURN Southampton Centre AURN data -0.19957 2018-09-25
2018-09-25 05:00:00 o3 AURN Southampton Centre AURN data -0.09979 2018-09-25
2018-09-25 03:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) -0.10000 2018-09-25
2018-09-25 04:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) -0.20000 2018-09-25
2018-09-25 05:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) -0.10000 2018-09-25
p <- makeTilePlot(o3dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Availability and level of o3 data over time

Figure 4.16: Availability and level of o3 data over time

plotDT <- o3dt[!is.na(value), .(mean = mean(value, na.rm = TRUE)),
             keyby = .(obsDate, site)]

extreme03Daily <- plotDT[mean > myParams$dailyO3Threshold_WHO][order(-mean)]

kableExtra::kable(caption = paste0("10 highest values greater than WHO threshold (PM 10 > ", 
                                   myParams$dailyO3Threshold_WHO , ")"), 
                  digits = 2,
                  head(extreme03Daily, 10)) %>%
  kable_styling()
Table 4.10: 10 highest values greater than WHO threshold (PM 10 > 100)
obsDate site mean
2018-07-02 Southampton Centre AURN data 112.95
2018-07-02 Southampton - Background (near city centre, AURN site) 112.94
2018-07-01 Southampton Centre AURN data 109.95
2018-07-01 Southampton - Background (near city centre, AURN site) 109.95
p <- makeDotPlot(plotDT, 
                 xVar = "obsDate", 
                 yVar = "mean", 
                 byVar = "site", 
                 yLab = paste0("Mean daily ", yLab)
                 )

p <- p + 
  geom_hline(yintercept = myParams$dailyO3Threshold_WHO) +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(plotDT$value)
yMin <- min(plotDT$value)
addLockdownDate(p)
03 levels, Southampton (daily mean)

Figure 4.17: 03 levels, Southampton (daily mean)

nDaysOverThreshold <- uniqueN(extreme03Daily$obsDate)
nDays <- uniqueN(plotDT$obsDate) # need to count days not site-days

Figure 4.22 shows daily values for all sites across the entire dataset and indicates the 2 days (0.2%) that breached the WHO PM10 daily mean exposure threshold (50) - see Table 4.15.

plotDT <- o3dt[!is.na(value) & obsDate > myParams$recentCutDate, .(mean = mean(value, na.rm = TRUE)), 
    keyby = .(obsDate, site)]

extreme03Daily <- plotDT[mean > myParams$dailyO3Threshold_WHO][order(-mean)]

kableExtra::kable(caption = paste0("10 highest values greater than WHO threshold (PM 10 > ", myParams$dailyO3Threshold_WHO, 
    ")"), digits = 2, head(extreme03Daily, 10)) %>% kable_styling()
Table 4.11: 10 highest values greater than WHO threshold (PM 10 > 100)
obsDate site mean
p <- makeDotPlot(plotDT, xVar = "obsDate", yVar = "mean", byVar = "site", yLab = paste0("Mean daily ", 
    yLab))

p <- p + scale_x_date(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
p <- addLockdownDate(p)
addWeekendsDate(p)
03 levels, Southampton (daily mean, recent)

Figure 4.18: 03 levels, Southampton (daily mean, recent)

nDaysOverThreshold <- uniqueN(extreme03Daily$obsDate)
nDays <- uniqueN(plotDT$obsDate)  # need to count days not site-days
o31yeardt <- o3dt[dateTimeUTC > myParams$oneYearAgo]
t <- o31yeardt[value > 100][order(-value)]

kableExtra::kable(caption = "10 highest hourly values (o3 > 100)", head(t)) %>%
  kable_styling()
Table 4.12: 10 highest hourly values (o3 > 100)
dateTimeUTC pollutant source site value obsDate
2019-06-29 16:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 134.7 2019-06-29
2019-06-29 15:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 132.7 2019-06-29
2019-06-29 18:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 131.1 2019-06-29
2019-07-25 13:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 127.3 2019-07-25
2019-06-29 14:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 127.1 2019-06-29
2019-08-24 13:00:00 o3 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 126.5 2019-08-24
p <- makeDotPlot(o31yeardt[!is.na(value)], 
                 xVar = "dateTimeUTC", 
                 yVar = "value", 
                 byVar = "site", 
                 yLab = yLab)

p <- p + labs(caption = "NB: There is no WHO o3 hourly threshold")

p <- p +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMax <- max(o31yeardt$value, na.rm = TRUE)
yMin <- min(o31yeardt$value, na.rm = TRUE)
addLockdownDateTime(p)
o3 levels, Southampton (hourly, last 12 months)

Figure 4.19: o3 levels, Southampton (hourly, last 12 months)

Figure 4.24 shows hourly PM 10 values for all sites over the last 12 months and suggests there may be outliers (see Table 4.17).

Figure 4.20 shows the most recent hourly data.

recentDT <- o3dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
03 levels, Southampton (hourly, recent)

Figure 4.20: 03 levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

4.5 PM 10

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"PM is a common proxy indicator for air pollution. It affects more people than any other pollutant. The major components of PM are sulfate, nitrates, ammonia, sodium chloride, black carbon, mineral dust and water. It consists of a complex mixture of solid and liquid particles of organic and inorganic substances suspended in the air. While particles with a diameter of 10 microns or less, (≤ PM10) can penetrate and lodge deep inside the lungs, the even more health-damaging particles are those with a diameter of 2.5 microns or less, (≤ PM2.5). PM2.5 can penetrate the lung barrier and enter the blood system. Chronic exposure to particles contributes to the risk of developing cardiovascular and respiratory diseases, as well as of lung cancer.

There is a close, quantitative relationship between exposure to high concentrations of small particulates (PM10 and PM2.5) and increased mortality or morbidity, both daily and over time. Conversely, when concentrations of small and fine particulates are reduced, related mortality will also go down – presuming other factors remain the same. This allows policy-makers to project the population health improvements that could be expected if particulate air pollution is reduced."

PM 10 data: has more sensors and wider coverage than PM2.5

yLab <- "PM 10 (ug/m3)"
pm10dt <- sotonAirDT[pollutant == "pm10"]

t <- pm10dt[, .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, na.rm = TRUE), 
    max = max(value, na.rm = TRUE)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Summary of pm10 data") %>% kable_styling()
Table 4.13: Summary of pm10 data
site source mean sd min max
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk 18.99465 14.22679 0.0 761.6
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 18.08068 11.32020 -3.5 344.1
Southampton - Bitterne southampton.my-air.uk NaN NA Inf -Inf
Southampton - Onslow Road (near RSH) southampton.my-air.uk NaN NA Inf -Inf
Southampton - Redbridge southampton.my-air.uk NaN NA Inf -Inf
Southampton - Victoria Road (Woolston) southampton.my-air.uk NaN NA Inf -Inf
Southampton A33 AURN data AURN 19.11482 12.07895 -3.2 122.3
Southampton Centre AURN data AURN 17.04150 11.08975 -4.7 344.1

Table 4.13 suggests that there may be a few (84) negative values. These are shown in 4.14 while 4.21 shows data availability and PM 10 levels over time at each site.

t <- head(pm10dt[value < 0], nrow(pm10dt[value < 0]))
kableExtra::kable(head(t), caption = "Negative PM10 values - first 6") %>% kable_styling()
Table 4.14: Negative PM10 values - first 6
dateTimeUTC pollutant source site value obsDate
2020-02-02 04:00:00 pm10 AURN Southampton A33 AURN data -1.4 2020-02-02
2018-01-02 12:00:00 pm10 AURN Southampton Centre AURN data -0.4 2018-01-02
2018-09-11 00:00:00 pm10 AURN Southampton Centre AURN data -2.3 2018-09-11
2018-09-12 00:00:00 pm10 AURN Southampton Centre AURN data -4.6 2018-09-12
2018-09-12 01:00:00 pm10 AURN Southampton Centre AURN data -0.4 2018-09-12
2018-09-12 03:00:00 pm10 AURN Southampton Centre AURN data -1.0 2018-09-12
p <- makeTilePlot(pm10dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Availability and level of PM 10 data over time

Figure 4.21: Availability and level of PM 10 data over time

plotDT <- pm10dt[!is.na(value), .(mean = mean(value, na.rm = TRUE)),
             keyby = .(obsDate, site)]

extremePm10Daily <- plotDT[mean > myParams$dailyPm10Threshold_WHO][order(-mean)]

kableExtra::kable(caption = paste0("10 highest values greater than WHO threshold (PM 10 > ", 
                                   myParams$dailyPm10Threshold_WHO , ")"), 
                  digits = 2,
                  head(extremePm10Daily, 10)) %>%
  kable_styling()
Table 4.15: 10 highest values greater than WHO threshold (PM 10 > 50)
obsDate site mean
2016-08-09 Southampton - A33 Roadside (near docks, AURN site) 144.48
2017-06-19 Southampton - A33 Roadside (near docks, AURN site) 143.66
2017-05-05 Southampton - A33 Roadside (near docks, AURN site) 88.94
2016-09-19 Southampton - A33 Roadside (near docks, AURN site) 88.46
2016-11-30 Southampton - A33 Roadside (near docks, AURN site) 79.25
2016-03-12 Southampton - A33 Roadside (near docks, AURN site) 72.00
2017-01-22 Southampton - A33 Roadside (near docks, AURN site) 66.86
2017-01-22 Southampton A33 AURN data 66.86
2019-02-27 Southampton - Background (near city centre, AURN site) 64.67
2019-02-27 Southampton - A33 Roadside (near docks, AURN site) 60.60
p <- makeDotPlot(plotDT, 
                 xVar = "obsDate", 
                 yVar = "mean", 
                 byVar = "site", 
                 yLab = paste0("Mean daily ", yLab)
                 )

p <- p + 
  geom_hline(yintercept = myParams$dailyPm10Threshold_WHO) +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap))

yMin <- min(plotDT$value)
yMax <- max(plotDT$value)
addLockdownDate(p)
PM10 levels, Southampton (daily mean)

Figure 4.22: PM10 levels, Southampton (daily mean)

nDaysOverThreshold <- uniqueN(extremePm10Daily$obsDate)
nDays <- uniqueN(plotDT$obsDate) # need to count days not site-days

Figure 4.22 shows daily values for all sites across the entire dataset and indicates the 19 days (1.3%) that breached the WHO PM10 daily mean exposure threshold (50) - see Table 4.15.

plotDT <- pm10dt[!is.na(value) & obsDate > myParams$recentCutDate, .(mean = mean(value, na.rm = TRUE)), 
    keyby = .(obsDate, site)]

extremePm10Daily <- plotDT[mean > myParams$dailyPm10Threshold_WHO][order(-mean)]

kableExtra::kable(caption = paste0("10 highest values greater than WHO threshold (PM 10 > ", myParams$dailyPm10Threshold_WHO, 
    ")"), digits = 2, head(extremePm10Daily, 10)) %>% kable_styling()
Table 4.16: 10 highest values greater than WHO threshold (PM 10 > 50)
obsDate site mean
p <- makeDotPlot(plotDT, xVar = "obsDate", yVar = "mean", byVar = "site", yLab = paste0("Mean daily ", 
    yLab))

p <- p + geom_hline(yintercept = myParams$dailyPm10Threshold_WHO) + scale_x_date(date_breaks = "2 day", 
    date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, 
    "\nReference line = WHO PM10 mean daily threshold"))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
p <- addLockdownDate(p)
addWeekendsDate(p)
PM10 levels, Southampton (daily mean, recent)

Figure 4.23: PM10 levels, Southampton (daily mean, recent)

nDaysOverThreshold <- uniqueN(extremePm10Daily$obsDate)
nDays <- uniqueN(plotDT$obsDate)  # need to count days not site-days
pm101yeardt <- pm10dt[!is.na(value) & dateTimeUTC > myParams$oneYearAgo]
t <- pm101yeardt[value > 100][order(-value)]

kableExtra::kable(caption = "10 highest hourly values (PM 10 > 100)", head(t)) %>%
  kable_styling()
Table 4.17: 10 highest hourly values (PM 10 > 100)
dateTimeUTC pollutant source site value obsDate
2019-10-27 20:00:00 pm10 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 252.5 2019-10-27
2019-12-02 19:00:00 pm10 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 174.6 2019-12-02
2019-10-27 19:00:00 pm10 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 162.2 2019-10-27
2019-12-02 18:00:00 pm10 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 114.3 2019-12-02
2019-12-02 21:00:00 pm10 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 109.1 2019-12-02
p <- makeDotPlot(pm101yeardt[!is.na(value)], 
                 xVar = "dateTimeUTC", 
                 yVar = "value", 
                 byVar = "site", 
                 yLab = yLab)

p <- p + labs(caption = "")

p <- p +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap,myParams$lockdownCap, 
                        "\nNB: There is no WHO PM10 hourly threshold"))

yMax <- max(pm101yeardt$value, na.rm = TRUE)
yMin <- min(pm101yeardt$value, na.rm = TRUE)
addLockdownDateTime(p)
PM10 levels, Southampton (hourly, last 12 months)

Figure 4.24: PM10 levels, Southampton (hourly, last 12 months)

Figure 4.24 shows hourly PM 10 values for all sites over the last 12 months and suggests there may be outliers (see Table 4.17).

Figure 4.25 shows the most recent hourly data.

recentDT <- pm10dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
PM10 levels, Southampton (hourly, recent)

Figure 4.25: PM10 levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

4.6 PM 2.5

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

“Small particulate pollution has health impacts even at very low concentrations – indeed no threshold has been identified below which no damage to health is observed. Therefore, the WHO 2005 guideline limits aimed to achieve the lowest concentrations of PM possible.”

yLab <- "PM 2.5 (ug/m3)"
pm25dt <- sotonAirDT[pollutant == "pm2.5"]
t <- dt[!is.na(value), .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, 
    na.rm = TRUE), max = max(value, na.rm = TRUE)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Summary of pm2.5 data") %>% kable_styling()
Table 4.18: Summary of pm2.5 data
site source mean sd min max
Southampton - Onslow Road (near RSH) southampton.my-air.uk 72.56027 61.30777 4.60000 636.1000
Southampton - Victoria Road (Woolston) southampton.my-air.uk 54.52237 58.10140 1.10000 848.1000
Southampton A33 AURN data AURN 69.56498 68.59654 0.19699 536.7503
Southampton Centre AURN data AURN 41.97340 54.64460 2.29213 855.6162

Table 4.18 suggests that there may be a few (246) negative values. These are shown in Table 4.19 while Figure 4.26 shows data availability and PM 2.5 levels over time at each site.

t <- head(pm25dt[value < 0], nrow(pm25dt))
kableExtra::kable(head(t), caption = "Negative pm2.5 values - first 6") %>% kable_styling()
Table 4.19: Negative pm2.5 values - first 6
dateTimeUTC pollutant source site value obsDate
2018-01-01 13:00:00 pm2.5 AURN Southampton Centre AURN data -3.0 2018-01-01
2018-01-01 14:00:00 pm2.5 AURN Southampton Centre AURN data -2.9 2018-01-01
2018-01-05 15:00:00 pm2.5 AURN Southampton Centre AURN data -0.9 2018-01-05
2018-01-15 07:00:00 pm2.5 AURN Southampton Centre AURN data -4.0 2018-01-15
2018-01-18 14:00:00 pm2.5 AURN Southampton Centre AURN data -0.8 2018-01-18
2018-01-18 15:00:00 pm2.5 AURN Southampton Centre AURN data -0.9 2018-01-18
p <- makeTilePlot(pm25dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Availability and level of PM 10 data over time

Figure 4.26: Availability and level of PM 10 data over time

plotDT <- pm25dt[!is.na(value), .(mean = mean(value, na.rm = TRUE)),
             keyby = .(obsDate, site)]

extremePm25Daily <- plotDT[mean > myParams$dailyPm2.5Threshold_WHO][order(-mean)]

kableExtra::kable(caption = paste0("6 highest values greater than WHO threshold (PM 2.5 > ", 
                                   myParams$dailyPm2.5Threshold_WHO , ")"), 
                  digits = 2,
                  head(extremePm25Daily)) %>%
  kable_styling()
Table 4.20: 6 highest values greater than WHO threshold (PM 2.5 > 25)
obsDate site mean
2016-03-12 Southampton - Background (near city centre, AURN site) 64.79
2016-03-12 Southampton Centre AURN data 64.79
2019-04-17 Southampton - Background (near city centre, AURN site) 49.04
2016-03-13 Southampton - Background (near city centre, AURN site) 47.79
2016-03-13 Southampton Centre AURN data 47.79
2019-04-07 Southampton - Background (near city centre, AURN site) 46.90
p <- makeDotPlot(plotDT, 
                 xVar = "obsDate", 
                 yVar = "mean", 
                 byVar = "site", 
                 yLab = paste0("Mean daily ", yLab)
                 )

p <- p + 
  geom_hline(yintercept = myParams$dailyPm2.5Threshold_WHO) +
  geom_smooth() + #add smoothed line
  labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, "\nReference line = WHO PM2.5 mean daily threshold"))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
addLockdownDate(p)
PM2.5 levels, Southampton (daily mean)

Figure 4.27: PM2.5 levels, Southampton (daily mean)

nDaysOverThreshold <- uniqueN(extremePm25Daily$obsDate)
nDays <- uniqueN(plotDT$obsDate) # need to count days not site-days

Figure 4.27 shows daily values for all sites across the dataset and indicates that the WHO PM2_5 daily mean exposure threshold (25) was breached on 85 days (6.9 %). The 6 worst cases are shown in Table 4.20.

plotDT <- pm25dt[!is.na(value) & obsDate > myParams$recentCutDate, .(mean = mean(value, na.rm = TRUE)), 
    keyby = .(obsDate, site)]

extremePm25Daily <- plotDT[mean > myParams$dailyPm2.5Threshold_WHO][order(-mean)]

kableExtra::kable(caption = paste0("6 highest values greater than WHO threshold (PM 2.5 > ", myParams$dailyPm2.5Threshold_WHO, 
    ")"), digits = 2, head(extremePm25Daily)) %>% kable_styling()
Table 4.21: 6 highest values greater than WHO threshold (PM 2.5 > 25)
obsDate site mean
2020-03-27 Southampton - Background (near city centre, AURN site) 35.09
2020-03-27 Southampton Centre AURN data 33.10
2020-03-26 Southampton - Background (near city centre, AURN site) 30.95
2020-03-26 Southampton Centre AURN data 29.20
p <- makeDotPlot(plotDT, xVar = "obsDate", yVar = "mean", byVar = "site", yLab = paste0("Mean daily ", 
    yLab))

p <- p + geom_hline(yintercept = myParams$dailyPm2.5Threshold_WHO) + scale_x_date(date_breaks = "2 day", 
    date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, 
    myParams$weekendCap, "\nReference line = WHO daily PM2.5 threshold"))

yMax <- max(plotDT$mean)
yMin <- min(plotDT$mean)
p <- addLockdownDate(p)
addWeekendsDate(p)
PM2.5 levels, Southampton (daily mean, recent)

Figure 4.28: PM2.5 levels, Southampton (daily mean, recent)

nDaysOverThreshold <- uniqueN(extremePm25Daily$obsDate)
nDays <- uniqueN(plotDT$obsDate)  # need to count days not site-days
dt <- pm25dt[!is.na(value) & dateTimeUTC > myParams$oneYearAgo]
t <- pm25dt[value > 50][order(-value)]

kableExtra::kable(caption = "Extreme hourly values (PM 2.5 > 50, last 12 months, worst 6)", head(t)) %>%
  kable_styling()
Table 4.22: Extreme hourly values (PM 2.5 > 50, last 12 months, worst 6)
dateTimeUTC pollutant source site value obsDate
2016-01-01 00:00:00 pm2.5 AURN Southampton Centre AURN data 289.2 2016-01-01
2016-01-01 00:00:00 pm2.5 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 289.2 2016-01-01
2019-10-27 20:00:00 pm2.5 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 239.1 2019-10-27
2019-12-02 19:00:00 pm2.5 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 167.6 2019-12-02
2016-01-01 01:00:00 pm2.5 AURN Southampton Centre AURN data 141.8 2016-01-01
2016-01-01 01:00:00 pm2.5 southampton.my-air.uk Southampton - Background (near city centre, AURN site) 141.8 2016-01-01
p <- makeDotPlot(dt[!is.na(value)], 
                 xVar = "dateTimeUTC", 
                 yVar = "value", 
                 byVar = "site", 
                 yLab = yLab)

p <- p +
  geom_smooth() + # add smoothed line
  labs(caption = paste0(myParams$gamCap, "\nNB: There is no WHO PM2.5 hourly threshold"))

yMax <- max(dt$value)
yMin <- min(dt$value)
addLockdownDateTime(p)
PM2_5 levels, Southampton (hourly, last 12 months)

Figure 4.29: PM2_5 levels, Southampton (hourly, last 12 months)

Figure 4.29 shows hourly values for all sites for the last 12 months while Table 4.22 reports the 6 worst hours.

Figure 4.30 shows the most recent hourly data.

recentDT <- pm25dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$weekendCap, "\nNB: There is no WHO PM2.5 hourly threshold"))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
PM2.5 levels, Southampton (hourly, recent)

Figure 4.30: PM2.5 levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

5 Observations

  • Why are there large data holes? (see tile plots)
  • Nitorgen Dioxide levels appear to be trending downwards
  • For particulates the trend is more complex and the trends for PM10 and PM2.5 differ.
    • Something happened on the 27th October 2019 at 20:00. There are spikes on all hourly PM plots (although this is masked in the daily plots). Could it have been a cruise ship leaving?
    • Something else happened on the 2nd December 2019 at 21:00. Was this another ship?

6 Annex

6.1 Original SSC data

skimr::skim(lDT)
Table 6.1: Data summary
Name lDT
Number of rows 1836786
Number of columns 7
_______________________
Column type frequency:
character 3
Date 1
factor 1
numeric 1
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
site 0 1 22 54 0 6 0
source 0 1 21 21 0 1 0
pollutant 0 1 2 5 0 7 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
obsDate 0 1 2016-01-01 2020-12-31 2018-07-02 1827

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
variable 0 1 FALSE 7 co: 262398, no2: 262398, nox: 262398, oz: 262398

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
value 1475068 0.2 38.26 45.79 -4 12.5 26.9 49.5 1431.8 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dateTimeUTC 0 1 2016-01-01 2020-12-31 2018-07-02 43733

6.2 Original AURN data

skimr::skim(aurnDT)
Table 6.2: Data summary
Name aurnDT
Number of rows 701712
Number of columns 8
_______________________
Column type frequency:
character 5
Date 1
numeric 1
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
date 0 1 20 20 0 35088 0
code 0 1 4 4 0 2 0
site 0 1 15 18 0 2 0
pollutant 0 1 2 5 0 13 0
source 0 1 4 4 0 1 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
obsDate 0 1 2016-01-01 2020-12-31 2017-11-27 1462

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
value 228151 0.67 43.08 76.31 -9.6 3.98 12.7 39.13 1007.78 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dateTimeUTC 0 1 2016-01-01 2020-12-31 23:00:00 2017-11-27 03:00:00 35088

6.3 Nitrogen Dioxide

t <- sotonAirDT[pollutant == "no2"]

skimr::skim(t)
Table 6.3: Data summary
Name t
Number of rows 332574
Number of columns 6
_______________________
Column type frequency:
character 3
Date 1
numeric 1
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
pollutant 0 1 3 3 0 1 0
source 0 1 4 21 0 2 0
site 0 1 22 54 0 8 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
obsDate 0 1 2016-01-01 2020-12-31 2018-05-17 1827

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
value 153044 0.54 35.98 22.6 -2.14 19.2 31.8 48 287.5 ▇▂▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dateTimeUTC 0 1 2016-01-01 2020-12-31 23:00:00 2018-05-17 12:00:00 43825
t <- sotonAirDT[pollutant == "no2" & value > myParams$hourlyNo2Threshold_WHO][order(-value)]

kableExtra::kable(caption = paste0("Values greater than WHO threshold (NO2 > ", myParams$hourlyNo2Threshold_WHO, 
    ")"), t) %>% kable_styling()
Table 6.4: Values greater than WHO threshold (NO2 > 200)
dateTimeUTC pollutant source site value obsDate
2016-11-30 17:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 287.5 2016-11-30
2016-11-30 19:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 275.3 2016-11-30
2016-11-30 18:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 268.7 2016-11-30
2017-01-05 18:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 251.6 2017-01-05
2017-01-05 17:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 247.3 2017-01-05
2017-01-24 18:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 243.5 2017-01-24
2017-01-24 19:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 242.0 2017-01-24
2016-03-08 09:00:00 no2 southampton.my-air.uk Southampton - Onslow Road (near RSH) 241.3 2016-03-08
2017-01-03 08:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 234.4 2017-01-03
2017-01-03 09:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 232.8 2017-01-03
2017-01-05 19:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 226.6 2017-01-05
2016-11-30 16:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 222.6 2016-11-30
2016-12-29 09:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 218.7 2016-12-29
2016-03-08 08:00:00 no2 southampton.my-air.uk Southampton - Onslow Road (near RSH) 216.0 2016-03-08
2017-01-05 20:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 214.3 2017-01-05
2017-01-24 20:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 212.7 2017-01-24
2016-11-30 09:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 209.9 2016-11-30
2016-03-12 22:00:00 no2 southampton.my-air.uk Southampton - Onslow Road (near RSH) 208.5 2016-03-12
2016-03-08 07:00:00 no2 southampton.my-air.uk Southampton - Onslow Road (near RSH) 208.1 2016-03-08
2016-11-30 20:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 207.0 2016-11-30
2016-02-19 08:00:00 no2 southampton.my-air.uk Southampton - Onslow Road (near RSH) 206.3 2016-02-19
2016-01-19 19:00:00 no2 southampton.my-air.uk Southampton - Victoria Road (Woolston) 204.4 2016-01-19
2016-03-21 08:00:00 no2 southampton.my-air.uk Southampton - Onslow Road (near RSH) 202.8 2016-03-21

6.4 PM 10

t <- sotonAirDT[pollutant == "pm10"]

skimr::skim(t)
Table 6.5: Data summary
Name t
Number of rows 332574
Number of columns 6
_______________________
Column type frequency:
character 3
Date 1
numeric 1
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
pollutant 0 1 4 4 0 1 0
source 0 1 4 21 0 2 0
site 0 1 22 54 0 8 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
obsDate 0 1 2016-01-01 2020-12-31 2018-05-17 1827

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
value 231055 0.31 18.42 12.51 -4.7 10.6 15.6 23 761.6 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dateTimeUTC 0 1 2016-01-01 2020-12-31 23:00:00 2018-05-17 12:00:00 43825
kableExtra::kable(caption = paste0("PM 10 values greater than WHO threshold (NO2 > ", myParams$dailyPm10Threshold_WHO, 
    ")"), extremePm10Daily) %>% kable_styling()
Table 6.6: PM 10 values greater than WHO threshold (NO2 > 50)
obsDate site mean

6.5 PM 2.5

t <- sotonAirDT[pollutant == "pm2.5"]

skimr::skim(t)
Table 6.7: Data summary
Name t
Number of rows 297486
Number of columns 6
_______________________
Column type frequency:
character 3
Date 1
numeric 1
POSIXct 1
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
pollutant 0 1 5 5 0 1 0
source 0 1 4 21 0 2 0
site 0 1 22 54 0 7 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
obsDate 0 1 2016-01-01 2020-12-31 2018-06-06 1827

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
value 247645 0.17 11.66 9.37 -4.9 6.1 9.1 14 289.2 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
dateTimeUTC 0 1 2016-01-01 2020-12-31 23:00:00 2018-06-06 43825
kableExtra::kable(caption = paste0("PM 2.5 values greater than WHO threshold (NO2 > ", myParams$dailyPm2.5Threshold_WHO, 
    ")"), extremePm25Daily) %>% kable_styling()
Table 6.8: PM 2.5 values greater than WHO threshold (NO2 > 25)
obsDate site mean
2020-03-27 Southampton - Background (near city centre, AURN site) 35.08750
2020-03-27 Southampton Centre AURN data 33.10154
2020-03-26 Southampton - Background (near city centre, AURN site) 30.95000
2020-03-26 Southampton Centre AURN data 29.19821

6.6 What correlates with what?

Basic pairs analysis

wideDT <- data.table::dcast(sotonAirDT[!is.na(value)], # drop data cells with value = NA
                dateTimeUTC + site ~ pollutant, value.var = "value")

#pairs(wideDT[, .(no,no2,nox,so2,o3,pm10,pm2.5)])

library("GGally") 
# https://ggobi.github.io/ggally/#columns_and_mapping
GGally::ggpairs(wideDT, 
                columns = c("no","no2","nox","so2","o3","pm10","pm2.5"),
                aes(color = site)
                )

# pm10DT <- sotonAirDT[pollutant == "pm10"]
# pm10DT[, pm10 := value]
# setkey(pm10DT, dateTimeUTC, site, obsDate)
# pm25DT <- sotonAirDT[pollutant == "pm2.5"]
# pm25DT[, pm25 := value]
# setkey(pm25DT, dateTimeUTC, site, obsDate)
# 
# dt <- pm10DT[pm25DT]
# 
# ggplot2::ggplot(dt, aes(x = pm10, y = pm25, colour = site)) +
#   geom_point() +
#   theme(legend.position="bottom") +
#   scale_color_viridis_d(name = "Site")

6.7 Comparing SSC and AURN

There are only two data streams which match:

matchedDT <- sotonAirDT[site %like% "AURN"]
table(matchedDT$site)
## 
##     Southampton - A33 Roadside (near docks, AURN site) 
##                                                 306131 
## Southampton - Background (near city centre, AURN site) 
##                                                 306131 
##                              Southampton A33 AURN data 
##                                                 280704 
##                           Southampton Centre AURN data 
##                                                 421008
# break up and re-join as wide
sccA33DT <- matchedDT[site %like% "near docks"]
setkey(sccA33DT, dateTimeUTC, pollutant)
sccCenDT <- matchedDT[site %like% "near city"]
setkey(sccCenDT, dateTimeUTC, pollutant)
aurnA33DT <- matchedDT[site %like% "A33 AURN data"]
aurnA33DT[, `:=`(aurnValue, value)]
setkey(aurnA33DT, dateTimeUTC, pollutant)
aurnCenDT <- matchedDT[site %like% "Centre AURN data"]
aurnCenDT[, `:=`(aurnValue, value)]
setkey(aurnCenDT, dateTimeUTC, pollutant)

a33dt <- sccA33DT[aurnA33DT]
centredt <- sccCenDT[aurnCenDT]

a33dt <- a33dt[!is.na(site)]  # remove non-matches
a33dt <- a33dt[!is.na(value)]
a33dt <- a33dt[!is.na(aurnValue)]
centredt <- centredt[!is.na(site)]  # remove non-matches
centredt <- centredt[!is.na(value)]
centredt <- centredt[!is.na(aurnValue)]

Any differences should be to do with the ratification process on data older than 6 months.

Test A33 site

a33dt[, `:=`(Year, lubridate::year(dateTimeUTC))]
ggplot2::ggplot(a33dt, aes(x = value, y = aurnValue, colour = as.factor(Year))) + geom_point() + theme(legend.position = "bottom") + 
    scale_colour_discrete(name = "Year") + facet_grid(. ~ pollutant, scales = "free")

Test City centre site

centredt[, `:=`(Year, lubridate::year(dateTimeUTC))]
ggplot2::ggplot(centredt, aes(x = value, y = aurnValue, colour = as.factor(Year))) + geom_point() + theme(legend.position = "bottom") + 
    scale_colour_discrete(name = "Year") + facet_grid(. ~ pollutant, scales = "free")

7 Runtime

Report generated using knitr in RStudio with R version 3.6.3 (2020-02-29) running on x86_64-apple-darwin15.6.0 (Darwin Kernel Version 19.4.0: Wed Mar 4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64).

t <- proc.time() - myParams$startTime

elapsed <- t[[3]]

Analysis completed in 979.841 seconds ( 16.33 minutes).

R packages used:

  • data.table - (Dowle et al. 2015)
  • ggplot2 - (Wickham 2009)
  • here - (Müller 2017)
  • kableExtra - (Zhu 2018)
  • lubridate - (Grolemund and Wickham 2011)
  • skimr - (Arino de la Rubia et al. 2017)
  • viridis - (Garnier 2018)

References

Arino de la Rubia, Eduardo, Hao Zhu, Shannon Ellis, Elin Waring, and Michael Quinn. 2017. Skimr: Skimr. https://github.com/ropenscilabs/skimr.

Dowle, M, A Srinivasan, T Short, S Lianoglou with contributions from R Saporta, and E Antonyan. 2015. Data.table: Extension of Data.frame. https://CRAN.R-project.org/package=data.table.

Garnier, Simon. 2018. Viridis: Default Color Maps from ’Matplotlib’. https://CRAN.R-project.org/package=viridis.

Grolemund, Garrett, and Hadley Wickham. 2011. “Dates and Times Made Easy with lubridate.” Journal of Statistical Software 40 (3): 1–25. http://www.jstatsoft.org/v40/i03/.

Müller, Kirill. 2017. Here: A Simpler Way to Find Your Files. https://CRAN.R-project.org/package=here.

Wickham, Hadley. 2009. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. http://ggplot2.org.

Zhu, Hao. 2018. KableExtra: Construct Complex Table with ’Kable’ and Pipe Syntax. https://CRAN.R-project.org/package=kableExtra.