tte_integration.Rmd
The TTE (time-to-event) modules are {tidymodules}
, which are R6 classes. The TTE collection of modules features three main modules:
If you are integrating this into a project you generally will not need the Mapping module as you will already know which variables you will be including in your models. The mapping module is useful if you want to load multiple data sets that have inconsistent naming schemes, such as ADaM and NOVDD.
Before including these in your application it is good to be familiar with standard Shiny modules. A good introduction is available here: https://shiny.rstudio.com/articles/modules.html
The TTE Module features include:
We can run this example with the following code:
There are a few main parts that are different from regular Shiny modules. The first step is that we need to initialize the module with
library(subpat)
#> Loading required package: bs4Dash
#>
#> Attaching package: 'bs4Dash'
#> The following object is masked from 'package:graphics':
#>
#> box
#> Loading required package: tidymodules
#> Loading required package: shiny
#>
#> Attaching package: 'shiny'
#> The following objects are masked from 'package:bs4Dash':
#>
#> column, tabPanel, tabsetPanel, updateTabsetPanel
#> Loading required package: shinyBS
#> subpat is NOT VALIDATED, and should be reserved for exploratory analysis only.
tteModule <- TTE$new()
We can optionally give our module an id by passing id = my_id
as a parameter to new
. The module will dynamically create an id if we do not specify one. We can see what the module looks like by printing it
tteModule
#> Module Namespace TTE-1
#> Module Session global_session
#> - Class TTE << TidyModule << R6
#> - Input [4]
#> (1) data => Empty
#> (2) mapping => Empty
#> (3) subgroups => Empty
#> (4) options => Empty
#> - Output [0]
Here we can see the namespace that was generated, the input ports and the output ports. You can think of the input ports as the parameters to a function. The output ports are the values that are returned from the module. Here we can see that there is nothing being returned, since this module just displays data. We can refer to the input or output ports by name or by number. In the TTE modules, options is always the last input port.
The next step is to call our module somewhere in the server function:
This is identical to using Shiny’s callModule
function except that we do not have to keep track of the id of the module.
The next step is to pass data and options into our module. There are two ways to pass data into a TidyModule: through pipes, and explictly. The elegant way to do this with tidymodules (and why is is named tidy modules), is through pipes. The basic formula to pass data into a module is my_reactive %>j% MyModule
. This will pass the my_reactive
reactive value into the jth input port of MyModule
. Let’s try this with the TTE module:
# Create a reactive of the NCCTG Lung Cancer Data Set from the survival package
data_reactive <- reactive({
survival::lung
})
# Pass the data into the TTE module
# This needs to be in a server function and reactive context:
# E.g: isolate, observe, observeEvent, etc.
isolate({
data_reactive %>1% tteModule
})
Now we have the data passed into the module. Currently the module will not do much since it expects the mapping
parameter to be provided. The mapping is a reactive list of values that map the variables from your data set into the correct parameter. The parameters are:
time
event
treatment
strata
parameter
parameter_value
population
aval_conv
# Set the variable names to use in the model
# See the information about the variables with
# help(lung)
mapping <- reactive({
list(
time = 'time',
event = 'status',
treatment = 'sex',
# Conversion factor: makes the time number of months.
aval_conv = 30.34
)
})
# Pass the mapping into the second input port
isolate({
mapping %>2% tteModule
})
We can also pass options into the module in a similar way. Options expects a reactive function. There are two options that we can pass into the module:
makePlotly
Should the graph be interactive via plotly? Note, enabling this is experimental and the survival plots do not always look great. Default: FALSE
conftype
The confidence interval type. Choice between: “none”, “plain”, “log”, or “log-log”. Default: “log-log”options <- reactive(list(
makePlotly = FALSE,
conftype = "log-log"
))
isolate({
options %>4% tteModule
})
That’s all you need to include the TTE module in your application. The full application is available below:
library(shiny)
library(subpat)
library(tidymodules)
tteModule <- TTE$new()
ui <- fluidPage(
h2("Time-to-event Analysis of NCCTG Lung Cancer Data"),
tteModule$standardUi()
)
server <- function(input, output, session) {
# Set the variable names to use in the model
mapping <- reactive({
list(
time = 'time',
event = 'status',
treatment = 'sex',
# Conversion factor: makes the time number of months.
aval_conv = 30.34,
# Included are some other parameters that we can set
# For this example, we set them to null
# The comments show some common values ADaM data sets
strata = NULL, # c('STRVAL1', 'STRVAL2'),
parameter = NULL, # 'PARAM',
parameter_value = NULL, # 'Progression free Survival',
population = NULL# "FASFL"
)
})
# Here are some general options for the module
options <- reactive(list(
# Do you want the graph interactive?
makePlotly = FALSE,
# Confidence interval type
# Options: log-log (SAS default), "log", "none", "plain"
# See help on survival::survfit.formula for more information
conftype = "log-log"
))
# We need to call the callModule() method of the tidymodule
tteModule$callModule()
# Here you want to load your data in some way
# In this example, we just wrap the `lung` dataset from the survival package
data_reactive <- reactive({
survival::lung
})
observe({
# Pass the data into the TTE module
# The pipe %>1% means pass the reactive into the first input of TTE module (the data)
data_reactive %>1% tteModule
# Pass the mapping into the TTE module
# The pipe %>2% means pass the reactive into the second input of the module
mapping %>2% tteModule
# Pass our options into the TTE module
options %>4% tteModule
})
}
# Run the application
shinyApp(ui = ui, server = server)
The subgroup module is currently a prototype, which is not as full featured as I would like. If you would like to test it out anyway, the code is easy to integrate into your own application.
library(shiny)
library(subpat)
library(bs4Dash)
library(tidymodules)
subgroupManagerModule <- SubgroupManager$new()
ui <- tagList(
shinyjs::useShinyjs(),
bs4DashPage(
sidebar = bs4DashSidebar(disable = TRUE),
body = bs4DashBody(
subgroupManagerModule$ui(),
verbatimTextOutput('subgroupSummary')
)
)
)
server <- function(input, output, session) {
subgroupManagerModule$callModule()
observe({
reactive(mtcars) %>1% subgroupManagerModule
})
output$subgroupSummary <- renderPrint({
print("Subgroups:")
print(summary(mod(1)$execOutput("subgroups")))
})
}
# Run the application
shinyApp(ui = ui, server = server)