diff --git a/inst/design/basic_concept.drawio b/inst/design/basic_concept.drawio
new file mode 100644
index 00000000..851014e5
--- /dev/null
+++ b/inst/design/basic_concept.drawio
@@ -0,0 +1,475 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vignettes/data-extract-merge.Rmd b/vignettes/data-extract-merge.Rmd
index 85ba37f5..dd34f573 100644
--- a/vignettes/data-extract-merge.Rmd
+++ b/vignettes/data-extract-merge.Rmd
@@ -17,28 +17,63 @@ knitr::opts_chunk$set(
)
```
-`teal.transform` provides `merge_expression_srv`, which converts `data_extract_srv` into `R` expressions to transform data
-for analytical purposes.
-For example, you may wish to select `AGE` from `ADSL` and select `AVAL` from `ADTTE`, filtered for rows where `PARAMCD` is `OS`, and then merge the results using the primary keys to create an analysis dataset `ANL`.
-This diagram illustrates the concept:
+`teal.transform` allows the app user to oversee transforming a relational set of data objects into the final dataset for analysis.
+User actions create a R expression that subsets and merges the input data.
-```{r echo=FALSE, out.width='100%'}
-knitr::include_graphics("./images/data_extract_spec/basic_concept.png")
-```
+In the following example we will create an analysis dataset `ANL` by:
-In the following code block, we create a `data_extract_spec` object for each dataset, as illustrated above.
+1. Selecting the column `AGE` from `ADSL`
+2. Selecting the column `AVAL` and filtering the rows where `PARAMCD` is `OS` from `ADTTE`
+3. Merging the results from the above datasets using the primary keys.
+
+
+
+Note that primary key columns are maintained when selecting columns from datasets.
+
+Let's see how to achieve this dynamic `select`, `filter`, and `merge` operations in a `shiny` app using `teal.transform`.
+
+#### Step 1/5 - Preparing the Data
```{r}
library(teal.transform)
-library(teal.widgets)
library(teal.data)
library(shiny)
+# Define data.frame objects
+ADSL <- teal.transform::rADSL
+ADTTE <- teal.transform::rADTTE
+
+# create a list of reactive data.frame objects
+datasets <- list(
+ ADSL = reactive(ADSL),
+ ADTTE = reactive(ADTTE)
+)
+
+# create join_keys
+join_keys <- join_keys(
+ join_key("ADSL", "ADSL", c("STUDYID", "USUBJID")),
+ join_key("ADSL", "ADTTE", c("STUDYID", "USUBJID")),
+ join_key("ADTTE", "ADTTE", c("STUDYID", "USUBJID", "PARAMCD"))
+)
+```
+
+
+#### Step 2/5 - Creating data extract specifications
+
+In the following code block, we create a `data_extract_spec` object for each dataset, as illustrated above.
+It is created by the `data_extract_spec()` function which takes in four arguments:
+
+1. `dataname` is the name of the dataset to be extracted.
+2. `select` helps specify the columns from which we wish to allow the app user to select. It can be generated using the function `select_spec()`. In the case of `ADSL`, we restrict the selection to `AGE`, `SEX`, and `BMRKR1`, with `AGE` being the default selection.
+3. `filter` helps specify the values of a variable we wish to filter during extraction. It can be generated using the function `filter_spec()`. In the case of `ADTTE`, we filter the variable `PARAMCD` by allowing users to choose from `CRSD`, `EFS`, `OS`, and `PFS`, with `OS` being the default filter.
+4. `reshape` is a boolean which helps to specify if the data needs to be reshaped from long to wide format. By default it is set to `FALSE`.
+
+```{r}
adsl_extract <- data_extract_spec(
dataname = "ADSL",
select = select_spec(
label = "Select variable:",
- choices = c("AGE", "BMRKR1"),
+ choices = c("AGE", "SEX", "BMRKR1"),
selected = "AGE",
multiple = TRUE,
fixed = FALSE
@@ -48,7 +83,7 @@ adsl_extract <- data_extract_spec(
adtte_extract <- data_extract_spec(
dataname = "ADTTE",
select = select_spec(
- choices = c("AVAL", "ASEQ"),
+ choices = c("AVAL", "AVALC", "ASEQ"),
selected = "AVAL",
multiple = TRUE,
fixed = FALSE
@@ -63,34 +98,49 @@ adtte_extract <- data_extract_spec(
data_extracts <- list(adsl_extract = adsl_extract, adtte_extract = adtte_extract)
```
-#### Example module
+#### Step 3/5 - Creating the UI
-Here, we define the `merge_ui` and `merge_srv` functions, which will be used to create the UI and the server
-components of the `shiny` app, respectively.
+Here, we define the `merge_ui` function, which will be used to create the UI components for the `shiny` app.
+
+Note that we take in the list of `data_extract` objects as input, and make use of the `data_extract_ui` function to create our UI.
```{r}
merge_ui <- function(id, data_extracts) {
ns <- NS(id)
- standard_layout(
- output = white_small_well(
+ sidebarLayout(
+ sidebarPanel(
+ h3("Encoding"),
+ div(
+ data_extract_ui(
+ ns("adsl_extract"), # must correspond with data_extracts list names
+ label = "ADSL extract",
+ data_extracts[[1]]
+ ),
+ data_extract_ui(
+ ns("adtte_extract"), # must correspond with data_extracts list names
+ label = "ADTTE extract",
+ data_extracts[[2]]
+ )
+ )
+ ),
+ mainPanel(
+ h3("Output"),
verbatimTextOutput(ns("expr")),
dataTableOutput(ns("data"))
- ),
- encoding = div(
- data_extract_ui(
- ns("adsl_extract"), # must correspond with data_extracts list names
- label = "ADSL extract",
- data_extracts[[1]]
- ),
- data_extract_ui(
- ns("adtte_extract"), # must correspond with data_extracts list names
- label = "ADTTE extract",
- data_extracts[[2]]
- )
)
)
}
+```
+#### Step 4/5 - Creating the Server Logic
+
+Here, we define the `merge_srv` function, which will be used to create the server logic for the `shiny` app.
+
+This function takes as arguments the datasets (as a list of reactive `data.frame`), the data extract specifications created above (the `data_extract` list), and the `join_keys` object (read more about the `join_keys` in the [Join Keys vignette of `teal.data`](https://insightsengineering.github.io/teal.data/latest-tag/articles/join-keys.html)).
+We make use of the `merge_expression_srv` function to get a reactive list containing merge expression and information needed to perform the transformation - see more in `merge_expression_srv` documentation.
+We print this expression in the UI and also evaluate it to get the final `ANL` dataset which is also displayed as a table in the UI.
+
+```{r}
merge_srv <- function(id, datasets, data_extracts, join_keys) {
moduleServer(id, function(input, output, session) {
selector_list <- data_extract_multiple_srv(data_extracts, datasets, join_keys)
@@ -111,39 +161,9 @@ merge_srv <- function(id, datasets, data_extracts, join_keys) {
}
```
-Output from `data_extract_srv` (`reactive`) should be passed to `merge_expression_srv` together with `datasets`
-(list of reactive `data.frame` objects) and `join_keys` object.
-`merge_expression_srv` returns a reactive list containing merge expression and information needed to perform the transformation - see more in `merge_expression_srv` documentation.
-
-#### Example data
-
-The `data_extract_srv` module depends on a list of reactive or non-reactive `data.frame` objects.
-Here, we demonstrate the usage of a list of reactive `data.frame` objects as input to `datasets`,
-along with a list of necessary join keys per `data.frame` object:
-
-
-```{r}
-# Define data.frame objects
-ADSL <- teal.transform::rADSL
-ADTTE <- teal.transform::rADTTE
-
-# create a list of reactive data.frame objects
-datasets <- list(
- ADSL = reactive(ADSL),
- ADTTE = reactive(ADTTE)
-)
-
-# create join_keys
-join_keys <- join_keys(
- join_key("ADSL", "ADSL", c("STUDYID", "USUBJID")),
- join_key("ADSL", "ADTTE", c("STUDYID", "USUBJID")),
- join_key("ADTTE", "ADTTE", c("STUDYID", "USUBJID", "PARAMCD"))
-)
-```
-
-#### Shiny app
+#### Step 5/5 - Creating the `shiny` App
-Finally, we include `merge_ui` and `merge_srv` to the UI and server component of the `shinyApp`, respectively,
+Finally, we include `merge_ui` and `merge_srv` in the UI and server components of the `shinyApp`, respectively,
using the `data_extract`s defined in the first code block and the `datasets` object:
```{r eval=FALSE}
@@ -154,3 +174,5 @@ shinyApp(
}
)
```
+
+
diff --git a/vignettes/data-extract.Rmd b/vignettes/data-extract.Rmd
index 416b0061..9116c03e 100644
--- a/vignettes/data-extract.Rmd
+++ b/vignettes/data-extract.Rmd
@@ -17,13 +17,11 @@ knitr::opts_chunk$set(
)
```
-There are times when an app developer wants to offer users more flexibility in analyzing data within their custom module.
-In such cases, relinquishing control of the application to users requires developers to provide a degree of freedom.
With `teal`, app developers can open up their applications to users, allowing them to decide exactly which app data to
analyze within the module.
-Many `teal` modules leverage `data_extract_spec` objects and modules to handle user input.
-Examples can be found in `teal.modules.general` and `teal.modules.clinical`.
+A `teal` module can leverage the use of `data_extract_spec` objects to handle and process the user input.
+Examples can be found in the [modules from the `teal.modules.clinical` package](https://insightsengineering.github.io/teal.modules.clinical/latest-tag/reference/index.html).
### `data_extract_spec`
@@ -31,48 +29,13 @@ The role of `data_extract_spec` is twofold: to create a UI component in a `shiny
from the UI to the module itself.
Let's delve into how it fulfills both of these responsibilities.
-#### Example module
-
-To demonstrate different initialization options of `data_extract_spec`, let's first define a `shiny` module that
-utilizes `data_extract_ui` and `data_extract_srv` to handle `data_extract_spec` objects.
-This module creates a UI component for a single `data_extract_spec` and prints a list of values returned from the `data_extract_srv` module.
-For more information about `data_extract_ui` and `data_extract_srv`, please refer to the package documentation.
+#### Step 1/4 - Preparing the Data
```{r}
library(teal.transform)
-library(teal.widgets)
library(teal.data)
library(shiny)
-extract_ui <- function(id, data_extract) {
- ns <- NS(id)
- standard_layout(
- output = white_small_well(verbatimTextOutput(ns("output"))),
- encoding = data_extract_ui(ns("data_extract"), label = "variable", data_extract)
- )
-}
-
-extract_srv <- function(id, datasets, data_extract, join_keys) {
- moduleServer(id, function(input, output, session) {
- reactive_extract_input <- data_extract_srv("data_extract", datasets, data_extract, join_keys)
- s <- reactive({
- format_data_extract(reactive_extract_input())
- })
- output$output <- renderPrint({
- cat(s())
- })
- })
-}
-```
-
-
-#### Example data
-
-The `data_extract_srv` module depends on a list of reactive or non-reactive `data.frame` objects.
-Here, we demonstrate the usage of a list of reactive `data.frame` objects as input to `datasets`,
-along with a list of necessary join keys per `data.frame` object:
-
-```{r}
# Define data.frame objects
ADSL <- teal.transform::rADSL
ADTTE <- teal.transform::rADTTE
@@ -90,6 +53,8 @@ join_keys <- join_keys(
)
```
+#### Step 2/4 - Creating a `data_extract_spec` Object
+
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.
@@ -102,7 +67,42 @@ simple_des <- data_extract_spec(
)
```
-#### Shiny app
+#### Step 3/4 - Creating the `shiny` UI and Server Modules
+
+To demonstrate different initialization options of `data_extract_spec`, let's first define a `shiny` module that
+utilizes `data_extract_ui` and `data_extract_srv` to handle `data_extract_spec` objects.
+This module creates a UI component for a single `data_extract_spec` and prints a list of values returned from the `data_extract_srv` module.
+For more information about `data_extract_ui` and `data_extract_srv`, please refer to the package documentation.
+
+```{r}
+extract_ui <- function(id, data_extract) {
+ ns <- NS(id)
+ sidebarLayout(
+ sidebarPanel(
+ h3("Encoding"),
+ data_extract_ui(ns("data_extract"), label = "variable", data_extract)
+ ),
+ mainPanel(
+ h3("Output"),
+ verbatimTextOutput(ns("output"))
+ )
+ )
+}
+
+extract_srv <- function(id, datasets, data_extract, join_keys) {
+ moduleServer(id, function(input, output, session) {
+ reactive_extract_input <- data_extract_srv("data_extract", datasets, data_extract, join_keys)
+ s <- reactive({
+ format_data_extract(reactive_extract_input())
+ })
+ output$output <- renderPrint({
+ cat(s())
+ })
+ })
+}
+```
+
+#### Step 4/4 - Creating the `shiny` App
Finally, we include `extract_ui` in the UI of the `shinyApp`, and utilize `extract_srv` in the server function of the `shinyApp`:
@@ -114,3 +114,5 @@ shinyApp(
}
)
```
+
+
diff --git a/vignettes/data-merge.Rmd b/vignettes/data-merge.Rmd
index 4f2cee18..8552d7c0 100644
--- a/vignettes/data-merge.Rmd
+++ b/vignettes/data-merge.Rmd
@@ -17,16 +17,14 @@ knitr::opts_chunk$set(
)
```
-Combining datasets is an essential step when working with modules that involve multiple datasets.
-Within the context of `teal`, we use the term "merge" to refer to the process of combining datasets.
-To support this, two functions are provided: `merge_expression_module` and `merge_expression_srv`, each tailored for different use cases.
+Joining datasets is an essential step when working with relational datasets.
-Use `merge_expression_module` when there is no need to process the `data_extract` list.
+To support this, two functions are provided depending on how to process the `data_extract_spec` object:
+
+1. `merge_expression_module` can be used when there is no need to process the list of `data_extract_spec`.
This function reads the data and the list of `data_extract_spec` objects and applies the merging.
-Essentially, it serves as a wrapper that combines `data_extract_multiple_srv()` and `merge_expression_srv()`.
-Further details are provided below.
-In scenarios where additional processing of the `data_extract` list is necessary,
-`merge_expression_srv()` can be used along with `data_extract_multiple_srv()` or `data_extract_srv()` to customize the `selector_list` input.
+Essentially, it serves as a wrapper that combines `data_extract_multiple_srv()` and `merge_expression_srv()`.
+2. `merge_expression_srv` and `data_extract_multiple_srv` can be used in scenarios where additional processing of the list of `data_extract_spec` is necessary or `data_extract_srv()` to customize the `selector_list` input.
The following sections provide examples for both scenarios.
@@ -35,14 +33,35 @@ The following sections provide examples for both scenarios.
Using `merge_expression_module` alone requires a list of `data_extract_spec` objects for the `data_extract` argument,
a list of reactive or non-reactive `data.frame` objects, and a list of join keys corresponding to each `data.frame` object.
-#### App code
+#### Step 1/5 - Preparing the Data
```{r}
library(teal.transform)
-library(teal.widgets)
library(teal.data)
library(shiny)
+# Define data.frame objects
+ADSL <- teal.transform::rADSL
+ADTTE <- teal.transform::rADTTE
+
+# create a list of reactive data.frame objects
+datasets <- list(
+ ADSL = reactive(ADSL),
+ ADTTE = reactive(ADTTE)
+)
+
+# create join_keys
+join_keys <- join_keys(
+ join_key("ADSL", "ADSL", c("STUDYID", "USUBJID")),
+ join_key("ADSL", "ADTTE", c("STUDYID", "USUBJID")),
+ join_key("ADTTE", "ADTTE", c("STUDYID", "USUBJID", "PARAMCD"))
+)
+```
+
+
+#### Step 2/5 - Creating the Data Extracts
+
+```{r}
adsl_extract <- data_extract_spec(
dataname = "ADSL",
select = select_spec(
@@ -65,30 +84,42 @@ adtte_extract <- data_extract_spec(
)
data_extracts <- list(adsl_extract = adsl_extract, adtte_extract = adtte_extract)
+```
+
+#### Step 3/5 - Creating the UI
+```{r}
merge_ui <- function(id, data_extracts) {
ns <- NS(id)
- standard_layout(
- output = white_small_well(
+ sidebarLayout(
+ sidebarPanel(
+ h3("Encoding"),
+ div(
+ data_extract_ui(
+ ns("adsl_extract"), # must correspond with data_extracts list names
+ label = "ADSL extract",
+ data_extracts[[1]]
+ ),
+ data_extract_ui(
+ ns("adtte_extract"), # must correspond with data_extracts list names
+ label = "ADTTE extract",
+ data_extracts[[2]]
+ )
+ )
+ ),
+ mainPanel(
+ h3("Output"),
verbatimTextOutput(ns("expr")),
dataTableOutput(ns("data"))
- ),
- encoding = div(
- data_extract_ui(
- ns("adsl_extract"), # must correspond with data_extracts list names
- label = "ADSL extract",
- data_extracts[[1]]
- ),
- data_extract_ui(
- ns("adtte_extract"), # must correspond with data_extracts list names
- label = "ADTTE extract",
- data_extracts[[2]]
- )
)
)
}
+```
+
+#### Step 4/5 - Creating the Server Logic
-merge_module <- function(id, datasets, data_extracts, join_keys) {
+```{r}
+merge_srv <- function(id, datasets, data_extracts, join_keys) {
moduleServer(id, function(input, output, session) {
merged_data <- merge_expression_module(
data_extract = data_extracts,
@@ -105,36 +136,24 @@ merge_module <- function(id, datasets, data_extracts, join_keys) {
output$data <- renderDataTable(ANL())
})
}
-
-# Define data.frame objects
-ADSL <- teal.transform::rADSL
-ADTTE <- teal.transform::rADTTE
-
-# create a list of reactive data.frame objects
-datasets <- list(
- ADSL = reactive(ADSL),
- ADTTE = reactive(ADTTE)
-)
-
-# create join_keys
-join_keys <- join_keys(
- join_key("ADSL", "ADSL", c("STUDYID", "USUBJID")),
- join_key("ADSL", "ADTTE", c("STUDYID", "USUBJID")),
- join_key("ADTTE", "ADTTE", c("STUDYID", "USUBJID", "PARAMCD"))
-)
```
-#### Shiny app
+#### Step 5/5 - Creating the `shiny` App
```{r eval=FALSE}
shinyApp(
ui = fluidPage(merge_ui("data_merge", data_extracts)),
server = function(input, output, session) {
- merge_module("data_merge", datasets, data_extracts, join_keys)
+ merge_srv("data_merge", datasets, data_extracts, join_keys)
}
)
```
+
+
+
+
+
### `data_extract_multiple_srv` + `merge_expression_srv`
In the scenario above, if the user deselects the `ADTTE` variable, the merging between `ADTTE` and `ADSL` would still occur, even though `ADTTE` is not used or needed.
@@ -142,8 +161,10 @@ Here, the developer might update the `selector_list` input in a reactive manner
Below, we reuse the input from above and update the app server so that the `adtte_extract` is removed from the selector_list input when no `ADTTE` variable is selected.
The `reactive_selector_list` is then passed to `merge_expression_srv`:
+#### Modifying the Server Logic
+
```{r}
-merge_module <- function(id, datasets, data_extracts, join_keys) {
+merge_srv <- function(id, datasets, data_extracts, join_keys) {
moduleServer(id, function(input, output, session) {
selector_list <- data_extract_multiple_srv(data_extracts, datasets, join_keys)
reactive_selector_list <- reactive({
@@ -171,17 +192,19 @@ merge_module <- function(id, datasets, data_extracts, join_keys) {
}
```
-#### Shiny app
+#### Updating the `shiny` app
```{r eval=FALSE}
shinyApp(
ui = fluidPage(merge_ui("data_merge", data_extracts)),
server = function(input, output, session) {
- merge_module("data_merge", datasets, data_extracts, join_keys)
+ merge_srv("data_merge", datasets, data_extracts, join_keys)
}
)
```
+
+
`merge_expression_module` is replaced here with three parts:
1) `selector_list`: the output of `data_extract_multiple_srv`, which loops over the list of `data_extract` given and runs `data_extract_srv` for each one, returning a list of reactive objects.
diff --git a/vignettes/images/app-data-extract-merge.png b/vignettes/images/app-data-extract-merge.png
new file mode 100644
index 00000000..a54904a2
Binary files /dev/null and b/vignettes/images/app-data-extract-merge.png differ
diff --git a/vignettes/images/app-data-extract.png b/vignettes/images/app-data-extract.png
new file mode 100644
index 00000000..a3728ac7
Binary files /dev/null and b/vignettes/images/app-data-extract.png differ
diff --git a/vignettes/images/app-data-merge-1.png b/vignettes/images/app-data-merge-1.png
new file mode 100644
index 00000000..4cbd38ba
Binary files /dev/null and b/vignettes/images/app-data-merge-1.png differ
diff --git a/vignettes/images/app-data-merge-2.png b/vignettes/images/app-data-merge-2.png
new file mode 100644
index 00000000..487d130e
Binary files /dev/null and b/vignettes/images/app-data-merge-2.png differ
diff --git a/vignettes/images/basic_concept.svg b/vignettes/images/basic_concept.svg
new file mode 100644
index 00000000..59cc580b
--- /dev/null
+++ b/vignettes/images/basic_concept.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vignettes/images/data_extract_spec/basic_concept.png b/vignettes/images/data_extract_spec/basic_concept.png
deleted file mode 100644
index 5d34ee31..00000000
Binary files a/vignettes/images/data_extract_spec/basic_concept.png and /dev/null differ
diff --git a/vignettes/teal-transform.Rmd b/vignettes/teal-transform.Rmd
index b94a41ab..91a9a71e 100644
--- a/vignettes/teal-transform.Rmd
+++ b/vignettes/teal-transform.Rmd
@@ -22,13 +22,16 @@ knitr::opts_chunk$set(
The `teal.transform` package is an integral component of the `teal` framework.
It serves a dual purpose:
-- For `teal` module developers, it offers a standardized user interface for column selection from datasets and facilitates dataset merging, resulting in the creation of analysis datasets for use within their modules.
- For `teal` application developers, it provides a means to specify which dataset columns can be accessed through the user interface, streamlining column selection within their applications.
+- For `teal` module developers, it offers a standardized user interface for column selection from datasets and facilitates dataset merging, resulting in the creation of analysis datasets for use within their modules.
## Data Extraction and Data Merging
+The primary goal of `teal.transform` to to provide functions that help in abstracting the process of Data Extraction and Data Merging in UI elements of the `shiny` app.
+This helps in reducing the amount of code required to create a UI elements that directly transform the data to perform the required analysis. This is how the app user gains flexibility to transform their data right from the UI.
+
+To explore the combined use of data extraction and merging to see the full use of `teal.transform`, please explore the [Combining data-extract with data-merge](data-extract-merge.html) vignette.
+
To delve into the process of selecting specific data columns, please consult the [Data Extraction](data-extract.html) vignette.
For comprehensive information regarding data merging, please refer to the [Data Merge](data-merge.html) vignette.
-
-To explore the combined use of data extraction and merging, please explore the [Combining data-extract with data-merge](data-extract-merge.html) vignette.