Introduction
plnr is a framework for planning and executing analyses
in R. Use it to organize and run multiple analyses. It covers two cases:
the same function applied with different arguments, and multiple
different functions applied to your data.
Core Concepts
Broad technical terms
| Object | Description |
| argset | A named list containing a set of arguments. |
| analysis |
These are the fundamental units that are scheduled in
|
| plan |
This is the overarching “scheduler”:
|
Different types of plans
| Plan Type | Description |
| Single-function plan | Same action function applied multiple times with different argsets applied to the same datasets. |
| Multi-function plan | Different action functions applied to the same datasets. |
Plan Examples
| Plan Type | Example |
| Single-function plan | Multiple strata (e.g. locations, age groups) that you need to apply the same function to to (e.g. outbreak detection, trend detection, graphing). |
| Single-function plan | Multiple variables (e.g. multiple outcomes, multiple exposures) that you need to apply the same statistical methods to (e.g. regression models, correlation plots). |
| Multi-function plan | Creating the output for a report (e.g. multiple different tables and graphs). |
Basic Usage
This simple example shows the core concepts:
## plnr 2026.8.21
## https://www.rwhite.no/plnr/
##
## Attaching package: 'data.table'
## The following object is masked from 'package:base':
##
## %notin%
# Create a new plan
p <- Plan$new()
# Add data
p$add_data(
name = "deaths",
direct = data.table(deaths=1:4, year=2001:2004)
)
# Add argsets for different years
p$add_argset(
name = "fig_1_2002",
year_max = 2002
)
p$add_argset(
name = "fig_1_2003",
year_max = 2003
)
# Define analysis function
fn_fig_1 <- function(data, argset) {
plot_data <- data$deaths[year <= argset$year_max]
ggplot(plot_data, aes(x=year, y=deaths)) +
geom_line() +
geom_point(size=3) +
labs(title = glue::glue("Deaths from 2001 until {argset$year_max}"))
}
# Apply function to all argsets
p$apply_action_fn_to_all_argsets(fn_name = "fn_fig_1")
# Run analyses
p$run_one("fig_1_2002")
Advanced Features
Data Management
The framework makes data management efficient in three ways:
- It loads data once and reuses it across analyses.
- It keeps data cleaning separate from analysis.
- It tracks data changes with a hash.
Debugging Tools
plnr includes several tools for development and
debugging:
# Access data directly
p$get_data()## $deaths
## deaths year
## <int> <int>
## 1: 1 2001
## 2: 2 2002
## 3: 3 2003
## 4: 4 2004
##
## $hash
## $hash$current
## [1] "1e95d7e0bebc100ba24647f2b28f429e"
##
## $hash$current_elements
## $hash$current_elements$deaths
## [1] "c9e30a8d0af2d4d284347ce8c275e2b9"
# Access specific argset
p$get_argset("fig_1_2002")## $year_max
## [1] 2002
# Access analysis by name or index
p$get_analysis(1)## $argset
## $argset$year_max
## [1] 2002
##
## $argset$index_analysis
## [1] 1
##
##
## $fn_name
## [1] "fn_fig_1"
# Use is_run_directly() for development
fn_analysis <- function(data, argset) {
if(plnr::is_run_directly()) {
data <- p$get_data()
argset <- p$get_argset("fig_1_2002")
}
# function continues here
}Function Naming
When you add an analysis, you can use either fn_name or
fn:
# Using fn_name (recommended)
p$add_analysis(
name = "fig_1_2002",
fn_name = "fn_fig_1",
year_max = 2002
)
# Using fn (for function factories)
p$add_analysis(
name = "fig_1_2003",
fn = fn_fig_1,
year_max = 2003
)Hash-based Caching
The framework uses hashing to track data changes:
# Create two plans with same data
p1 <- Plan$new()
p1$add_data(direct = data.table(deaths=1:4, year=2001:2004), name = "deaths")
p1$add_data(direct = data.table(deaths=1:4, year=2001:2004), name = "deaths2")
p2 <- Plan$new()
p2$add_data(direct = data.table(deaths=1:4, year=2001:2004), name = "deaths")
p2$add_data(direct = data.table(deaths=1:4, year=2001:2004), name = "deaths2")
# Same data has same hash
identical(p1$get_data()$hash$current_elements, p2$get_data()$hash$current_elements)## [1] TRUE
# Different data has different hash
p1$add_data(direct = data.table(deaths=1:5, year=2001:2005), name = "deaths3")
p1$get_data()$hash$current_elements## $deaths
## [1] "c9e30a8d0af2d4d284347ce8c275e2b9"
##
## $deaths2
## [1] "c9e30a8d0af2d4d284347ce8c275e2b9"
##
## $deaths3
## [1] "3840cef6dc64a556e25ff652446512d0"
Best Practices
-
Data Organization
- Keep data cleaning separate from analysis.
- Use meaningful names for datasets.
- Document the data structure and the assumptions.
-
Analysis Functions
- An action function MUST accept
dataandargsetparameters. - Use
is_run_directly()during development. - Keep each function focused on one purpose.
- An action function MUST accept
-
Plan Structure
- Use meaningful names for argsets and analyses.
- Group related analyses together.
- Document the plan structure and its dependencies.
-
Development Workflow
- Start with small examples.
- Use the debugging tools during development.
- Test each analysis on its own, before you run the full plan.
Next Steps
- Read the Adding Analyses vignette for more detailed examples.
- Visit the package website for additional resources.
- Read the function documentation with
help(package="plnr").
