This note summarizes recommended methods for the installation and testing of the R package AQEval.
User Caveats
Both R and AQEval are freely distributed under public licence. However, you still need to confirm you are allowed to install and use any software. So:
If you have any problems installing or using AQEval, please get in touch, or post an issue on the package repository
If you do not already have R, it can be downloaded and installed from CRAN1.
If you want to use one, there are also a number of R interfaces you can install to simplify coding, e.g.:
From R or an interface, you can download and install the current stable-release version of the AQEval package:
install.packages("AQEval")
This installs both AQEval and (if you do not already have them) any other R packages that it uses.
Alternatively, you can download the developer’s version of the package from the project archive:
# (if you do not have remotes package, install it from CRAN)
# install.packages("remotes")
remotes::install_github("karlropkins/AQEval")
(This is often more recent but may not be fully tested…)
A lot of testing is done when an R package is put together. Both build and check routines are typically run whenever a package is updated. For example, the check routines typically require both the code to install correctly and the on-board examples (the examples in help documentation) run both quickly and without error. In addition, if a package is coming from CRAN it means that they, acting as third-party party reviewer, have also confirmed performance using multiple computer platforms.
However, you may also test your local package installation.
The simplest to way to both learn how to use AQEval and test the package installation is to work through either the examples provided in the on-board documentation or the package introduction.
Or run through a quick workflow using major functions and compare outputs with a reference set like this:
# load package
require(AQEval)
## Loading required package: AQEval
# have a quick look at the on-board data
head(aq.data)
## # A tibble: 6 × 6
## date no2 bg.no2 ws wd air_temp
## <dttm> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2001-01-01 00:00:00 5.77 NA 8.5 170 5.55
## 2 2001-01-01 01:00:00 6.50 NA 6.95 170 6.5
## 3 2001-01-01 02:00:00 11.0 NA 5.95 170 7.5
## 4 2001-01-01 03:00:00 7.38 NA 6.2 181. 8.4
## 5 2001-01-01 04:00:00 5.77 NA 7.45 190 8.8
## 6 2001-01-01 05:00:00 5.77 NA 7.45 190 9
aq.data is a data.frame of time-series: date, the dataset time-stamp; nitrogen dioxide no2 concentrations, wind speed ws, wind direction wd and air temperature air_temp, all measured at a roadside air quality monitoring station; and, bg.no2, nitrogen dioxide concentrations at a near-by background site.
# Use openair function timeAverage to convert that from 1-hour to 14-day average.
# (Here, we are after a quick example for package testing, but is standard analyses
# to try a range of averaging period because there will be trade-offs between
# run-time and detection rates...)
temp <- openair::timeAverage(aq.data, "14 day")
head(temp)
## # A tibble: 6 × 6
## date no2 bg.no2 ws wd air_temp
## <dttm> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2001-01-01 00:00:00 41.2 22.4 4.76 112. 5.98
## 2 2001-01-15 00:00:00 59.7 32.8 3.11 169. 3.30
## 3 2001-01-29 00:00:00 36.6 21.0 4.01 203. 6.41
## 4 2001-02-12 00:00:00 59.4 30.8 2.57 311. 5.27
## 5 2001-02-26 00:00:00 50.1 21.9 3.68 123. 5.59
## 6 2001-03-12 00:00:00 45.4 26.5 3.78 55.2 6.22
# Use AQEval function quantBreakPoints to detect and quantify possible break-points
# in the nitrogen dioxide time-series
quantBreakPoints(temp, "no2", h=0.1, test=FALSE)
This test indicates an almost-regular ‘saw-tooth’ pattern to the nitrogen dioxide time-series with relatively high levels during the winter months of each year. This is typical of a measurement that is dominated by a seasonal cycle.
(You should see similar plot and a screen report listing the identified break-points.)
If we want to look for other changes that might be obscured by that seasonal profile we could try to separate them, e.g. using AQEval function isolateContribution:
# We go back to the 1-hour data and apply isolateContribution
# to build a deseasonalisation, deweathering and background
# correction (dswb) model.
aq.data$dswb.no2 <- isolateContribution(aq.data,
"no2", background="bg.no2")
## no2 ~ s(bg.no2) + te(wd, ws) + s(year.day) + s(day.hour)
Note, that the report says that the model uses a range of parameters, bg.no2, ws and wd from the dataset, but also year.day, the day of the year, and day.hour, the hour of the day. These additional terms are calculated from the date time-series.
(And, access to day.hour is why we went back to aq.data rather than building model with the 14-day version, temp…)
See on-board documentation, e.g. ?isolateContribution for further details, or if you are interested in trying out other signal isolation models.
# convert that to 14-day like before
temp <- openair::timeAverage(aq.data, "14 day")
# and apply quantBreakPoints to the isolated NO2 time-series
quantBreakPoints(temp, "dswb.no2", h=0.1, test=FALSE)
Now we see a change-point at the end of 2002 that was previously hidden by the series of larger seasonal changes.
(Again, you should see similar if quantBreakPoints and isolateContribution are both working correctly, and the workflow should be error-free if both AQEval and openair have been installed correctly.)
Manual testing is useful when you are new to a package, but it can be time-consuming especially if you want to test multiple minor functions in a package or if you are updating a package that you are already highly familiar with and just want to quickly confirm consistent function outputs…
So, AQEval also has an on-board automatic testing option.
This uses a package called tinytest, installed alongside AQEval, to run a series of similar workflows and compare their outputs and expected outcomes.
Probably, the easiest way to use this is to just run the lot:
tinytest::test_package("AQEval", at_home=TRUE)
## test_AQEval_calc.stats.R...... 4 tests OK 0.2s
## test_AQEval_data.R............ 2 tests OK 0.1s
## test_AQEval_find.R............ 3 tests OK 16ms
## test_AQEval_isolate.R......... 1 tests OK 0.3s
## test_AQEval_quant.R........... 6 tests OK 0.8s
## test_AQEval_spec.R............ 2 tests OK 0.5s
## All ok, 18 results (1.9s)
(If they are all OK when you run this, we think your installation is as well.)
Obviously, testing, however meticulous, will not catch everything.
Some issues are unexpected. For example, a user may use the software in an innovative way the developer had not envisioned or use it with an new type of data. But just as easily maybe we missed something when we put together the standard test list for AQEval, so please feel free to get in contact or post an issue if you think there is anything we have missed or if you are any having problems installing AQEval.
R
R Core Team (2025). R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/.
AQEval
Ropkins K, Walker A, Tate J (2025). AQEval: Air Quality Evaluation. R package version 0.6.2, https://github.com/karlropkins/AQEval.
Ropkins K, Walker A, Philips I, Rushton C, Clark T, Tate J (2022). “Change Detection of Air Quality Time-Series Using the R Package AQEval.” SSRN preprint. doi:10.2139/ssrn.4267722, https://dx.doi.org/10.2139/ssrn.4267722.
openair (using timeAverage function in examples):
Carslaw DC, Ropkins K (2012). “openair - An R package for air quality data analysis.” Environmental Modelling & Software, 27–28(0), 52-61. ISSN 1364-8152, doi:10.1016/j.envsoft.2011.09.008.
tinytest (for automatic testing):
van der Loo M (2020). “A method for deriving information from running R code.” The R Journal, Accepted for publication. https://arxiv.org/abs/2002.07472.
If you have no previous experience of R you should probably also consider getting so training because it can be a steep learning curve…↩︎