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.
| 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”:
|
| 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 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). |
This simple example shows the core concepts:
## plnr 2026.9.23
## https://www.rwhite.no/plnr/
library(ggplot2)
library(data.table)
# 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")The framework makes data management efficient in three ways:
plnr includes several tools for development and
debugging:
## $deaths
## deaths year
## <int> <int>
## 1: 1 2001
## 2: 2 2002
## 3: 3 2003
## 4: 4 2004
##
## $hash
## $hash$current
## [1] "cec793cabd6a9a5511328896c6484c03"
##
## $hash$current_elements
## $hash$current_elements$deaths
## [1] "98d1244c379870be0c043ad5a6e9f743"
## $year_max
## [1] 2002
## $argset
## $argset$year_max
## [1] 2002
##
## $argset$index_analysis
## [1] 1
##
##
## $fn_name
## [1] "fn_fig_1"
When you add an analysis, you can use either fn_name or
fn:
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] "98d1244c379870be0c043ad5a6e9f743"
##
## $deaths2
## [1] "98d1244c379870be0c043ad5a6e9f743"
##
## $deaths3
## [1] "e2c9e7668db24508e3a89d196d994dd6"
data and
argset parameters.is_run_directly() during development.help(package="plnr").