| Type: | Package |
| Title: | Dataset and Variable Picker and Merge Module for 'teal' Applications |
| Version: | 0.1.0 |
| Date: | 2026-05-07 |
| Description: | Allows users to interactively select datasets, variables, and values within 'teal' applications using a 'tidyselect'-style interface. Selected picks can be merged and transformed into analysis-ready data within 'teal' modules. |
| License: | Apache License 2.0 |
| URL: | https://github.com/insightsengineering/teal.picks/, https://insightsengineering.github.io/teal.picks/ |
| BugReports: | https://github.com/insightsengineering/teal.picks/issues |
| Depends: | R (≥ 4.1) |
| Imports: | bsicons, checkmate, dplyr, htmltools, logger, methods, rlang, shiny, shinyWidgets, teal, teal.code, teal.data, teal.logger, tidyselect, yaml |
| Suggests: | jsonlite, knitr, rmarkdown, rvest, shinytest2, teal.transform, testthat (≥ 3.0), tibble, withr (≥ 3.0.0) |
| VignetteBuilder: | knitr |
| Config/Needs/website: | insightsengineering/nesttemplate |
| Config/roxygen2/version: | 8.0.0 |
| Config/testthat/edition: | 3 |
| Encoding: | UTF-8 |
| Language: | en-US |
| NeedsCompilation: | no |
| Packaged: | 2026-05-14 20:49:46 UTC; unardid |
| Author: | Dawid Kaledkowski |
| Maintainer: | Dawid Kaledkowski <dawid.kaledkowski@roche.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-05-19 09:10:02 UTC |
dplyr::filter call
Description
Create a dplyr::filter call
Usage
.call_dplyr_filter(x)
Arguments
x |
( |
Value
call.
dplyr::select call
Description
Create dplyr::select call from dataname and variables
Usage
.call_dplyr_select(dataname, variables)
Arguments
dataname |
( |
variables |
( |
Value
call.
Evaluate delayed choices
Description
Evaluate delayed choices
Usage
.determine_choices(x, data)
.determine_selected(x, data, multiple = FALSE)
.determine_delayed(x, data)
.possible_choices(data)
Arguments
x |
( |
data |
( |
multiple |
( |
Details
Various ways to evaluate choices/selected.
Function resolves x to determine choices or selected. x is matched in multiple ways with
data to return valid choices:
-
x (character): values are matched with names of data and only intersection is returned. -
x (tidyselect-helper): using tidyselect::eval_select -
x (function): function is executed on each element ofdatato determine where function returns TRUE
Mechanism is robust in a sense that it never fails (tryCatch) and returns NULL if no-match found. NULL
in determine() is handled gracefully, by setting NULL to all following components of picks.
In the examples below you can replace .determine_delayed with .determine_choices or .determine_selected.
-
character: refers to the object name indata, for example.determine_delayed(data = iris, x = "Species") .determine_delayed(data = iris, x = c("Species", "inexisting")) .determine_delayed(data = list2env(list(iris = iris, mtcars = mtcars)), x = "iris") -
quosure: delayed (quoted)tidyselect-helperto be evaluated throughtidyselect::eval_select. For example.determine_delayed(data = iris, x = rlang::quo(tidyselect::starts_with("Sepal"))) .determine_delayed(data = iris, x = rlang::quo(1:2)) .determine_delayed(data = iris, x = rlang::quo(Petal.Length:Sepal.Length)) -
function(x): predicate function returning a logical flag. Evaluated for eachdataelement. For example.determine_delayed(data = iris, x = is.numeric) .determine_delayed(data = letters, x = function(x) x > "c") .determine_delayed(data = list2env(list(iris = iris, mtcars = mtcars, a = "a")), x = is.data.frame)
Value
character containing names/levels of data elements which match x, with two differences:
-
.determine_choicesreturns vector named after data labels -
.determine_selectedcuts vector to scalar whenmultiple = FALSE
Is picks delayed
Description
Determine whether list of picks/picks or pick are delayed.
When "pick" is created it could be either:
-
quosurewhentidyselecthelper used (delayed) -
functionwhen predicate function provided (delayed) -
atomicwhen vector of choices/selected provided (eager)
Usage
.is_delayed(x)
Arguments
x |
( |
Value
A logical(1) indicating if any of the elements in picks is delayed.,
For a single pick, such as datasets(), variables() or values(),
it checks if either choices or selected are delayed.
Is an object created using tidyselect
Description
choices and selected can be provided using tidyselect, (e.g. tidyselect::everything()
tidyselect::where(), tidyselect::starts_with()). These functions can't be called
independently but rather as an argument of function which consumes them.
.is_tidyselect safely determines if x can be evaluated with tidyselect::eval_select()
Usage
.is_tidyselect(x)
Arguments
x |
|
Value
logical(1)
Analyse selectors and concludes a merge parameters
Description
Analyse selectors and concludes a merge parameters
Usage
.merge_summary_list(selectors, join_keys)
Value
list containing:
mapping (
named list) containing selected values in each selector. Thismappingis sorted according to correct datasets merge order.variablescontains names of the variables inANLjoin_keys (
join_keys) updatedjoin_keyscontaining keys ofANL
Pick class constructor
Description
Create a pick object
Usage
.pick(
choices,
selected,
multiple = length(selected) > 1,
ordered = FALSE,
fixed = FALSE,
...
)
Arguments
choices |
( |
selected |
( |
multiple |
( |
ordered |
( |
fixed |
( |
... |
for for |
Value
pick generic object that is used by datasets(), variables() and values()
to create objects of corresponding classes.
pickerInput choices icons
Description
Icons describing a class of the choice
Usage
.picker_icon(x)
Arguments
x |
( |
Value
html-tag in form of character(1)
Resolve downstream after selected changes
Description
@description
When select input at position i changes:
All slots after position i in
picks_resolvedare reset to their unresolved (delayed) state, because later slots depend on earlier ones. Slots before and at position i are kept as-is. For example, changing variables (i=2) resets everything after it but keeps dataset (i=1) intact.The new selection replaces the old value at slot i.
Resolve is called, which evaluates only the slots that are still in an unresolved state.
The updated picks replace the current
reactiveValue. Thanks to this design reactive values are triggered only once
Usage
.resolve(selected, slot_name, picks_resolved, old_picks, data)
Arguments
selected |
( |
slot_name |
( |
picks_resolved |
( |
old_picks |
( |
data |
( |
Value
The result of changing the picks_resolved reactiveVal given as argument.
It returns NULL if it does nothing.
Update reactive values with log
Description
Update reactive values only if values differ to avoid unnecessary reactive trigger
Usage
.update_rv(rv, value, log)
Arguments
rv |
( |
value |
( |
log |
( |
Value
the result of reactiveVal update if new value is different, NULL otherwise.
Check if datasets can be merged in topological order
Description
Determines the topological order from join_keys, then checks that each dataset can be joined with at least one of the previously accumulated datasets.
Usage
.validate_join_keys(selectors, join_keys)
Arguments
selectors |
(
|
join_keys |
( |
Value
TRUE if validation passes, otherwise raises a validation
error with details on which datasets cannot be merged and why.
Convert data_extract_spec to picks
Description
Helper functions to ease transition between
teal.transform::data_extract_spec() and picks().
Usage
as.picks(x, quiet = FALSE)
teal_transform_filter(x, label = "Filter")
Arguments
x |
( |
quiet |
( |
label |
( |
Details
With introduction of picks, data_extract_spec will no longer serve a primary tool to
define variable choices and default selection in teal-modules and eventually data_extract_spec
will be deprecated.
To ease the transition to the new tool, we provide as.picks method which can handle 1:1
conversion from data_extract_spec to picks. Unfortunately, when data_extract_spec
contains filter_spec then as.picks is unable to provide reliable picks equivalent.
Value
A picks object when conversion is possible, otherwise NULL with a warning (if quiet = FALSE).
Examples
# convert des with eager select_spec
as.picks(
teal.transform::data_extract_spec(
dataname = "iris",
teal.transform::select_spec(
choices = c("Sepal.Length", "Sepal.Width", "Species"),
selected = c("Sepal.Length", "Species"),
multiple = TRUE,
ordered = TRUE
)
)
)
# convert des with delayed select_spec
as.picks(
teal.transform::data_extract_spec(
dataname = "iris",
teal.transform::select_spec(
choices = teal.transform::variable_choices("iris"),
selected = teal.transform::first_choice(),
multiple = TRUE,
ordered = TRUE
)
)
)
as.picks(
teal.transform::data_extract_spec(
dataname = "iris",
teal.transform::select_spec(
choices = teal.transform::variable_choices(
"iris",
subset = function(data) names(Filter(is.numeric, data))
),
selected = teal.transform::first_choice(),
multiple = TRUE,
ordered = TRUE
)
)
)
# teal_transform_module build on teal.transform
teal_transform_filter(
teal.transform::data_extract_spec(
dataname = "iris",
filter = teal.transform::filter_spec(
vars = "Species",
choices = c("setosa", "versicolor", "virginica"),
selected = c("setosa", "versicolor")
)
)
)
teal_transform_filter(
picks(
datasets(choices = "iris", select = "iris"),
variables(choices = "Species", "Species"),
values(
choices = c("setosa", "versicolor", "virginica"),
selected = c("setosa", "versicolor")
)
)
)
Drop-down badge
Description
Drop-down button in a form of a badge with bg-primary as default style
Clicking badge shows a drop-down containing any HTML element. Folded drop-down
doesn't trigger display output which means that items rendered using render*
will be recomputed only when drop-down is show.
Usage
badge_dropdown(id, label, content)
Arguments
id |
( |
label |
( |
content |
( |
Value
A shiny.tag object representing a drop-down badge component to display the options.
Fixed badge
Description
Fixed badge
Usage
badge_fixed(id, label, content)
Arguments
id |
( |
label |
( |
content |
( |
Value
A shiny.tag object representing a fixed badge component to display the selected option.
Checks varname argument and convert to call
Description
Checks varname type and parse if it's a character.
Usage
call_check_parse_varname(varname)
Arguments
varname |
( |
Value
the parsed varname.
Choices condition call
Description
Compose choices condition call from inputs.
Usage
call_condition_choice(varname, choices)
Arguments
varname |
( |
choices |
( |
Details
choices can be vector of any type but for some output might be converted:
-
factorcall is composed on choices converted tocharacter; -
Datecall is composed on choices converted tocharacterusingformat(choices); -
POSIXct,POSIXltcall is composed on choices converted tocharacterusingformat(choices).
One has to be careful here as formatted date-time variable might loose
some precision (see format argument in format.POSIXlt() and output call
could be insufficient for exact comparison. In this case one should specify
varname = trunc(<varname>) and possibly convert choices to character).
Value
call.
logical variable condition call
Description
Compose logical variable condition call from inputs.
Usage
call_condition_logical(varname, choice)
Arguments
varname |
( |
choice |
( |
Value
call.
numeric range condition call
Description
Compose numeric range condition call from inputs.
Usage
call_condition_range(varname, range)
Arguments
varname |
( |
range |
( |
Value
call.
Date range condition call
Description
Compose Date range condition call from inputs.
Usage
call_condition_range_date(varname, range)
Arguments
varname |
( |
range |
( |
Value
call.
POSIXct range condition call
Description
Compose POSIXct range condition call from inputs.
Usage
call_condition_range_posixct(varname, range, timezone = Sys.timezone())
Arguments
varname |
( |
range |
( |
timezone |
( |
Value
call.
Combine calls by operator
Description
Combine list of calls by specific operator.
Usage
calls_combine_by(operator, calls)
Arguments
operator |
( |
calls |
( |
Value
A combined call.
Assert level
Description
Assert level
Usage
check_last_level(x, class)
assert_last_level(x, class, .var.name = checkmate::vname(x), add = NULL)
Arguments
x |
|
class |
Class of the last element of picks |
.var.name |
[ |
add |
[ |
Value
For check_last_level a logical value or a string.
For assert_last_level invisibly the object checked or an error.
Examples
x <- picks(datasets(), variables(), values())
assert_last_level(x, "values")
A method that should take a type and resolve it.
Description
Generic that makes the minimal check on spec. Responsible of subsetting/extract the data received and check that the type matches
Usage
determine(x, data)
Arguments
x |
The specification to resolve. |
data |
The minimal data required. |
Value
A list with two elements, the type resolved and the data extracted.
Helper functions to check pick attributes
Description
Helper functions for pick objects generated from
datasets(), variables() or values():
-
is_pick_multiple()checks if a pick has themultipleattribute set toTRUE.
-
is_pick_fixed()checks if a pick has thefixedattribute set toTRUE.
-
is_pick_ordered()checks if a pick has theorderedattribute set toTRUE.
Usage
is_pick_multiple(x)
is_pick_fixed(x)
is_pick_ordered(x)
Arguments
x |
( |
Value
TRUE if the pick has the attribute set to TRUE,
FALSE otherwise.
Examples
p <- picks(datasets("iris"), variables(), values())
is_pick_multiple(p$variables)
is_pick_fixed(p$variables)
is_pick_ordered(p$variables)
Declare interaction variable pairs for tidyselect
Description
Used inside tidyselect expressions to declare a pair of variables that
interact with each other. The pair is recorded in the selection environment
and the positions of both variables within the available variables are
returned.
Usage
interaction_vars(
var1,
var2,
vars = tidyselect::peek_vars(fn = "interaction_vars")
)
Arguments
var1 |
An unquoted variable name. |
var2 |
An unquoted variable name that interacts with |
vars |
Character vector of available variable names, retrieved
automatically via |
Value
An integer vector of length 2 giving the positions of var1 and
var2 in vars, or NA where a variable is not found.
Examples
picks(
datasets("ADAE"),
variables(
c(AGE, RACE, interaction_vars("COUNTRY", "RACE")),
selected = "COUNTRY:RACE",
multiple = TRUE
),
values()
)
Merge Server Function for Dataset Integration
Description
merge_srv is a powerful Shiny server function that orchestrates the merging of multiple datasets
based on user selections from picks objects. It creates a reactive merged dataset (teal_data object)
and tracks which variables from each selector are included in the final merged output.
This function serves as the bridge between user interface selections (managed by selectors) and the actual data merging logic. It automatically handles:
Dataset joining based on join keys
Variable selection and renaming to avoid conflicts
Reactive updates when user selections change
Generation of reproducible R code for the merge operation
Usage
merge_srv(
id,
data,
selectors,
output_name = "anl",
join_fun = "dplyr::inner_join"
)
Arguments
id |
( |
data |
( |
selectors |
(
|
output_name |
( |
join_fun |
( |
Value
A list with two reactive elements:
-
dataAreactivereturning a teal.data::teal_data object containing the merged dataset. The merged dataset is named according tooutput_nameparameter. Theteal_dataobject includes:The merged dataset with all selected variables
Complete R code to reproduce the merge operation
Updated join keys reflecting the merged dataset structure
-
variablesAreactivereturning a named list mapping selector names to their selected variables in the merged dataset. The structure is:list(selector_name_1 = c("var1", "var2"), selector_name_2 = c("var3", "var4"), ...). Variable names reflect any renaming that occurred during the merge to avoid conflicts.
How It Works
The merge_srv function performs the following steps:
-
Receives Input Data: Takes a reactive
teal_dataobject containing source datasets with defined join keys -
Processes Selectors: Evaluates each selector (whether static
picksor reactive) to determine which datasets and variables are selected -
Determines Merge Order: Uses topological sort based on the
join_keysto determine the optimal order for merging datasets. -
Handles Variable Conflicts: Automatically renames variables when:
Multiple selectors choose variables with the same name from different datasets
Foreign key variables would conflict with existing variables
Renaming follows the pattern
{column-name}_{dataset-name}
-
Performs Merge: Generates and executes merge code that:
Selects only required variables from each dataset
Applies any filters defined in selectors
Joins datasets using specified join function and join keys
Maintains reproducibility through generated R code
-
Updates Join Keys: Creates new join key relationships for the merged dataset (
"anl") relative to remaining datasets in theteal_dataobject -
Tracks Variables: Keeps track of the variable names in the merged dataset
Usage Pattern
# In your Shiny server function
merged <- merge_srv(
id = "merge",
data = shiny::reactive(my_teal_data),
selectors = list(
selector1 = picks(...),
selector2 = shiny::reactive(picks(...))
),
output_name = "anl",
join_fun = "dplyr::left_join"
)
# Access merged data
merged_data <- merged$data() # teal_data object with merged dataset
anl <- merged_data[["anl"]] # The actual merged data.frame/tibble
# Get variable mapping
vars <- merged$variables()
# Returns: list(selector1 = c("VAR1", "VAR2"), selector2 = c("VAR3", "VAR4_ADSL"))
# Get reproducible code
code <- teal.code::get_code(merged_data)
Merge Logic Details
Dataset Order: Datasets are merged in topological order based on join keys. The first dataset acts as the "left" side of the join, and subsequent datasets are joined one by one.
Join Keys: The function uses join keys from the source teal_data object to determine:
Which datasets can be joined together
Which columns to use for joining (the
byparameter)Whether datasets need intermediate joins (not yet implemented)
Variable Selection: For each dataset being merged:
Selects user-chosen variables from selectors
Includes foreign key variables needed for joining (even if not explicitly selected)
Removes duplicate foreign keys after join (they're already in the left dataset)
Conflict Resolution: When variable names conflict:
Variables from later datasets get suffixed with
_datanameForeign keys that match are merged (not duplicated)
The mapping returned in
merge_varsreflects the final names
Integration with Selectors
merge_srv is designed to work with picks_srv() which creates selector objects:
# Create selectors in server
selectors <- picks_srv(
picks = list(
adsl = picks(...),
adae = picks(...)
),
data = data
)
# Pass to merge_srv
merged <- merge_srv(
id = "merge",
data = data,
selectors = selectors
)
See Also
-
picks_srv()for creating selectors -
teal.data::join_keys()for defining dataset relationships
Examples
# Complete example with CDISC data
library(teal.picks)
library(teal.data)
library(shiny)
# Prepare data with join keys
data <- teal_data()
data <- within(data, {
ADSL <- teal.data::rADSL
ADAE <- teal.data::rADAE
})
join_keys(data) <- default_cdisc_join_keys[c("ADSL", "ADAE")]
# Create Shiny app
ui <- fluidPage(
picks_ui("adsl", picks(datasets("ADSL"), variables())),
picks_ui("adae", picks(datasets("ADAE"), variables())),
verbatimTextOutput("code"),
verbatimTextOutput("vars")
)
server <- function(input, output, session) {
# Create selectors
selectors <- list(
adsl = picks_srv("adsl",
data = shiny::reactive(data),
picks = picks(datasets("ADSL"), variables())
),
adae = picks_srv("adae",
data = shiny::reactive(data),
picks = picks(datasets("ADAE"), variables())
)
)
# Merge datasets
merged <- merge_srv(
id = "merge",
data = shiny::reactive(data),
selectors = selectors,
output_name = "anl",
join_fun = "dplyr::left_join"
)
# Display results
output$code <- renderPrint({
cat(teal.code::get_code(merged$data()))
})
output$vars <- renderPrint({
merged$variables()
})
}
if (interactive()) {
shinyApp(ui, server)
}
Choices/selected settings
Description
Define choices and default selection for variables. picks allows app-developer to specify
datasets, variables and values to be selected by app-user during Shiny session.
Functions are based on the idea of choices/selected where app-developer provides choices
and what is selected by default. App-user changes selected interactively (see picks_module).
Usage
picks(..., check_dataset = TRUE)
datasets(choices = tidyselect::everything(), selected = 1L, fixed = NULL, ...)
variables(
choices = tidyselect::everything(),
selected = 1L,
multiple = NULL,
fixed = NULL,
ordered = FALSE,
...
)
values(
choices = function(x) !is.na(x),
selected = function(x) !is.na(x),
multiple = TRUE,
fixed = NULL,
...
)
Arguments
... |
for for |
check_dataset |
( |
choices |
( |
selected |
( |
fixed |
( |
multiple |
( |
ordered |
( |
Value
For picks() it returns an object of picks class, which is a list of pick objects with additional
attributes for Shiny interactivity.
For datasets(), variables(), and values() it returns a pick object with
class corresponding to the type of selection including the choices and selected values.
tidyselect support
Both choices and selected parameters support tidyselect syntax, enabling dynamic
and flexible variable selection patterns. This allows choices to be determined at runtime
based on data characteristics rather than hard-coded values.
Using tidyselect for choices and selected
When choices uses tidyselect, the available options are determined dynamically based on actually
selected data:
-
tidyselect::everything()- All variables/datasets -
tidyselect::starts_with("prefix")- Variables starting with a prefix -
tidyselect::ends_with("suffix")- Variables ending with a suffix -
tidyselect::contains("pattern")- Variables containing a pattern -
tidyselect::matches("regex")- Variables matching a regular expression -
tidyselect::where(predicate)- Variables/datasets satisfying a predicate function -
tidyselect::all_of(vars)- All specified variables (error if missing) -
tidyselect::any_of(vars)- Any specified variables (silent if missing) Range selectors like
Sepal.Length:Petal.Width- Variables between two positionsInteger indices (e.g.,
1L,1L:3L,c(1L, 3L, 5L)) - Select by position. Be careful, must be integer!
The selected parameter can use the same syntax but it will be applied to the subset defined in choices. This
means that choices = is.numeric, selected = is.factor or choices = c("a", "b", "c"), selected = c("d", "e")
will imply en empty selected.
Warning: Using explicit character values for selected with dynamic choices may
cause issues if the selected values are not present in the dynamically determined choices.
Prefer using numeric indices (e.g., 1 for first variable) when choices is dynamic.
Structure and element dependencies
The picks() function creates a hierarchical structure where elements depend on their
predecessors, enabling cascading reactive updates during Shiny sessions.
Element hierarchy
A picks object must follow this order:
-
datasets()- to select a dataset. Always the first element (required). -
variables()- To select columns from the chosen dataset. -
values()- To select specific values from the chosen variable(s).
Each element's choices are evaluated within the context of its predecessor's selection.
How dependencies work
-
Fixed dataset: When
datasets(choices = "iris")specifies one dataset, thevariables()choices are evaluated against that dataset columns. -
Multiple dataset choices: When
datasets(choices = c("iris", "mtcars"))allows multiple options,variables()choices are re-evaluated each time the user selects a different dataset. This creates a reactive dependency where variable choices update automatically. -
Dynamic dataset choices: When using
datasets(choices = tidyselect::where(is.data.frame)), all available data frames are discovered at runtime, and variable choices adapt to whichever dataset the user selects. -
Variable to values: Similarly,
values()choices are evaluated based on the selected variable(s), allowing users to filter specific levels or values. When multiple variables are selected, then values will be a concatenation of the columns.
Best practices
Always start with
datasets()- this is enforced by validationUse dynamic
choicesinvariables()when working with multiple datasets to ensure compatibility across different data structuresPrefer
tidyselect::everything()ortidyselect::where()predicates for flexible variable selection that works across datasets with different schemasUse numeric indices for
selectedwhenchoicesare dynamic to avoid referencing variables that may not exist in all datasets
Important: values() requires type-aware configuration
Why values() is different from datasets() and variables()
datasets() and variables() operate on named lists of objects, meaning they work with character-based
identifiers. This allows you to use text-based selectors like starts_with("S") or contains("prefix")
consistently for both datasets and variable names.
values() is fundamentally different because it operates on the actual data content within a
selected variable (column). The type of data in the column determines what kind of filtering makes sense:
-
numericcolumns (e.g.,age,height,price) contain numbers -
character/factorcolumns (e.g.,country,category,status) contain categorical values -
Date/POSIXctcolumns contain temporal data -
logicalcolumns contain TRUE/FALSE values
Type-specific UI controls
The values() function automatically renders different UI controls based on data type:
-
numericdata: Creates asliderInputfor range selection-
choicesmust be a numeric vector of length 2:c(min, max) -
selectedmust be a numeric vector of length 2:c(selected_min, selected_max)
-
-
Categorical data (
character/factor): Creates apickerInputfor discrete selection-
choicescan be a character vector or predicate function -
selectedcan be specific values or a predicate function
-
-
Date/POSIXctdata: Creates date/datetime range selectors-
choicesmust be a Date orPOSIXctvector of length 2
-
-
logicaldata: Creates a checkbox or picker for TRUE/FALSE selection
Developer responsibility
App developers must ensure values() configuration matches the variable type:
-
Know your data: Understand what type of variable(s) users might select
-
Configure appropriately: Set
choicesandselectedto match expected data types -
Use predicates for flexibility: When variable type is dynamic, use predicate functions like
function(x) !is.na(x)(the default) to handle multiple types safely
Examples of correct usage
# For a numeric variable (e.g., age)
picks(
datasets(choices = "demographic"),
variables(choices = "age", multiple = FALSE),
values(choices = c(0, 100), selected = c(18, 65))
)
# For a categorical variable (e.g., country)
picks(
datasets(choices = "demographic"),
variables(choices = "country", multiple = FALSE),
values(choices = c("USA", "Canada", "Mexico"), selected = "USA")
)
# Safe approach when variable type is unknown - use predicates
picks(
datasets(choices = "demographic"),
variables(choices = tidyselect::everything(), selected = 1L),
values(choices = function(x) !is.na(x), selected = function(x) !is.na(x))
)
Common mistakes to avoid
# WRONG: Using string selectors for numeric data
values(choices = starts_with("5")) # Doesn't make sense for numeric data!
# WRONG: Providing categorical choices for a numeric variable
values(choices = c("low", "medium", "high")) # Won't work if variable is numeric!
# WRONG: Providing numeric range for categorical variable
values(choices = c(0, 100)) # Won't work if variable is factor/character!
Example: Three-level hierarchy
picks(
datasets(choices = c("iris", "mtcars"), selected = "iris"),
variables(choices = tidyselect::where(is.numeric), selected = 1L),
values(choices = tidyselect::everything(), selected = seq_len(10))
)
In this example:
User first selects a dataset (
irisormtcars)Variable choices update to show only numeric columns from selected dataset
After selecting a variable, value choices show all unique values from that column
Examples
# Select columns from iris dataset using range selector
picks(
datasets(choices = "iris"),
variables(choices = Sepal.Length:Petal.Width, selected = 1L)
)
# Single variable selection from iris dataset
picks(
datasets(choices = "iris", selected = "iris"),
variables(choices = c("Sepal.Length", "Sepal.Width"), selected = "Sepal.Length", multiple = FALSE)
)
# Dynamic selection: any variable from iris, first selected by default
picks(
datasets(choices = "iris", selected = "iris"),
variables(choices = tidyselect::everything(), selected = 1L, multiple = FALSE)
)
# Multiple dataset choices: variable choices will update when dataset changes
picks(
datasets(choices = c("iris", "mtcars"), selected = "iris"),
variables(choices = tidyselect::everything(), selected = 1L, multiple = FALSE)
)
# Select from any dataset, filter by numeric variables
picks(
datasets(choices = c("iris", "mtcars"), selected = 1L),
variables(choices = tidyselect::where(is.numeric), selected = 1L)
)
# Fully dynamic: auto-discover datasets and variables
picks(
datasets(choices = tidyselect::where(is.data.frame), selected = 1L),
variables(choices = tidyselect::everything(), selected = 1L, multiple = FALSE)
)
# Select categorical variables with length constraints
picks(
datasets(choices = tidyselect::everything(), selected = 1L),
variables(choices = is_categorical(min.len = 2, max.len = 15), selected = seq_len(2))
)
Interactive picks
Description
Creates UI and server components for interactive picks() in Shiny modules. The module is based on
configuration provided via picks() and its responsibility is to determine relevant input
values
The module supports both single and combined picks:
Single
picksobjects for a single inputNamed lists of
picksobjects for multiple inputs
Usage
picks_ui(id, picks, container = "badge_dropdown")
## S3 method for class 'list'
picks_ui(id, picks, container)
## S3 method for class 'picks'
picks_ui(id, picks, container)
picks_srv(id = "", picks, data)
## S3 method for class 'list'
picks_srv(id, picks, data)
## S3 method for class 'picks'
picks_srv(id, picks, data)
Arguments
id |
( |
picks |
( |
container |
( |
data |
( |
Details
The module uses S3 method dispatch to handle different ways to provide picks:
-
.picksmethods handle single 'picks“ object -
.listmethods handle multiplepicksobjects
The UI component (picks_ui) creates the visual elements, while the
server component (picks_srv) manages the reactive logic,
Value
-
picks_ui(): UI elements for the input controls -
picks_srv(): Server-side reactive logic returning the processed data
See Also
picks() for creating 'picks“ objects
Examples
library(shiny)
example_pick <- picks(
datasets("ADSL"),
variables(selected = c("SEX", "COUNTRY", "ARMCD"))
)
ui <- fluidPage(
picks_ui("my_picks", picks = example_pick),
h4("Resolved picks:"),
verbatimTextOutput("result"),
h4("Table:"),
tableOutput("table")
)
server <- function(input, output, session) {
data <- teal.data::teal_data("ADSL" = teal.data::rADSL)
teal.data::join_keys(data) <- teal.data::default_cdisc_join_keys["ADSL"]
selectors <- picks_srv(
picks = list(my_picks = example_pick),
data = reactive(data)
)
anl <- merge_srv("merge", data = reactive(data), selectors = selectors)
output$result <- renderPrint(cat(gsub("\033\\[[0-9;]*m", "", format(selectors$my_picks()))))
output$table <- renderTable(anl$data()$anl)
}
if (interactive()) {
shinyApp(ui, server)
}
Select a range
Description
Helper to work with ranges. Setting choices or selected to range using
ranged() in any of them will automatically create a numeric, Date or POSIXct
input to filter. variables(choices) must only refer to numeric, Date, or POSIXct
columns. An informative error is raised if the resolved column type is unsupported.
Usage
ranged(min = -Inf, max = Inf)
Arguments
min |
( |
max |
( |
Value
A function that allows the use of a range in choices or selected of values() in
numeric, Date, or POSIXct variables.
Examples
p <- picks(
datasets(choices = "mtcars"),
variables(choices = is.numeric, selected = 1),
values(choices = ranged(), ranged(20, 30))
)
resolver(data = list("mtcars label" = mtcars), x = p)
Resolve picks
Description
Resolve iterates through each picks element and determines values .
Usage
resolver(x, data)
Arguments
x |
( |
data |
( |
Value
resolved picks.
Examples
x <- picks(datasets(tidyselect::where(is.data.frame)), variables("a", "a"))
data <- list(
df1 = data.frame(a = as.factor(LETTERS[1:5]), b = letters[1:5]),
df2 = data.frame(a = LETTERS[1:5], b = 1:5),
m = matrix()
)
resolver(x = x, data = data)
Restore value from bookmark.
Description
Get value from bookmark or return default.
Usage
restoreValue(value, default)
Arguments
value |
( |
default |
fallback value |
Details
Bookmarks can store not only inputs but also arbitrary values.
These values are stored by onBookmark callbacks and restored by onBookmarked callbacks,
and they are placed in the values environment in the session$restoreContext field.
Using teal_data_module makes it impossible to run the callbacks
because the app becomes ready before modules execute and callbacks are registered.
In those cases the stored values can still be recovered from the session object directly.
Note that variable names in the values environment are prefixed with module name space names,
therefore, when using this function in modules, value must be run through the name space function.
Value
In an application restored from a server-side bookmark,
the variable specified by value from the values environment.
Otherwise default.
tidyselect helpers
Description
#'
Predicate functions simplifying
picks specification.
Usage
is_categorical(min.len, max.len)
Arguments
min.len |
( |
max.len |
( |
Value
A tidyselector that can be used directly in choices or selected of variables() in picks().
Examples
# select factor column but exclude foreign keys
variables(choices = is_categorical(min.len = 2, max.len = 10))
# Supports tidyselect helpers, e.g. to select all categorical variables with 2 to 10 unique values
dplyr::select(iris, dplyr::where(is_categorical(2, 10)))
p <- picks(
datasets(is.data.frame, 2L),
variables(is_categorical(2, 10))
)
resolver(data = list(mtcars = mtcars, iris = iris), x = p)
Merge module
Description
Example teal::module containing interactive inputs and displaying results of merge.
Usage
tm_merge(label = "merge-module", picks, transformators = list())
Arguments
label |
( |
picks |
( |
transformators |
( |
Value
A teal::module object that merges datasets based on user selections and displays the results.
Examples
library(teal)
data <- within(teal.data::teal_data(), {
iris <- iris
mtcars <- mtcars
})
app <- init(
data = data,
modules = modules(
modules(
label = "Testing modules",
tm_merge(
label = "non adam",
picks = list(
a = picks(
datasets("iris", "iris"),
variables(
choices = c("Sepal.Length", "Species"),
selected = "Sepal.Length"
),
values()
)
)
)
)
)
)
if (interactive()) {
shinyApp(app$ui, app$server, enableBookmarking = "server")
}