Data extract
NEST coreDev
2022-05-03
data-extract.Rmd
There are times when an app developer wants to showcase more than
just one fixed slice of their dataset in their custom module.
Relinquishing control of the application to a user demands the developer
gives their users a degree of freedom. In case of analyzing data,
teal
allows app developers to open up their applications to
users, letting them decide exactly what app data to analyze in the
module.
A lot of teal
modules use data_extract_spec
objects and modules to tackle user input. You can find many examples in
e.g. teal.modules.general
and
teal.modules.clinical
.
data_extract_spec
data_extract_spec
’s task is two-fold: create a UI
component in a shiny
application and pass the user input
from the UI to the module itself. Having that formulated, let’s have a
look at how it supports both its responsibilities.
Example module
In order to showcase different initialization options of
data_extract_spec
, first we define a shiny
module which uses data_extract_ui
and
data_extract_srv
designed to handle
data_extract_spec
objects. The module creates a UI
component for single data_extract_spec
and prints a list of
values returned from data_extract_srv
module. Please see
package documentation for more information about
data_extract_ui
and data_extract_srv
.
library(teal.transform)
#> Loading required package: magrittr
library(shiny)
extract_ui <- function(id, data_extract) {
ns <- NS(id)
teal.widgets::standard_layout(
output = teal.widgets::white_small_well(verbatimTextOutput(ns("output"))),
encoding = data_extract_ui(ns("data_extract"), label = "variable", data_extract)
)
}
extract_srv <- function(id, datasets, data_extract) {
moduleServer(id, function(input, output, session) {
reactive_extract_input <- data_extract_srv("data_extract", datasets, data_extract)
s <- reactive({
format_data_extract(reactive_extract_input())
})
output$output <- renderPrint({
cat(s())
})
})
}
Example data
teal.transform
functions depend on a
FilteredData
object from the teal.slice
package. Normally, FilteredData
is created automatically by
teal::init
,
but for example purposes we define a wrapper function to initialize the
necessary object.
sample_filtered_data <- function() {
# create TealData
adsl <- teal.data::cdisc_dataset("ADSL", scda::synthetic_cdisc_data("latest")$adsl)
adtte <- teal.data::cdisc_dataset("ADTTE", scda::synthetic_cdisc_data("latest")$adtte)
data <- teal.data::cdisc_data(adsl, adtte)
# covert TealData to FilteredData
datasets <- teal.slice:::filtered_data_new(data)
teal.slice:::filtered_data_set(data, datasets)
datasets
}
datasets <- sample_filtered_data()
Consider the following example, where we create two UI elements, one
to filter on a specific level from SEX
variable, and a
second one to select a variable from c("BMRKR1", "AGE")
.
data_extract_spec
object is handed over to the shiny app
and gives instructions to generate UI components.
simple_des <- data_extract_spec(
dataname = "ADSL",
filter = filter_spec(vars = "SEX", choices = c("F", "M")),
select = select_spec(choices = c("BMRKR1", "AGE"))
)