criteria_fun <-function(tr) !is(tr, "ContentRow") &&all_zero_or_na(tr)lyt <-basic_table(show_colcounts =TRUE) %>%split_cols_by("ACTARMCD") %>%analyze_num_patients(vars ="USUBJID",.stats =c("unique"),.labels =c(unique ="Total number of patients with at least one adverse event" ) ) %>%split_rows_by("SMQ",child_labels ="visible",nested =FALSE,split_fun =trim_levels_in_group("AEDECOD", drop_outlevs =FALSE),label_pos ="topleft",split_label ="Standardized MedDRA Query" ) %>%summarize_num_patients(var ="USUBJID",.stats =c("unique", "nonunique"),.labels =c(unique ="Total number of patients with at least one adverse event",nonunique ="Total number of events" ) ) %>%count_occurrences(vars ="AEDECOD",.indent_mods =-1L,drop =FALSE ) %>%append_varlabels(adae, "AEDECOD", indent =1L)result <-build_table( lyt,df = adae_smq_1,alt_counts_df = adsl) %>%sort_at_path(path =c("SMQ"), scorefun = cont_n_allcols) %>%sort_at_path(path =c("SMQ", "*", "AEDECOD"), scorefun = score_occurrences, na.pos ="last") %>%trim_rows(criteria = criteria_fun)result
Standardized MedDRA Query ARM A ARM B ARM C
Dictionary-Derived Term (N=134) (N=134) (N=132)
—————————————————————————————————————————————————————————————————————————————————————————————————
Total number of patients with at least one adverse event 43 (32.1%) 46 (34.3%) 43 (32.6%)
C.1.1.1.3/B.2.2.3.1 AESI(BROAD)
Total number of patients with at least one adverse event 43 (32.1%) 46 (34.3%) 43 (32.6%)
Total number of events 55 63 64
dcd C.1.1.1.3 43 (32.1%) 46 (34.3%) 43 (32.6%)
Experimental use!
WebR is a tool allowing you to run R code in the web browser. Modify the code below and click run to see the results. Alternatively, copy the code and click here to open WebR in a new tab.
criteria_fun <-function(tr) {!is(tr, "ContentRow") &&all_zero_or_na(tr) &&!grepl("Total number of", obj_label(tr))}lyt <-basic_table(show_colcounts =TRUE) %>%split_cols_by("ACTARMCD") %>%analyze_num_patients(vars ="USUBJID",.stats =c("unique"),.labels =c(unique ="Total number of patients with at least one adverse event" ) ) %>%split_rows_by("SMQ",child_labels ="visible",nested =FALSE,split_fun =trim_levels_in_group("AEDECOD", drop_outlevs =FALSE),label_pos ="topleft",split_label ="Standardized MedDRA Query" ) %>%analyze_num_patients(vars ="USUBJID",.stats =c("unique", "nonunique"),.labels =c(unique ="Total number of patients with at least one adverse event",nonunique ="Total number of events" ),show_labels ="hidden" ) %>%count_occurrences(vars ="AEDECOD",drop =FALSE ) %>%append_varlabels(adae, "AEDECOD", indent =1L)score_ae_pts <-function(tt) { count_vals <-cell_values(tree_children(tt)[["USUBJID"]])[[1]]sum(matrix(unlist(count_vals), nrow =length(count_vals), byrow =TRUE)[, 1])}result <-build_table( lyt,df = adae_smq_all,alt_counts_df = adsl) %>%sort_at_path(path =c("SMQ"), scorefun = score_ae_pts) %>%sort_at_path(path =c("SMQ", "*", "AEDECOD"), scorefun = score_occurrences, na.pos ="last") %>%trim_rows(criteria = criteria_fun)result
Standardized MedDRA Query ARM A ARM B ARM C
Dictionary-Derived Term (N=134) (N=134) (N=132)
—————————————————————————————————————————————————————————————————————————————————————————————————
Total number of patients with at least one adverse event 69 (51.5%) 78 (58.2%) 77 (58.3%)
D.2.1.5.3/A.1.1.1.1 AESI
Total number of patients with at least one adverse event 47 (35.1%) 58 (43.3%) 57 (43.2%)
Total number of events 62 72 74
dcd D.2.1.5.3 47 (35.1%) 58 (43.3%) 57 (43.2%)
C.1.1.1.3/B.2.2.3.1 AESI(BROAD)
Total number of patients with at least one adverse event 43 (32.1%) 46 (34.3%) 43 (32.6%)
Total number of events 55 63 64
dcd C.1.1.1.3 43 (32.1%) 46 (34.3%) 43 (32.6%)
non observed SMQ02NAM level(BROAD)
Total number of patients with at least one adverse event 0 0 0
Total number of events 0 0 0
Experimental use!
WebR is a tool allowing you to run R code in the web browser. Modify the code below and click run to see the results. Alternatively, copy the code and click here to open WebR in a new tab.
Code
library(dplyr)library(tern)library(stringr)adsl <- random.cdisc.data::cadsladae <- random.cdisc.data::cadae# Ensure character variables are converted to factors and empty strings and NAs are explicit missing# levels. For details, refer to Teal and Study Data article.adsl <-df_explicit_na(adsl)adae <-df_explicit_na(adae)# AEs are filtered for relatedness to study drug.adae_rel <- adae %>%filter(AEREL =="Y")# Simulate a random AAG dataset.aag <-data.frame(NAMVAR =c("SMQ01NAM", "SMQ01NAM", "SMQ02NAM", "CQ01NAM", "CQ01NAM"),SRCVAR =rep("AEDECOD", 5),GRPTYPE =c("SMQ", "SMQ", "SMQ", "CUSTOM", "CUSTOM"),REFID =c(1, 1, 2, 3, 3),REFNAME =c(rep("C.1.1.1.3/B.2.2.3.1 AESI", 2), "non observed SMQ02NAM level", rep("D.2.1.5.3/A.1.1.1.1 AESI", 2)),SCOPE =c("BROAD", "BROAD", "BROAD", "", ""),REFTERM =c("C.1.1.1.3", "B.2.2.3.1", "Z.9.9.9.9", "D.2.1.5.3", "A.1.1.1.1"),stringsAsFactors =FALSE)# Create summary AAG dataset (used for labelling).# Note it's important to incorporate SCOPE into the basket names for SMQs so as to# match the flags present in ADAE.aag_summary <- aag %>%select(NAMVAR, REFNAME, SCOPE) %>%unique() %>%mutate(REFNAME_SCOPE =ifelse(SCOPE =="", REFNAME, paste0(REFNAME, "(", SCOPE, ")")) ) %>%rename(basket = NAMVAR, basket_name = REFNAME_SCOPE) %>%select(basket, basket_name)# Make a summary of the full ADAE based on AAG by using h_stack_by_baskets helper functionadae_smq_all <-h_stack_by_baskets(df = adae_rel,aag_summary = aag_summary,keys =c("STUDYID", "USUBJID", "ACTARMCD", "AEDECOD"))# Post-process adae_smq_all to keep only certain baskets of interest for variant 1# Not need to drop baskets for variant 2 as all baskets will be considered.baskets_to_drop_variant <- aag_summary$basket_name[!aag_summary$basket %in%c("SMQ01NAM")]# Adjust the analysis dataset based on basket subset for variant 1.adae_smq_1 <- adae_smq_all %>%filter(!adae_smq_all$SMQ %in% baskets_to_drop_variant) %>%mutate(SMQ = tern::fct_discard(SMQ, discard = baskets_to_drop_variant) )
Note that filtering AEs for relatedness to study drug is not a necessary data pre-processing step for the module. It can be achieved using the teal module filter panel. The example here pre-sets the filters using AEREL = "Y" in adae.
shinylive allow you to modify to run shiny application entirely in the web browser. Modify the code below and click re-run the app to see the results. The performance is slighly worse and some of the features (e.g. downloading) might not work at all.