Individual Longitudinal Visualization


Individual Longitudinal Visualization. Patients randomized to active treatment or placebo with an on-treatment period of 52 weeks and a subsequent 8 weeks off-treatment follow-up period.

Panels 1 Vasculitis symptom score with a square root transformation to reduce right skewness in the score 2 Oral Corticosteroid (OCS) dose with log(x+1) transformation to reduce right skewness in the dose 3 Cumulative Remission Events (Remission is defined as Vasculitis Symptom Score = 0 and OCS Dose ≤ 7.5 mg/day) 4 Cumulative Relapse Events (Relapse is defined as an acute flare-up of symptoms, usually requiring immediate treatment with high dose OCS treatment)

What is Trelliscope? Trelliscope is a powerful, scalable, interactive approach to data visualization. The idea behind trelliscope is strongly embedded in the small multiples or trellis display, where data are split into groups and displayed into a grid. This technique is especially suitable for visualizing large datasets and making comparisons easier. Trelliscope was developed by Ryan Hafen and further details can be found in Ryan’s presentation: Modern Approaches to Data Exploration with Trellis Display or in it’s documentation trelliscopejs

Trelliscope makes small multiple displays come alive by providing the ability to interactively set a specific grid, filter or sorting sort based on summary statistics computed for each group. n_ady:# Days in study dose Median OCS dose symMedian Vasculitis symptom score cumrem: # Remission Days" cumrel # Relapse Days

Group Longitudinal (Means & Ratios) Visualization


Vasculitis Symptom Score
Means Panel presents the active treatment and placebo over the 52 weeks on treatment and 8 weeks off treatment follow-up period. Darker lines represent the daily means and shaded area are 1+/- Standard Error of the mean.
Ratio Panel lines represent the daily ratio of the active treatment to placebo, with their associated 95% confidence intervals represented by the shaded area. Both the daily means (SE) and ratios (95% CI) were obtain from a overdispersed corrected poisson regression.

Oral Corticosteroid (OCS) dose
Means Panel lines represent the daily geometric means for the active treatment and placebo with their associated +/- SE.
Ratio Panel daily ratio of geometric means with their associated 95% confidence intervals. When the upper CI doesn’t overlap with the 1 horizontal line we conclude there is significant effect. Both the daily geometric means (SE) and ratios were obtain from a log + 1 OCS transformed linear regression.

Remission Event & Relapse Event (cumulative) Means daily cumulative events (+/- SE) Ratio the daily ratio (95%) of treatment to placebo. These models were also generated using and overdispered poisson regression.

Boxplots are the marginal effects of each panel at different times thought the study: 0 to 24 weeks (early on-treatment period) 24 to 52 weeks (later on-treatment period) 52 to 60 weeks (8 weeks of off-treatment follow-up period)

Group Longitudinal (Means & Ratios) Visualization (Animated)


Extends previous static result figure by including animation

Group (Means & Ratios) Descriptive Statistics Table

Descriptive Statistics 0-24 wks 24-52 wks 52-60 wks
P, N = 167 T, N = 167 T / P, N = 167 P, N = 197 T, N = 197 T / P, N = 197 P, N = 56 T, N = 56 T / P, N = 56
Vasculitis symptom score
Median 2.45 1.68 0.68 2.10 2.09 1.02 1.70 2.46 1.49
IQR 2.24, 2.62 1.57, 2.03 0.56, 0.86 1.87, 2.26 1.94, 2.22 0.90, 1.10 1.56, 1.89 2.29, 2.51 1.21, 1.62
Range 1.92 - 3.51 1.22 - 3.06 0.51 - 0.98 1.19 - 2.54 1.68 - 2.63 0.78 - 2.01 1.22 - 2.06 2.23 - 2.63 1.11 - 2.01
Oral Corticosteroid dose
Median 11.6 8.9 0.8 10.0 4.5 0.5 10.2 5.2 0.6
IQR 10.4, 13.1 6.8, 11.8 0.7, 0.9 9.7, 10.4 4.3, 4.8 0.5, 0.5 9.9, 10.4 4.6, 5.5 0.5, 0.6
Range 9.7 - 14.1 5.4 - 13.9 0.6 - 1.0 9.2 - 11.0 4.1 - 5.4 0.4 - 0.6 9.4 - 11.1 4.5 - 7.0 0.5 - 0.7
Remission Event (cumulative)
Median 8.7 14.1 1.6 41.4 101.9 2.5 64.1 159.2 2.5
IQR 3.8, 13.9 3.1, 32.5 0.9, 2.3 30.7, 50.7 78.9, 127.9 2.5, 2.5 62.0, 65.7 154.2, 163.0 2.4, 2.5
Range 0.0 - 21.4 0.1 - 53.3 0.7 - 2.6 21.6 - 60.8 53.7 - 149.0 2.4 - 2.6 59.2 - 76.6 149.3 - 179.0 2.2 - 2.5
Relapse Event (cumulative)
Median 0.41 0.13 0.36 1.73 0.91 0.50 2.48 1.45 0.57
IQR 0.16, 0.76 0.08, 0.24 0.32, 0.46 1.44, 2.08 0.64, 1.09 0.44, 0.52 2.44, 2.64 1.42, 1.51 0.57, 0.58
Range 0.01 - 1.06 0.01 - 0.41 0.25 - 1.00 1.08 - 2.35 0.41 - 1.29 0.38 - 0.56 2.32 - 2.69 1.31 - 1.70 0.56 - 0.71

Representation of the boxplot panels in table format. In particular we show means, IQR (25% & 75% percentile), and minimum and maximum for each phase of the study, 0 to 24 weeks (early on-treatment period), 24 to 52 weeks (later on-treatment period) and 52 to 60 weeks (8 weeks of off-treatment follow-up period)

---
title:      Vasculitis Data Visualization
author:     Agustin Calatroni   Wonderful-Wednesdays 
date:       "`r format(Sys.Date(), format='%a %d %b %Y')`" 
output: 
  flexdashboard::flex_dashboard:
    storyboard: true
    self_contained: true
    source_code: embed
editor_options: 
  markdown: 
    wrap: 72
---

```{=html}

```
```{r knitr-defaults, include=FALSE}
# div id = "htmlwidget-517a0f624b2519fadf46"
knitr::opts_chunk$set(warning = FALSE, message = FALSE, comment = NA)
knitr::opts_chunk$set(cache = FALSE)
options(width=170)
```

```{r import-data-raw, include=FALSE}
pacman::p_load(tidyverse, rio)
pacman::p_load(labelled)

vas_01 <- read.csv("https://raw.githubusercontent.com/VIS-SIG/Wonderful-Wednesdays/master/data/2021/2021-05-12/vas_data.csv")

var_label(vas_01) <- c(subject	  =	'Subject ID',
                       trt01pn	  =	'Randomised treatment (0 = Placebo; 1 = Treatment)',
                       ady	        =	'Study Day',
                       sym	        =	'Vasculitis symptom score',
                       dose	     =	'Oral Corticosteroid (OCS) dose',
                       rem	        =	'Subject in Remission, i.e. Vasculitis Symptom Score = 0 and OCS Dose <= 7.5 mg/day (Y/N)',
                       rel	        =	'Relapse Event (Y)',
                       acc_rem	  =	'Accrued Duration of Remission (Days)',
                       sus_rem	  =	'Subject Achieved Remission Within First 24 Weeks and Remained in Remission Until EOS? (Y/N))')

# 1 rec per subject
vas_per <- vas_01 %>% 
   distinct(subject, trt01pn, acc_rem, sus_rem) %>% 
   mutate(trt01pc = factor(trt01pn,
                           levels = c(1, 2),
                           labels = c("P","T")))
export(vas_per, "vas_per.rds")

# 1 rec per day
vas_vis <- vas_01 %>% 
   left_join(vas_per %>% select(subject, trt01pc)) %>% 
   select(subject, trt01pc, ady, sym, dose, rem, rel) %>% 
   mutate(across(c(rem, rel), ~ifelse(.x == 'Y', 1, 0))) %>% 
   drop_na(sym, dose) 
export(vas_vis, "vas_vis.rds")
```

```{r import-data-derive, include=FALSE}
vas_per <- import("vas_per.rds")
vas_vis <- import("vas_vis.rds") %>% 
   filter(ady <= 420) 

vas_per_extra <- vas_vis %>% 
   group_by(subject) %>% 
   summarize(n_ady  = n(),
             cumrem = sum(rem),
             cumrel = sum(rel),
             dose =   median(dose),
             sym  =   median(sym)) 
```

### **Individual** Longitudinal Visualization

```{r create-trelliscope}
pacman::p_load(trelliscopejs)

vas_per <- vas_per %>% 
   ungroup() %>% 
   select(subject, trt01pc) %>% 
   left_join( vas_per_extra ) %>% 
   as.data.frame()

vas_per <- set_labels(vas_per,
                      list(trt01pc = "Randomised treatment (P = Placebo & T = Treatment)",
                           n_ady  = "# of Days in study", 
                           cumrem = "# of Remission Days", 
                           cumrel = "# of Relapse Days",
                           dose   = "Median Oral Corticosteroid (OCS) dose", 
                           sym    = "Median Vasculitis symptom score"))

# source('vas-gif.r') # generate the vas-gif prior to include into trelliscope

vas_per %>%
   mutate(panel_col = img_panel_local(str_glue('vas-subject-gif/subject_{subject}.gif'))) %>%
   trelliscope(name = 'Vasculitis Visualization',
               desc = 'Individual Trajectories for multiple outcomes',
               panel_col = 'panel_col',
               path = './vas-trelliscope',
               ncol = 2,
               nrow = 1,
               state = list(sort = list(sort_spec("n_ady", dir = "desc")),
                            labels  = c('sym', 'dose'))
   )
```

------------------------------------------------------------------------

**Individual** Longitudinal Visualization. Patients randomized to  active treatment  or 
 placebo  with an on-treatment period of 52 weeks and a subsequent 8 weeks off-treatment follow-up period.

**Panels** 
**1** Vasculitis symptom score with a square root transformation to reduce right skewness in the score
**2** Oral Corticosteroid (OCS) dose with log(x+1) transformation to reduce right skewness in the dose 
**3** Cumulative Remission Events (Remission is defined as Vasculitis Symptom Score = 0 and OCS Dose ≤ 7.5 mg/day)
**4** Cumulative Relapse Events (Relapse is defined as an acute flare-up of symptoms, usually requiring immediate treatment with high dose OCS treatment)

**What is Trelliscope?** Trelliscope is a powerful, scalable,
interactive approach to data visualization. The idea behind trelliscope
is strongly embedded in the small multiples or trellis display, where
data are split into groups and displayed into a grid. This technique is
especially suitable for visualizing large datasets and making
comparisons easier. Trelliscope was developed by [Ryan
Hafen](http://ryanhafen.com/) and further details can be found in
[Ryan's presentation: Modern Approaches to Data Exploration with Trellis
Display](http://slides.com/hafen/trelliscopejs) or in it's documentation
[trelliscopejs](https://hafen.github.io/trelliscopejs/)

Trelliscope makes small multiple displays come alive by providing the ability to interactively 
set a specific grid, filter or sorting sort  based on summary statistics computed for each group. 
**n_ady**:# Days in study **dose** Median OCS dose **sym**Median Vasculitis symptom score **cumrem**: # Remission Days" **cumrel** # Relapse Days 

### **Group** Longitudinal (Means & Ratios) Visualization

```{r reshape-calculate, eval=FALSE, include=FALSE}
pacman::p_load(emmeans)

vas_nest <- vas_vis %>%
   group_by(subject) %>%
   mutate(cumrem = cumsum(rem),
          cumrel = cumsum(rel)) %>%
   ungroup() %>%
   nest_by(ady)  %>%
   mutate(sym_m = list(glm(sym ~ trt01pc, data = data, family = quasipoisson)),
          sym_e = list(emmeans(sym_m, 'trt01pc', type = 'response')),
          sym_d = list(bind_rows(summary(sym_e, adjust = 'none', infer = TRUE) %>%
                                    as.data.frame(),
                                 pairs(sym_e, reverse = TRUE) %>%
                                    summary(adjust = 'none', infer = TRUE) %>%
                                    as.data.frame() %>%
                                    rename(trt01pc = contrast,
                                           rate = ratio) ) )) %>%
   mutate(dose_m = list(glm(log(dose+1) ~ trt01pc, data = data)),
          dose_e = list(emmeans(dose_m, 'trt01pc', type = 'response')),
          dose_d = list(bind_rows(summary(dose_e, adjust = 'none', infer = TRUE) %>%
                                     as.data.frame(),
                                  pairs(dose_e, reverse = TRUE) %>%
                                     summary(adjust = 'none', infer = TRUE) %>%
                                     as.data.frame() %>%
                                     rename(trt01pc = contrast,
                                            response = ratio)) %>%
                           rename(rate = response) ) ) %>%
   mutate(cumrem_m = list(glm(cumrem ~ trt01pc, data = data, family = quasipoisson)),
          cumrem_e = list(emmeans(cumrem_m, 'trt01pc', type = 'response')),
          cumrem_d = list(bind_rows(summary(cumrem_e, adjust = 'none', infer = TRUE) %>%
                                       as.data.frame(),
                                    pairs(cumrem_e, reverse = TRUE) %>%
                                       summary(adjust = 'none', infer = TRUE) %>%
                                       as.data.frame() %>%
                                       rename(trt01pc = contrast,
                                              rate = ratio) ) )) %>%
   mutate(cumrel_m = list(glm(cumrel ~ trt01pc, data = data, family = quasipoisson)),
          cumrel_e = list(emmeans(cumrel_m, 'trt01pc', type = 'response')),
          cumrel_d = list(bind_rows(summary(cumrel_e, adjust = 'none', infer = TRUE) %>%
                                       as.data.frame(),
                                    pairs(cumrel_e, reverse = TRUE) %>%
                                       summary(adjust = 'none', infer = TRUE) %>%
                                       as.data.frame() %>%
                                       rename(trt01pc = contrast,
                                              rate = ratio) ) ))
```

```{r reshape-long & ref-line, eval=FALSE, include=FALSE}
vas_glm <- vas_nest %>%
   select(ady, ends_with('_d')) %>%
   pivot_longer(cols = -1) %>%
   unnest(value) %>%
   mutate(name2 = ifelse(trt01pc %in% c('P','T'), 'mean', 'diff') %>%
             as.factor() %>%
             fct_relevel('mean','diff')) %>%
   mutate(name = factor(name) %>%
             fct_relevel('sym_d','dose_d','cumrem_d','cumrel_d')) %>%
   mutate(time = case_when(ady<168 ~ "a",
                           ady<365 ~ "b",
                           TRUE    ~ "c")) %>%
   mutate(rate      = ifelse(name == 'cumrel_d' & ady < 14 & trt01pc %in% c('P','T'),   0.01, rate),
          rate      = ifelse(name == 'cumrel_d' & ady < 14 & !(trt01pc %in% c('P','T')),   1, rate),
          SE        = ifelse(name == 'cumrel_d' & ady < 14 & trt01pc %in% c('P','T'),      0, SE),
          asymp.LCL = ifelse(name == 'cumrel_d' & ady < 14 & !(trt01pc %in% c('P','T')),   1, asymp.LCL),
          asymp.UCL = ifelse(name == 'cumrel_d' & ady < 14 & !(trt01pc %in% c('P','T')),   1, asymp.UCL))

export(vas_glm, 'vas_glm.rds')
```

```{r import-glm}
vas_glm <- import('vas_glm.rds') 

ref_df <- crossing(name = c('sym_d','dose_d','cumrem_d','cumrel_d'),
                   name2 = c('mean','diff'),
                   time = c('a','b','c'),
                   ref  = 1) %>% 
   as.data.frame() %>% 
   mutate(name  = as.factor(name) %>% fct_relevel('sym_d','dose_d','cumrem_d','cumrel_d'),
          name2 = as.factor(name2) %>% fct_relevel('mean','diff')) %>% 
   filter(name2 != 'mean')

axs_df <- crossing(name = c('sym_d','dose_d','cumrem_d','cumrel_d'),
                   name2 = c('mean','diff'),
                   nesting( ady = c(1, 168, 365, 420),
                            txt = c('a','b','c','d') )) %>% 
   as.data.frame() %>% 
   mutate(name  = as.factor(name) %>% fct_relevel('sym_d','dose_d','cumrem_d','cumrel_d'),
          name2 = as.factor(name2) %>% fct_relevel('mean','diff')) %>% 
   filter(name2 == 'mean') %>% 
   filter(name  == 'sym_d')
```

```{r fig-1}
pacman::p_load(ggh4x, ggtext)

vas_l_l <- vas_glm %>% 
   group_by(name, name2, trt01pc) %>% 
   slice(n()) %>% 
   select(ady, name, name2, trt01pc, rate) %>% 
   mutate(color = case_when(trt01pc == 'T'     ~ '#1b9e77',
                            trt01pc == 'P'     ~ '#d95f02',
                            trt01pc == 'T / P' ~ '#7f7f7f'))

vas_l_l_s  <- vas_l_l %>% filter(name == 'sym_d', trt01pc %in% c('T','P')) 
vas_l_l_s2 <- vas_l_l %>% filter(name == 'sym_d', trt01pc %in% c('T / P')) 

vas_l_l_d  <- vas_l_l %>% filter(name == 'dose_d', trt01pc %in% c('T','P')) 
vas_l_l_d2 <- vas_l_l %>% filter(name == 'dose_d', trt01pc %in% c('T / P')) 

vas_l_l_c  <- vas_l_l %>% filter(name == 'cumrem_d', trt01pc %in% c('T','P')) 
vas_l_l_c2 <- vas_l_l %>% filter(name == 'cumrem_d', trt01pc %in% c('T / P')) 

vas_l_l_cl  <- vas_l_l %>% filter(name == 'cumrel_d', trt01pc %in% c('T','P')) 
vas_l_l_cl2 <- vas_l_l %>% filter(name == 'cumrel_d', trt01pc %in% c('T / P')) 

f1 <- ggplot(data = vas_glm,
             aes(x = ady, y =rate, color = trt01pc, fill = trt01pc)) +
   geom_hline(data = ref_df,
              aes(yintercept = ref),
              col = 'gray25') +
   geom_vline(xintercept = c(168, 365), col = 'gray65') +
   geom_line() +
   geom_ribbon(data = . %>% filter(name2 == 'mean'),
               aes(ymin=rate-SE, ymax=rate+SE),
               alpha=0.5, colour = NA) +
   geom_ribbon(data = . %>% filter(name2 == 'diff'),
               aes(ymin=asymp.LCL, ymax=asymp.UCL),
               alpha=0.5, colour = NA) +
   
   geom_segment(data = axs_df,
                x  = 1, xend = 365, y = 5.0, yend = 5.0,
                arrow = arrow(length = unit(0.08,  "native"), type = "closed"),
                inherit.aes = FALSE) +
   geom_label(data = axs_df,
              x = 168, label = "On Treatment",
              y = 5.4,
              size = 3,
              inherit.aes = FALSE) +
   geom_segment(data = axs_df,
                x  = 366, xend = 420, y = 5.0, yend = 5.0,
                arrow = arrow(length = unit(0.08,  "native"), type = "closed"),
                inherit.aes = FALSE) +
   geom_label(data = axs_df,
              x = 390, label = "Off Treatment",
              y = 5.4,
              size = 3,
              inherit.aes = FALSE) +
   coord_cartesian(clip = "off") +
   facet_nested_wrap(vars(name, name2),
                     dir = 'v',
                     strip.position = "left",
                     ncol = 1,
                     scales = 'free_y',
                     labeller = as_labeller(c(sym_d    = "Vasculitis Symptom Score",
                                              dose_d   = "Oral Corticosteroid Dose",
                                              cumrem_d = "Remission Event (cumulative)",
                                              cumrel_d = "Relapse Event (cumulative)",
                                              mean = 'Means',
                                              diff = 'Ratio'))
   ) +
   facetted_pos_scales(y =list(
      scale_y_continuous(limits = c(0.5, 4.5),
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_s %>% pull(rate),
                            labels = str_glue("{vas_l_l_s$trt01pc  }"),
                            name = NULL
                         )),
      scale_y_continuous(limits = c(0.25, 4.5),
                         trans = "log10",
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_s2 %>% pull(rate),
                            labels = str_glue("{vas_l_l_s2$trt01pc  }"),
                            name = NULL
                         )),
      
      scale_y_continuous(limits = c(3.5, 15.2),
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_d %>% pull(rate),
                            labels = str_glue("{vas_l_l_s$trt01pc  }"),
                            name = NULL
                         )),
      scale_y_continuous(limits = c(0.30, 2.0),
                         trans = "log10",
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_d2 %>% pull(rate),
                            labels = str_glue("{vas_l_l_s2$trt01pc  }"),
                            name = NULL
                         )),
      
      scale_y_continuous(limits = c(0, 205),
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_c %>% pull(rate),
                            labels = str_glue("{vas_l_l_s$trt01pc  }"),
                            name = NULL
                         )),
      scale_y_continuous(limits = c(0.2, 11),
                         trans = "log10",
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_c2 %>% pull(rate),
                            labels = str_glue("{vas_l_l_s2$trt01pc  }"),
                            name = NULL
                         )),
      
      scale_y_continuous(limits = c(0, 3.0),
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_cl %>% pull(rate),
                            labels = str_glue("{vas_l_l_s$trt01pc  }"),
                            name = NULL
                         )),
      scale_y_continuous(limits = c(0.10, 5.0),
                         trans = "log10",
                         minor_breaks = NULL,
                         sec.axis = dup_axis(
                            breaks = vas_l_l_cl2 %>% pull(rate),
                            labels = str_glue("{vas_l_l_s2$trt01pc  }"),
                            name = NULL
                         )))
   ) +
   scale_color_manual(values = c('T' = '#1b9e77',
                                 'P' = '#d95f02',
                                 'T / P' = '#7f7f7f'),
                      guide = FALSE) +
   scale_fill_manual(values = c('T' = '#1b9e77',
                                'P' = '#d95f02',
                                'T / P' = '#7f7f7f')) +
   scale_x_continuous(name = "Study Day",
                      limits = c(0, 420),
                      breaks = c(1, 168, 365, 420),
                      labels = c("1", "168 days\n 24 wks", "365 days\n 52 wks", "420 days\n 60 wks"),
                      expand = c(0.01, 0.01),
                      minor_breaks = NULL) + 
   labs(y = NULL) +
   theme_bw(base_size = 10) +
   theme(
      plot.margin = unit(c(1.5, 0.5, 0.5, 0.5), units="lines"),
      legend.position = "none",
      strip.placement = "outside",
      axis.text.x = element_text(hjust = 1),
      axis.text.y.right= element_markdown()
   ) 
```

```{r fig-2}
f2 <- ggplot(data = vas_glm ,
             aes(y = rate, fill = trt01pc)) +
   geom_hline(data = ref_df,
              aes(yintercept = ref),
              col = 'gray25') +
   geom_boxplot(varwidth = TRUE, alpha = 0.5, outlier.shape = NA) +
   facet_nested(rows = vars(name,name2),
                cols = vars(time),
                scales = 'free_y',
                labeller = as_labeller(c(sym_d    = "Vasculitis Symptom Score",
                                         dose_d   = "Oral Corticosteroid Dose",
                                         cumrem_d = "Remission Event (cumulative)",
                                         cumrel_d = "Relapse Event (cumulative)",
                                         mean = 'Means',
                                         diff = 'Ratio',
                                         a = '0-24 wks',
                                         b = '24-52 wks',
                                         c = '52-60 wks'))
   ) +
   facetted_pos_scales(y =list(
      scale_y_continuous(limits = c(0.5, 4.5),
                         minor_breaks = NULL),
      scale_y_continuous(limits = c(0.25, 4.5),
                         trans = "log10",
                         minor_breaks = NULL),
      
      scale_y_continuous(limits = c(3.5, 15.2),
                         minor_breaks = NULL),
      scale_y_continuous(limits = c(0.30, 2.0),
                         trans = "log10",
                         minor_breaks = NULL),
      
      scale_y_continuous(limits = c(0, 205),
                         minor_breaks = NULL),
      scale_y_continuous(limits = c(0.2, 11),
                         trans = "log10",
                         minor_breaks = NULL),
      
      scale_y_continuous(limits = c(0, 3.0),
                         minor_breaks = NULL),
      scale_y_continuous(limits = c(0.10, 5.0),
                         trans = "log10",
                         minor_breaks = NULL))
   ) +
   scale_color_manual(values = c('T' = '#1b9e77',
                                 'P' = '#d95f02',
                                 'T / P' = '#7f7f7f'),
                      guide = FALSE) +
   scale_fill_manual(values = c('T' = '#1b9e77',
                                'P' = '#d95f02',
                                'T / P' = '#7f7f7f'),
                     labels = c("P",
                                "T",
                                "Ratio")) +
   labs(y = NULL,
        fill = NULL) +
   theme_bw(base_size = 10) +
   theme(
      legend.position = "none",
      strip.placement = "outside",
      axis.title.x=element_blank(),
      axis.text.x=element_blank(),
      axis.ticks.x=element_blank(),
      panel.grid.major.x = element_blank(),
      panel.grid.minor.x = element_blank()
   )
```

```{r fig-comb, fig.width = 14, fig.height = 8, dpi = 300}
pacman::p_load(patchwork)
f1 + f2 +
   plot_layout(widths = c(4, 1.5))
```

------------------------------------------------------------------------

**Vasculitis Symptom Score**  
**Means Panel** presents the  active treatment  and 
 placebo  over the 52 weeks on treatment and 8 weeks off treatment follow-up period. 
Darker lines represent the daily means and shaded area are 1+/- Standard Error of the mean.  
**Ratio Panel** lines represent the daily ratio of the active treatment to placebo, with their associated 95% confidence intervals represented by the shaded area. Both the daily means (SE) and ratios (95% CI) were obtain from a overdispersed corrected poisson regression. 

**Oral Corticosteroid (OCS) dose**  
**Means Panel** lines represent the daily geometric means for the  active treatment  and 
 placebo  with their associated +/- SE.  
**Ratio Panel** daily ratio of geometric means with their associated 95% confidence intervals. When the upper CI doesn't
overlap with the 1 horizontal line we conclude there is significant effect. Both the daily geometric means (SE) and
ratios were obtain from a log + 1 OCS transformed linear regression.

**Remission Event & Relapse Event (cumulative)** **Means** daily cumulative events (+/- SE) **Ratio** the daily ratio (95%) of treatment to placebo. These models were also generated using and overdispered poisson regression.

**Boxplots** are the marginal effects of each panel at different times thought the study: **0 to 24 weeks** (early on-treatment period) **24 to 52 weeks** (later on-treatment period) **52 to 60 weeks** (8 weeks of off-treatment follow-up period) 


### **Group** Longitudinal (Means & Ratios) Visualization (Animated)

```{r include-gif}
# source('fig-gif.r') # generate the fig-gif prior to include
knitr::include_graphics("vas-fig-gif.gif")
```

------------------------------------------------------------------------

Extends previous static result figure by including animation

### **Group** (Means & Ratios) Descriptive Statistics Table

```{r gtsummary-table}
pacman::p_load(gtsummary)

t_1 <- vas_glm %>% 
   filter(name == 'sym_d') %>% 
   select(trt01pc, `Vasculitis symptom score` = rate, time) %>%
   mutate(time = factor(time, labels = c('0-24 wks','24-52 wks','52-60 wks'))) %>% 
   tbl_strata(
      strata = time,
      .tbl_fun = ~.x %>% tbl_summary(by = 'trt01pc',
                                     type = all_continuous() ~ "continuous2",
                                     statistic = list(all_continuous2() ~ c("{median}",
                                                                            "{p25}, {p75}",
                                                                            "{min} - {max}")) 
      )
   )

t_2 <- vas_glm %>% 
   filter(name == 'dose_d') %>% 
   select(trt01pc, `Oral Corticosteroid dose` = rate, time) %>%
   mutate(time = factor(time, labels = c('0-24 wks','24-52 wks','52-60 wks'))) %>%
   tbl_strata(
      strata = time,
      .tbl_fun = ~.x %>% tbl_summary(by = 'trt01pc',
                                     type = all_continuous() ~ "continuous2",
                                     statistic = list(all_continuous2() ~ c("{median}",
                                                                            "{p25}, {p75}",
                                                                            "{min} - {max}")) 
      )
   )

t_3 <- vas_glm %>% 
   filter(name == 'cumrem_d') %>% 
   select(trt01pc, `Remission Event (cumulative)` = rate, time) %>%
   mutate(time = factor(time, labels = c('0-24 wks','24-52 wks','52-60 wks'))) %>%
   tbl_strata(
      strata = time,
      .tbl_fun = ~.x %>% tbl_summary(by = 'trt01pc',
                                     digits =  all_continuous() ~ 1,
                                     type = all_continuous() ~ "continuous2",
                                     statistic = list(all_continuous2() ~ c("{median}",
                                                                            "{p25}, {p75}",
                                                                            "{min} - {max}")) 
      )
   )

t_4 <- vas_glm %>% 
   filter(name == 'cumrel_d') %>% 
   select(trt01pc, `Relapse Event (cumulative)` = rate, time) %>%
   mutate(time = factor(time, labels = c('0-24 wks','24-52 wks','52-60 wks'))) %>%
   tbl_strata(
      strata = time,
      .tbl_fun = ~.x %>% tbl_summary(by = 'trt01pc',
                                     type = all_continuous() ~ "continuous2",
                                     statistic = list(all_continuous2() ~ c("{median}",
                                                                            "{p25}, {p75}",
                                                                            "{min} - {max}")) 
      )
   )

tbl_stack(tbls = list(t_1, t_2, t_3, t_4)) %>% 
   modify_header(update = list(label ~ "**Descriptive Statistics**")) %>% 
   bold_labels() 
```

------------------------------------------------------------------------

Representation of the **boxplot** panels in table format. In particular we show means, IQR (25% & 75% percentile), and
minimum and maximum for each phase of the study, **0 to 24 weeks** (early on-treatment period), **24 to 52 weeks** (later on-treatment period) and **52 to 60 weeks** (8 weeks of off-treatment follow-up period)