From c364f61d02258adb3e4118e253a6a2bdc82d58b2 Mon Sep 17 00:00:00 2001 From: mahaalbashir Date: Mon, 10 Aug 2026 13:06:00 +0100 Subject: [PATCH 1/4] updating demo notebook --- NAMESPACE | 4 - NEWS.md | 4 + R/acro_tables.R | 2 + R/utils.R | 8 +- inst/WORDLIST | 21 +- inst/notebooks/acro_demo_2026.R | 491 ++++++++++++++++++++-- inst/notebooks/acro_demo_2026.Rmd | 34 +- inst/notebooks/acro_in_tidyverse_demo.Rmd | 4 +- man/acro_summarise.Rd | 4 +- man/create_factors.Rd | 19 - man/is_excluded.Rd | 19 - man/is_invalid.Rd | 17 - man/to_pandas_categorical.Rd | 19 - vignettes/supports.Rmd | 1 + 14 files changed, 519 insertions(+), 128 deletions(-) delete mode 100644 man/create_factors.Rd delete mode 100644 man/is_excluded.Rd delete mode 100644 man/is_invalid.Rd delete mode 100644 man/to_pandas_categorical.Rd diff --git a/NAMESPACE b/NAMESPACE index 7ba62a7..5e248eb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -18,7 +18,3 @@ export(acro_rename_output) export(acro_summarise) export(acro_surv_func) export(acro_table) -export(create_factors) -export(is_excluded) -export(is_invalid) -export(to_pandas_categorical) diff --git a/NEWS.md b/NEWS.md index 3cf74ce..f01bb63 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# acro 0.1.8 +* Added extended support to `acro_table()` to include all parameters from the base R `table()` function. +* Added additional parameters to `acro_crosstab()`. +* Introduced `acro_summarise()`, an ACRO wrapper for the tidyverse `summarise()` function. # acro 0.1.7 * Added support for installation via conda diff --git a/R/acro_tables.R b/R/acro_tables.R index 63b7da1..2af444a 100644 --- a/R/acro_tables.R +++ b/R/acro_tables.R @@ -167,6 +167,8 @@ acro_table <- function(index, columns, dnn = NULL, deparse.level = 0, useNA = "n return(table) } +#'Create a summary data frame +#' #' Creates a new data frame. It returns one row for each combination of grouping variables; if there are no grouping variables, the output will have a single row summarising all observations in the input #' #' @param .data A data frame or a data frame extension diff --git a/R/utils.R b/R/utils.R index 956b4e1..276bc95 100644 --- a/R/utils.R +++ b/R/utils.R @@ -3,7 +3,7 @@ #' @param Values to check for empty values in it #' #' @returns logical vector that shows the places of the empty values -#' @export +#' @noRd is_invalid <- function(Values) { # Check for NA or NaN in the object @@ -16,7 +16,7 @@ is_invalid <- function(Values) { #' @param exclude_list Items to exclude from the values #' #' @returns logical vector that shows the places of the items that needs to be excluded -#' @export +#' @noRd is_excluded <- function(Values, exclude_list) { # Catch everything in the exclude list @@ -43,7 +43,7 @@ is_excluded <- function(Values, exclude_list) { #' @param useNA whether to include NA values in the table #' #' @returns R vector factor -#' @export +#' @noRd create_factors <- function(Values, useNA) { # Check for NAs @@ -68,7 +68,7 @@ create_factors <- function(Values, useNA) { #' @param pd Reference to the Python `pandas` module #' #' @returns A Python `pandas.Categorical` object -#' @export +#' @noRd to_pandas_categorical <- function(Values, pd) { # Build the Pandas Categorical diff --git a/inst/WORDLIST b/inst/WORDLIST index 8382203..19df239 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -2,6 +2,7 @@ ADR Acknowledgement Analytics Conda +Crosstab EPSRC GRAIMATTER HDR @@ -9,30 +10,46 @@ Initialise Karnofsky MRC MyBinder +OpenML RStudio SACRO SDC +Summarise +TRE +TRE's TREs TREvolution Transformative Xplore -YAML analytics auditable +checksums codecov +coloured conda -config crosstab +csv disclosive +finalise +finalising github https +initialise initialised json numpy openml pre +prioritise programme +recognise +reimplement scipy +statsmodels +summarise +summarising +tidyverse +toolchain www xlsx yaml diff --git a/inst/notebooks/acro_demo_2026.R b/inst/notebooks/acro_demo_2026.R index 5366009..6702acb 100644 --- a/inst/notebooks/acro_demo_2026.R +++ b/inst/notebooks/acro_demo_2026.R @@ -1,52 +1,328 @@ -## ----------------------------------------------------------------------------- +#' --- +#' title: "acro R demonstration 2026" +#' editor_options: +#' markdown: +#' wrap: 90 +#' chunk_output_type: inline +#' --- +#' +#' # ACRO Demonstration +#' +#' This is a simple notebook to get you started with using the `acro` package to add +#' disclosure risk control to your analysis. +#' +#' ## A: The basic concepts +#' +#' ### 1: A research *session*: +#' +#' by which we mean the activity of running a series of commands (interactively or via a +#' script) that: - ingest some data, - manipulate it, and then - produce (and store) some +#' outputs. +#' +#' ### 2: Types of commands: +#' +#' Whether interactive, or just running a final script, we can think of the commands that get +#' run in a session as dividing into: +#' +#' \- *manipulation* commands that load and transform data into the shape you want +#' +#' \- *feedback* commands that report on your data - but are never intended to be exported. +#' For example, running a `head()` command to make sure your manipulations have got the data +#' into the format you want. +#' +#' \- *query* commands that produce an output from your data (table/plot/regression model +#' etc.) that you might want to export from the Trusted Research Environment (TRE) +#' +#' ### 3: Risk Assessment vs decision making: +#' +#' SACRO stands for Semi-Automated Checking of Research Outputs.\ +#' +#' - The prefix 'Semi' is important here - because in a principles-based system humans +#' should make *decisions* about output requests. +#' +#' - To help with that we provide the SACRO-Viewer, which collates all the relevant +#' information for them. +#' +#' A key part of that information is the *Risk Assessment*. +#' +#' - Since it involves calculating metrics and comparing them to thresholds (the TRE's risk +#' appetite) it can be done automatically, at the time an output query runs on the data. +#' +#' - This is what the ACRO package does when you use it as part of your workflow. +#' +#' ### 4: What acro does +#' +#' The acro package aims to support you in producing *Safe Outputs* within minimal changes to +#' your work flow. To do that we provide: +#' +#' 1. drop-in replacements for the most commonly used *output commands*, +#' +#' - keeping the same syntax as the originals, and +#' +#' - supporting as many of the options as we can (features supported will increase over +#' time in response demand). +#' +#' 2. a set of *session-management* commands to help you manage the set of files you request +#' for output. +#' +#' **Important to note** that currently acro outputs results (tables, details of regression +#' models etc.) as `.csv` files.\ +#' In other words we separate the processes of: +#' +#' - *creating* outputs - which *must* be done *inside* the TRE. +#' - *formatting* them for publication - which can be done outside the TRE with your +#' preferred toolchain. +#' +#' acro currently handles creation. We are interested in hearing from researchers whether it +#' is important to support them with formatting +#' +#' But if you format your outputs, and save them to your preferred type of file, you can add +#' them to your acro session as `custom_outputs`, including a comment to the reviewer to say +#' which of the risk-assessed outputs they are derived from. +#' +#' ### 5: How acro works in R +#' +#' There are obvious benefits to maintaining a single *point of truth* for the key +#' functionality of the code base: +#' +#' - it makes it easier to maintain and extend. +#' - it makes it possible to validate the disclosure -control process against a published +#' ontology +#' - it enables rapid and consistent support for other languages +#' +#' Therefore the `acro` in R acts like a *skin* that communicates with the underlying python +#' via R's `reticulate` package. So behind-the scenes: +#' +#' - For **regressions** and other statistics acro uses the *statsmodels* package - which +#' has the benefit of happily accepting R-style equations. +#' +#' - For **tables** acro uses the industry standard *pandas* package, in particular the +#' *pivot_table()* and *crosstab()* functions. +#' +#' This approach lets acro: +#' +#' - support R's `help()` functions and and vignettes +#' +#' - provide acro versions of standard R commands like `table` (this directly maps on +#' directly onto `crosstab()` queries) +#' +#' - provide R users with access to powerful table-building commands like crosstab: +#' +#' - There are hundreds (thousands?) of web sites showing how to do this.\ +#' +#' - You can make (hierarchical) 2-D tables (or 1-D if you add a 'dummy' variable +#' containing the same value for each row) +#' +#' - You can specify what the table cells contain by specifying which variable to +#' report on and what statistic to report- for example: mean, count, std deviation, +#' median etc.(pandas calls these *aggregation functions*) +#' +#' **The acro version does not reimplement any statistical commands**. Instead it reuses +#' them - but it adds extra code that checks for disclosure risks depending on the statistic +#' you ask for +#' +#' ## B: Getting Started with the demonstration +#' +#' ### Step 1: Check if acro is installed and if it is not install it from CRAN +#' +## --------------------------------------------------------------------------------------------------------------------- # Check if acro is installed if (!requireNamespace("acro", quietly = TRUE)) { # If not installed, install it install.packages("acro") } - -## ----------------------------------------------------------------------------- +#' +#' ### Step 2: Starting an ACRO session +#' +#' First of all, we need to load the package and then call acro_init() to initialise an acro +#' session. This function takes two optional parameters: +#' +#' - suppress which can be TRUE or FALSE (default) to choose whether to automatically apply +#' suppression to the results or not. +#' +#' - config: the name of a file in .yaml format the TRE may have given you to over-ride the +#' default risk appetite parameters. +#' +#' Note that when the cell runs it should report (possibly in a different coloured +#' font/background): +#' +#' - what version of acro is running: *this should be 0.4.12* +#' +#' - the TRE's risk appetite: that define the rules your outputs will be checked against. +#' +#' - whether suppression is automatically applied to disclosive outputs. +#' +#' #### Load the acro package +#' +## --------------------------------------------------------------------------------------------------------------------- library("acro") - -## ----------------------------------------------------------------------------- +#' +#' #### Initiate acro +#' +## --------------------------------------------------------------------------------------------------------------------- acro_init() - -## ----------------------------------------------------------------------------- +#' +#' ### Step 3: Load the data +#' +#' - The dataset used in this example notebook is the nursery dataset from OpenML. +#' - The code below reads the data from a folder called "nursery_data" which we assume is +#' at the same level as the folder where you are working. +#' - The path might need to be changed if the data has been downloaded and stored +#' elsewhere. +#' +#' **There is no change to your usual workflow here** This is just loading and manipulating +#' data. +#' +## --------------------------------------------------------------------------------------------------------------------- data <- farff::readARFF("data/nursery.arff") data <- as.data.frame(data) names(data)[names(data) == "class"] <- "recommendation" - -## ----------------------------------------------------------------------------- +#' +#' Convert the children column to integers, replacing 'more' with random int from range 4-10 +#' +## --------------------------------------------------------------------------------------------------------------------- data$children <- as.numeric(as.character(data$children)) data[is.na(data)] <- round(runif(sum(is.na(data)), min = 4, max = 10), 0) unique(data$children) - -## ----------------------------------------------------------------------------- +#' +#' Example of a Feedback command +#' +## --------------------------------------------------------------------------------------------------------------------- head(data) - -## ----------------------------------------------------------------------------- +#' +#' ## C: Producing tables that are 'Safe Outputs' +#' +#' ### Example 1: A simple 2-D table of frequencies stratified by two variables +#' +#' #### Using the acro version of R's table command +#' +#' We will produce a simple cross-tabulation of the number of records, stratified by values +#' for the *recommendation* and *parents* variables. +#' +## --------------------------------------------------------------------------------------------------------------------- rows <- data[, c("recommendation")] columns <- data[, c("parents")] table <- acro_table(index = rows, columns = columns, deparse.level = 1) table - -## ----------------------------------------------------------------------------- - +#' +#' #### How to understand this output +#' +#' The output in the console (or click on left thumbnail above) is the risk analysis produced +#' by acro. It is telling us that: +#' +#' - the overall summary status is *fail* because 4 cells are failing the 'minimum +#' threshold' check +#' +#' - which cells failed so you can choose how to respond +#' +#' - finally it is telling us that is has saved the table and risk assessment to our acro +#' session with id "output_0" +#' +#' The part in the data.frame window (or click or right thumbnail above) is the normal output +#' produced by the R *table* function. +#' +#' - As this is such a small table it is not hard to spot the four problematic cells with +#' zero or low counts. +#' +#' - But of course this might be harder for a bigger table. +#' +#' #### How to respond to this input +#' +#' There are basically three choices: +#' +#' 1. You might decide these low numbers reveal something where the public interest +#' outweighs the disclosure risk. +#' +#' - Rather than being a strict rules-based system, acro lets you attach an 'exception +#' request' to an output, to send a message to the output checkers. For example, you +#' could type: +#' +#' ``` +#' acro.add_exception('output_0',"I think you should let me have this because...") +#' ``` +#' +#' 2. You could redesign/recode the data so that table so that none of the cells in the +#' resulting table represent fewer than *n* people (10 for the default risk appetite). +#' +#' - For example, you could recode *'very_recommend'* and *'priority'* into one label.But +#' maybe it is revealing that the *'recommend'* value is not used? +#' +#' 3. You can redact the disclosive cells - and **acro will do this for you**. +#' +#' We simply enable the option to suppress disclosive cells and re-run the query. +#' +#' The code below shows option 3. When you run the cell below you should see that a new +#' output is created and added to the session: +#' +#' - the status now changes to `review` (so the output-checker knows what has been applied) +#' +#' - the code automatically adds an exception request saying that suppression has been +#' applied +#' +#' - and, most importantly, the cells are redacted. +#' +## --------------------------------------------------------------------------------------------------------------------- acro_enable_suppression() table <- acro_table(index = rows, columns = columns, deparse.level = 1) table - -## ----------------------------------------------------------------------------- +#' +#' ### ACRO Summarise +#' +#' - ACRO also supports the familiar summarise() function from the tidyverse package. +#' Below is an example of a standard piping operation that uses acro_summarise() instead of tidyverse summarise(). +#' - In this example, the data is grouped by *parents* and *recommendation*, and we calculate *the mean number of children*. +#' +## --------------------------------------------------------------------------------------------------------------------- +# Generate a summary table using ACRO +data %>% + group_by(parents, recommendation) %>% + acro_summarise( + mean_children = mean(children) + ) + +#' +#' As you can see from the outputs, acro_summarise() produces: +#' - *The summary table*: Identical results to what standard tidyverse summarise() would generate. +#' - *Disclosure metrics (counts and dominance)*: These are the Statistical Disclosure Control (SDC) checks that ACRO performs automatically in the background. They provide the evidence required by a Trusted Research Environment (TRE) output checker, saving you from having to calculate these checks manually. +#' +#' ### ACRO Crosstab +#' +#' According to R's documentation, the \`table' command is typically only used to produce +#' contingency tables - i.e. report on frequencies. +#' +#' We could have produced the table above using the command +#' `table2 <- acro_crosstab(index=rows,columns=columns)` +#' +#' To illustrate the sort of tables that `crosstab()` can easily produce, the example below +#' produces something more complex. Going through the parameters in order: +#' +#' - passing a list of variable names to `index` (rather than a single variable/column +#' name) tells it we want a hierarchy within the rows. +#' +#' - we can do the same to columns as well (or instead) if we want to +#' +#' - to specify the cell contents we: +#' +#' - set `values` to be the column `children` to identify what variable to report on +#' +#' - setting `aggfunc<-"mean"` to specify the statistic to use. +#' +#' - In this case the mean number of children per sub-group. This introduces additional +#' risks of *dominance* for which there are two widely used tests. +#' +#' - +#' +## --------------------------------------------------------------------------------------------------------------------- myrows <- list(data[, c("parents")], data[, c("finance")]) mycolumns <- data[, c("recommendation")] myvalues <- data[, c("children")] @@ -62,39 +338,186 @@ table4 <- acro_crosstab( ) table4 - -## ----------------------------------------------------------------------------- - +#' +#' ## D: What other sorts of analysis does ACRO currently support? +#' +#' We are continually adding support for more types of analysis as users prioritise them. +#' +#' ACRO currently supports: +#' +#' - **Tables** via `acro_table()`, `acro_crosstab()`, `acro_pivot_table()` and `acro_summarise()`. +#' For the `acro_table()`, `acro_crosstab()`, `acro_pivot_table()`: +#' - supported aggregation functions are: *mean*, *median*, *sum*, *std*, *count*, and +#' *mode*. +#' - you can also pass a list of aggregation functions e.g. +#' `aggfunc <-list("mean","median")` +#' - NB we have recently had reports of instability when automatically suppressing +#' tables with multiple aggregation functions, one of which is "std". A fix for this +#' will be issued shortly. +#' +#' For acro_summarise(): +#' - supported aggregation functions are: *mean*, *median*, *sum*, *std*, and +#' *mode*. The support for *n()* will be available shortly. +#' - ACRO currently does not support different aggregation functions for different values. It will be available shortly. +#' - acro_summarise() support standard R piping. +#' +#' +#' - **Survival analysis** via: `acro_surv_function()`, +#' +#' - **Histograms** via:`acro_hist()` +#' +#' - **Regression** via: `acro_ols()`, `acro_logit()`,`acro_probit()` +#' +#' You can get help on using any of these using the standard R `help()` syntax as shown in +#' the next cell. +#' +#' In RStudio this opens the help menu for the package in the sidebar. +#' +## --------------------------------------------------------------------------------------------------------------------- help(package = "acro") - -## ----------------------------------------------------------------------------- +#' +#' ## E: ACRO functionality to let users manage their outputs +#' +#' As explained above, you need to create an "acro session" whenever your code is run. +#' +#' After that, every time you run an acro \`query' command both the output and the risk +#' assessment are saved as part of the acro session. +#' +#' But we recognise that: +#' +#' - You may not want to request release of all your outputs - for example, the first table +#' we produced above. +#' +#' - It is good practice to provide a more informative name than just *output_n* for the +#' .csv files that acro produces +#' +#' - It helps the output checker if you provide some comments saying what the outputs are. +#' +#' - You might want to add more things to the bundles of files you want to take out, such +#' as: +#' +#' - outputs from analyses that acro doesn't currently support +#' +#' - your code itself (which many journals want) +#' +#' - maybe a version of your paper in pdf/word format etc. +#' +#' Therefore acro provides the following commands for 'session management' +#' +#' ### 1: Listing the current contents of an ACRO session +#' +#' This output is not beautiful (there's a GUI coming soon) but it should let you identify +#' outputs you want to rename,comment on, or delete. +#' +## --------------------------------------------------------------------------------------------------------------------- details <- acro_print_outputs() - -## ----------------------------------------------------------------------------- +#' +#' ### 2: Remove some ACRO outputs before finalising +#' +#' At the start of this demo we made a disclosive output -it's the first one with status +#' *fail*. +#' +#' We don't want to waste the output checker's time so lets remove it. +#' +## --------------------------------------------------------------------------------------------------------------------- acro_remove_output("output_0") - -## ----------------------------------------------------------------------------- +#' +#' ### 3: Rename ACRO outputs before finalising +#' +#' It's always a good idea to rename the outputs to provide more descriptive names. +#' +## --------------------------------------------------------------------------------------------------------------------- acro_rename_output("output_1", " crosstab_recommendation_vs_parents") acro_rename_output("output_2", "mean_children_by_parents_finance_vs_recommendation") - -## ----------------------------------------------------------------------------- - +#' +#' ### 4: Add a comment to output +#' +#' This is an example of adding a comment to outputs.\ +#' It can be used to provide a description or to pass additional information to the TRE +#' staff. +#' +#' They will see it alongside your file in the output checking viewer - rather than having it +#' in an email somewhere. +#' +## --------------------------------------------------------------------------------------------------------------------- acro_add_comments( "mean_children_by_parents_finance_vs_recommendation", "too few cases of recommend to report" ) - -## ----------------------------------------------------------------------------- +#' +#' ### 5. Request an exception +#' +#' An example of providing a reason why an exception should be made. +#' +#' There are none in this example but this is the syntax +#' +#' ``` +#' acro_add_exception("output_n", "This is evidence of systematic bias?") +#' ``` +#' +#' ### 6: Adding a custom output. +#' +#' As mentioned above you might want to request release of all sorts of things - including +#' your code, - or outputs from analyses *acro* doesn't support (yet) +#' +#' In ACRO we can add a file to our session with a comment describing what it is. +#' +#' The following example includes the R code extracted from this notebook using knit::purl(). +#' +## --------------------------------------------------------------------------------------------------------------------- acro_custom_output("acro_demo_2026.R", "This is the code that produced this session") - -## ----------------------------------------------------------------------------- +#' +#' ## F: Finishing your session and producing a folder of files to release. +#' +#' This is an example of the function *finalise()* which the users must call at the end of +#' each session. This function: +#' +#' - takes each output and saves it to a CSV file (or the original file type for custom +#' outputs) +#' +#' - saves the risk appetite used (minimum cell thresholds etc.) to a file called +#' *config.json* +#' +#' - saves the SDC analysis for each output to a json file *results.json* +#' +#' - adds checksums for everything - so we know they've not been edited. +#' +#' - puts all the above in a folder with the name you supply. +#' +#' **ACRO will not overwrite previous sessions** +#' +#' So every time you call finalise on a session you need to either: +#' +#' - manually delete the previous folder, or +#' +#' - provide a new folder name, or +#' +#' - create a unique string variable in your code and pass that to `finalise()` as shown +#' below. +#' +## --------------------------------------------------------------------------------------------------------------------- myfolder <- "Routputs" suffix <- format(Sys.time(), "%e_%m_%Y_%H_%M") foldername <- paste(myfolder, suffix, sep = "_") acro_finalise(foldername, ext = "json") + +#' +#' ## G: Reminder about getting help while you work +#' +#' - If you can't remember the name of the command, from the R prompt type: +#' `help(package="acro")` +#' +#' - in RStudio this will open the interactive sidebar +#' +#' - from a terminal this will list the commands present in the acro package +#' +#' - If you can know the name of the command and want an explanation or to explain the +#' syntax, from the R prompt type: `` help(topic=`acro_command_name`, package="acro") `` +#' +#' for example: `` help(topic=`acro_crosstab`,package="acro") `` diff --git a/inst/notebooks/acro_demo_2026.Rmd b/inst/notebooks/acro_demo_2026.Rmd index efd2954..b898a91 100644 --- a/inst/notebooks/acro_demo_2026.Rmd +++ b/inst/notebooks/acro_demo_2026.Rmd @@ -276,6 +276,25 @@ table <- acro_table(index = rows, columns = columns, deparse.level = 1) table ``` +### ACRO Summarise + +- ACRO also supports the familiar summarise() function from the tidyverse package. +Below is an example of a standard piping operation that uses acro_summarise() instead of tidyverse summarise(). +- In this example, the data is grouped by *parents* and *recommendation*, and we calculate *the mean number of children*. + +```{r} +# Generate a summary table using ACRO +data %>% + group_by(parents, recommendation) %>% + acro_summarise( + mean_children = mean(children) + ) +``` + +As you can see from the outputs, acro_summarise() produces: +- *The summary table*: Identical results to what standard tidyverse summarise() would generate. +- *Disclosure metrics (counts and dominance)*: These are the Statistical Disclosure Control (SDC) checks that ACRO performs automatically in the background. They provide the evidence required by a Trusted Research Environment (TRE) output checker, saving you from having to calculate these checks manually. + ### ACRO Crosstab According to R's documentation, the \`table' command is typically only used to produce @@ -320,18 +339,14 @@ table4 <- acro_crosstab( table4 ``` -### ACRO Summarise - -We also support the summarise() function from the tidy verse. Please see here for a separate example notebook about acro in the tidy verse [acro_in_tidyverse_demo.Rmd file](acro_in_tidyverse_demo.Rmd). - ## D: What other sorts of analysis does ACRO currently support? We are continually adding support for more types of analysis as users prioritise them. ACRO currently supports: -- **Tables** via `acro_table()`, `acro_crosstab()` and `acro_pivot_table()`. - +- **Tables** via `acro_table()`, `acro_crosstab()`, `acro_pivot_table()` and `acro_summarise()`. + For the `acro_table()`, `acro_crosstab()`, `acro_pivot_table()`: - supported aggregation functions are: *mean*, *median*, *sum*, *std*, *count*, and *mode*. - you can also pass a list of aggregation functions e.g. @@ -340,6 +355,13 @@ ACRO currently supports: tables with multiple aggregation functions, one of which is "std". A fix for this will be issued shortly. + For acro_summarise(): + - supported aggregation functions are: *mean*, *median*, *sum*, *std*, and + *mode*. The support for *n()* will be available shortly. + - ACRO currently does not support different aggregation functions for different values. It will be available shortly. + - acro_summarise() support standard R piping. + + - **Survival analysis** via: `acro_surv_function()`, - **Histograms** via:`acro_hist()` diff --git a/inst/notebooks/acro_in_tidyverse_demo.Rmd b/inst/notebooks/acro_in_tidyverse_demo.Rmd index abfecb5..f8bc557 100644 --- a/inst/notebooks/acro_in_tidyverse_demo.Rmd +++ b/inst/notebooks/acro_in_tidyverse_demo.Rmd @@ -58,7 +58,7 @@ nursery_data <- readARFF("../../data/nursery.arff") %>% In this step we are going to use some tidyverse verses to clean and prep the data. - *mutate()* are used to format the children column -- *setcet()* is used to keep only specific column +- *select()* is used to keep only specific column You can see that nothing has changed in the syntax or workflow up to this step ```{r} @@ -88,4 +88,4 @@ nursery_data %>% ) ``` -You can see that the output is not just the summary table but also the risk analysis produced by acro. You can then decide what are the steps you are going to make to remove the discolsive cells as discussed in the [acro_demo_2026.Rmd file](acro_demo_2026.Rmd) document. +You can see that the output is not just the summary table but also the risk analysis produced by acro. You can then decide what are the steps you are going to make to remove the disclosive cells as discussed in the [acro_demo_2026.Rmd file](acro_demo_2026.Rmd) document. diff --git a/man/acro_summarise.Rd b/man/acro_summarise.Rd index 1989945..68fa3cf 100644 --- a/man/acro_summarise.Rd +++ b/man/acro_summarise.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/acro_tables.R \name{acro_summarise} \alias{acro_summarise} -\title{Title} +\title{Create a summary data frame} \usage{ acro_summarise(.data, ..., .groups = NULL, .by = NULL) } @@ -19,5 +19,5 @@ acro_summarise(.data, ..., .groups = NULL, .by = NULL) Summary of the data } \description{ -Title +Creates a new data frame. It returns one row for each combination of grouping variables; if there are no grouping variables, the output will have a single row summarising all observations in the input } diff --git a/man/create_factors.Rd b/man/create_factors.Rd deleted file mode 100644 index 5480225..0000000 --- a/man/create_factors.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{create_factors} -\alias{create_factors} -\title{Convert data to factors and manage NA levels} -\usage{ -create_factors(Values, useNA) -} -\arguments{ -\item{Values}{to create factors on} - -\item{useNA}{whether to include NA values in the table} -} -\value{ -R vector factor -} -\description{ -Convert data to factors and manage NA levels -} diff --git a/man/is_excluded.Rd b/man/is_excluded.Rd deleted file mode 100644 index 90f2904..0000000 --- a/man/is_excluded.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{is_excluded} -\alias{is_excluded} -\title{Identify values to be excluded from an object} -\usage{ -is_excluded(Values, exclude_list) -} -\arguments{ -\item{Values}{to exclude from} - -\item{exclude_list}{Items to exclude from the values} -} -\value{ -logical vector that shows the places of the items that needs to be excluded -} -\description{ -Identify values to be excluded from an object -} diff --git a/man/is_invalid.Rd b/man/is_invalid.Rd deleted file mode 100644 index 93ba9dc..0000000 --- a/man/is_invalid.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{is_invalid} -\alias{is_invalid} -\title{Identify empty values; NA or NaN in an object} -\usage{ -is_invalid(Values) -} -\arguments{ -\item{Values}{to check for empty values in it} -} -\value{ -logical vector that shows the places of the empty values -} -\description{ -Identify empty values; NA or NaN in an object -} diff --git a/man/to_pandas_categorical.Rd b/man/to_pandas_categorical.Rd deleted file mode 100644 index 68f83d1..0000000 --- a/man/to_pandas_categorical.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{to_pandas_categorical} -\alias{to_pandas_categorical} -\title{Convert an R factor to a Pandas Categorical} -\usage{ -to_pandas_categorical(Values, pd) -} -\arguments{ -\item{Values}{R factor vector to be converted} - -\item{pd}{Reference to the Python \code{pandas} module} -} -\value{ -A Python \code{pandas.Categorical} object -} -\description{ -Convert an R factor to a Pandas Categorical -} diff --git a/vignettes/supports.Rmd b/vignettes/supports.Rmd index 5e40559..1f64668 100644 --- a/vignettes/supports.Rmd +++ b/vignettes/supports.Rmd @@ -22,6 +22,7 @@ This page provides a comprehensive overview of the capabilities ACRO supports. * **`crosstab()`** - Cross-tabulation of two or more variables with frequency counting * **`pivot_table()`** - Spreadsheet-style pivot tables with aggregation functions * **`table()`** - Simple frequency tables for categorical data (R interface only) +* **`summarise()`** - Creates summary statistics for data frames (similar to tidyverse summarise() **Technical Details:** From 8b4110c35b5bd678443869bdd0c07e7998002a4d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:13:36 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- R/acro_tables.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/acro_tables.R b/R/acro_tables.R index 2af444a..c19ce47 100644 --- a/R/acro_tables.R +++ b/R/acro_tables.R @@ -167,7 +167,7 @@ acro_table <- function(index, columns, dnn = NULL, deparse.level = 0, useNA = "n return(table) } -#'Create a summary data frame +#' Create a summary data frame #' #' Creates a new data frame. It returns one row for each combination of grouping variables; if there are no grouping variables, the output will have a single row summarising all observations in the input #' From dc08d88ae21e20f4fd7fb53242d2eb0f5404ddfa Mon Sep 17 00:00:00 2001 From: mahaalbashir Date: Wed, 12 Aug 2026 10:04:52 +0100 Subject: [PATCH 3/4] Update inst/notebooks/acro_demo_2026.R Co-authored-by: Jim-smith Signed-off-by: mahaalbashir --- inst/notebooks/acro_demo_2026.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/notebooks/acro_demo_2026.R b/inst/notebooks/acro_demo_2026.R index 6702acb..55e08d6 100644 --- a/inst/notebooks/acro_demo_2026.R +++ b/inst/notebooks/acro_demo_2026.R @@ -147,7 +147,7 @@ if (!requireNamespace("acro", quietly = TRUE)) { #' Note that when the cell runs it should report (possibly in a different coloured #' font/background): #' -#' - what version of acro is running: *this should be 0.4.12* +#' - what version of acro is running: *this should be 0.4.12 or above* #' #' - the TRE's risk appetite: that define the rules your outputs will be checked against. #' From 6ca81df93cc3216e74c147e73e0afb98c17a6ea3 Mon Sep 17 00:00:00 2001 From: mahaalbashir Date: Wed, 12 Aug 2026 10:08:25 +0100 Subject: [PATCH 4/4] Update acro_demo_2026.R Signed-off-by: mahaalbashir --- inst/notebooks/acro_demo_2026.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/notebooks/acro_demo_2026.R b/inst/notebooks/acro_demo_2026.R index 55e08d6..35a6c53 100644 --- a/inst/notebooks/acro_demo_2026.R +++ b/inst/notebooks/acro_demo_2026.R @@ -352,8 +352,8 @@ table4 #' - you can also pass a list of aggregation functions e.g. #' `aggfunc <-list("mean","median")` #' - NB we have recently had reports of instability when automatically suppressing -#' tables with multiple aggregation functions, one of which is "std". A fix for this -#' will be issued shortly. +#' tables with multiple aggregation functions, one of which is "std". This should be fixed in + versions 1.0 and above which implement suppression differently. #' #' For acro_summarise(): #' - supported aggregation functions are: *mean*, *median*, *sum*, *std*, and