---
title: "WWW091124"
author: "Thomas Weissensteiner"
date: "2024-10-12"
output:
  html_document:
    code_folding: show
    toc: true
    toc_float: true
    toc_depth: 4
---
**My scripts:**  

* rendered html versions: [Rpubs/thomas-weissensteiner](https://rpubs.com/thomas-weissensteiner)  
* .rmd files with executable code chunks: www.github.com/thomas-weissensteiner/portfolio/tree/main/  

**About myself:** www.linkedin.com/in/ThomasWs-Mopfair

```{r Options, include = FALSE}
## Global directory and output options 

# The working directory in "Global directory and output options" needs to be customised, and should include the following additional files:
# "variants_simulated.csv", the example data file
# "Summarizing_Human_Phenotype_Ontology_Terms_figs", a folder containing additional figures not generated by the code chunks  

knitr::opts_knit$set(root.dir = "C:/Users/ThomasWeissensteiner/OneDrive/Documents/portfolio/WWchallenge")
knitr::opts_chunk$set (warning = FALSE, message = F, tidy = FALSE)
knitr::opts_chunk$set (attr.output='style="max-height: 200px"')

```

### 1. Background
Why personalized dosing?

„Again and again, it has been shown that certain patients benefit more from individual drugs, while others suffer more heavily from side effects… …and still they are usually treated with a standard dose." Free translation of a quote from Prof. Dr. Dr. Gerd Geisslinger, Executive Director, Fraunhofer Institute for Translational Medicine and Pharmacology, Frankfurt

The Challenge

Use visulaisation to identify subgroups with a dose response that deviates from the remaining study participants
Therewith potential subgroups for personalized dosing could be identified

[VIS-SIG Wonderful Wednesdays challenge](https://github.com/VIS-SIG/Wonderful-Wednesdays/tree/master/data/2024/2024-09-11)
  





```{r set-up}
library(dplyr)
library(tidyr) # pivot_longer, pivot_wider
library(purrr) # list_rbind, set_names
library(ggplot2)
library(correlation) # correlation plots
library(ggpubr) # stat_compare_means, ggarrange
library(kableExtra) # rendering tables in HTML format (kableExtra rather than kable is required for R 4.3.0)

exampleData <- read.csv("https://raw.githubusercontent.com/VIS-SIG/Wonderful-Wednesdays/refs/heads/master/data/2024/2024-09-11/WWW54ExampleData.csv")
```
<br>
<br>

### 2. Data set
A simulated dose response data set

dose: dose levels (0, 100, 200 mg)
target: continuous response variable (higher is better)
subgroup variables:
bmi (body mass index: ‘low BMI’ or ‘high BMI’)
age (‘<40 years’ or ‘≥40 years’)
race (‘Black’, ‘Asian’, ‘White’)
sex (‘Female’, ‘Male’)
type (type of disease: ‘Acute disease’ or ‘Chronic disease’)
<br>
<br>

### 3. Target vs. dose in all patients
<br>

```{r chunk_1, fig.dim = c(7.5, 7.5)}
# - Requires R-libraries and object exampleData (chunk: set-up) - #

## Plot distribution of target values at different doses in the total population

sign_test <- 
  exampleData %>% 
  compare_means(
  data = .,
  target ~ dose,
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme(
      "light", 
      base_size = 10
      ),
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(
  
exampleData %>% 
  select (dose, target) %>% 
  
  ggplot (
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200"
        )
      ), 
      y = target)
    ) +
  geom_hline(
    yintercept = 0, 
    color = "darkgrey",
    size = 1.1
    ) +
  geom_violin(
    color = "lightgrey",
    fill  = "lightgrey", 
    width = 0.45
    ) +
  geom_jitter(
    height = 0, width = 0.2, 
    size = 1.3, 
    alpha = 0.2
    ) +
  geom_boxplot(
    width = 0.15 , 
    outlier.shape = NA,
    color = "salmon",
    lwd = 0.7,
    alpha = 0.5
    ) +
  theme_light() +
  theme(
    text=element_text(size = 13), 
    axis.text = element_text(
      size = 12),
    ) +
  scale_y_continuous(
    breaks = c(-2: 5),
    minor_breaks = NULL
    ) +
  labs(
    x = "Dose", 
    y = "Target", 
    size = 12, hjust = -15,
    title = "Target vs. dose levels in the total patient population\n"
    ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1)
)   

```
<br>
<br>
The reference for the Wilcoxon test is the group of untreated patients (dose = 0). Differences in target levels in treated patients are significant. However, the distribution of target values at the three dose levels suggests that at least two subgroups might exists that could respond differently
<br>
<br>

### 4. Best response in patient subgroups
<br>

In order to identify these potential groups, I stratified patients by one or two of the clinical and demographic characteristics that were provided.
For each group, I then calculated the median response for doses 100 and 200 (difference between median target values in the treated subgroups and patients receiving a dose 0).
<br>
<br>

#### 4.1. Table of responses in patient subgroups characterised by one or two variables  


```{r chunk_2, message = F,  warning = F}

# Generate all pairwise combinations of patient characteristics
pVars <- 
  exampleData %>% 
  names() %>% .[!. %in% c("dose","target")]

pVar_pairs <- 
  pVars %>% 
  { c(
    lapply(., function(x) c(x, x)),       # duplicate each characteristic
    combn(.,2, simplify = F)              # all combinations of 2 characteristics
  ) }
 
# ---
pChar_pairs <- 
  lapply(
    seq_along(pVar_pairs), 
    function (x) 
      exampleData %>% 
      select(pVar_pairs[[x]] ) %>% 
      unique(.)
    )
# ---

# Calculate median responses for the patient subgroups 
response_tbl <- 
  lapply(
    pVar_pairs, 
    function(x) 
      exampleData %>% 
        group_by(
          across(all_of(x) ), 
          dose
          ) %>% 
      summarise(
        median(target),
        N = n()
      )
  ) %>%
  # ensure all dataframes have the same number of columns 
    lapply(function(df)
      if(
        ncol(df) < length(pVars)) {
        cbind(df[, 1, drop = FALSE], df)    
        }else{
          df} 
      ) %>% 
  lapply(function(df)
    pivot_wider(
      df, 
      names_from = "dose",
      values_from = c("median(target)", "N")
      ) %>%
    set_names(
     "Var1_value", "Var2_value", 
     "median_0", "median_100", "median_200", 
      "N_0", "N_100", "N_200"
      )
    ) %>% 
  list_rbind() %>%
  mutate(
    response_100 = median_100 - median_0,
    response_200 = median_200 - median_0,
    max_response = max(response_100, response_200) ,
    max_resp_dose = which.max(c(response_100, response_200))*100,
    N_max = c(N_100, N_200)[max_resp_dose/100]
    )


## Table of best median responses stratified by patient subgroups

# Re-order columns, sort by maximum response (highest first)
response_tbl %>%   
  select( 
    "Var1_value", "Var2_value", 
    "N_max", "max_response",
    "N_0", "N_100", "N_200",
    "median_0", "median_100", "median_200"
    ) %>% 
  arrange( desc(max_response)) %>% 
  kable(., "html") %>% 
  scroll_box(width = "100%", height = "200px") %>% 
  kable_styling( 
    bootstrap_options = c(
      "striped", "hover", "responsive", full_width = F) 
    ) 


```
<br>
<br>

#### 4.2. Best response in patients stratified by demographic and clinical parameters - showing patient numbers in treated and matched untreated subgroups  
<br>

```{r chunk_3, fig.dim = c(15,15)}
# - Requires R-libraries (chunk: set-up) and object response_tbl (chunk: chunk_2a) - #

# Optional: rearrange so that diagonal of the plot shows responses in order of magnitude
response_tbl <- 
  response_tbl %>%
  mutate(
    .before = Var1,
    Var1 = case_when (
      Var1_value %in% c("high BMI", "low BMI") ~ "BMI",
      Var1_value %in% c(">=40 years", "<40 years") ~ "Age",
      Var1_value %in% c("Asian", "Black", "White") ~ "Ethnic",
      Var1_value %in% c("Chronic disease", "Acute disease") ~ "Type",
      Var1_value %in% c("Female", "Male") ~ "Sex"
      ),
    Var2 = case_when (
      Var2_value %in% c("high BMI", "low BMI") ~ "BMI",
      Var2_value %in% c(">=40 years", "<40 years") ~ "Age",
      Var2_value %in% c("Asian", "Black", "White") ~ "Ethnic",
      Var2_value %in% c("Chronic disease", "Acute disease") ~ "Type",
      Var2_value %in% c("Female", "Male") ~ "Sex"
      )
    ) %>% 
    mutate(
      pVar_equal = (Var1 == Var2)
      ) %>%  
    { rbind( 
        filter(., pVar_equal) %>% 
          group_by(Var1) %>%
          arrange(desc(max_response), .by_group = TRUE) %>%
          mutate(max_value = max(max_response, na.rm = TRUE)) %>%
          arrange(desc(max_value)) %>% 
          select (!max_value),
        filter(., !pVar_equal) 
        ) 
      } 

# Select and reshape  

response_tbl %>% 
  select(
    Var1,
    Var1_value, Var2_value, 
    N_max, N_0, 
    max_resp_dose, max_response
    ) %>% 
  pivot_wider(
    names_from = "Var2_value",
    values_from = c(
      "max_resp_dose", "max_response", "N_max", "N_0"), 
      names_sep = "-"
      ) %>% 
  pivot_longer(
    cols = !c("Var1", "Var1_value"),
    names_to = c("resp", "Var2_value"),
    values_to = c("max_response"), names_sep = "-"
    ) %>% 
  pivot_wider(
    names_from = "resp", 
    values_from = "max_response") %>% 
  mutate(
    Var1 = as.factor(Var1)
    ) %>% 

# Plot data
  ggplot(
    aes(
      x = Var1_value %>% 
        factor(., levels = unique(.) %>% rev ), 
      y = Var2_value %>% 
        factor(., levels = unique(.) %>% rev ),
      col   = max_response,
      label = max_response %>% round(3) 
      )
    ) +
    geom_tile(
      aes(fill= factor(max_resp_dose)),
      col="lightgrey"
      ) +
    scale_fill_manual(
      values = c("100" = "#BBE0CF", "200" = "#D5F9E8"),
      na.translate = F
      ) +
    geom_text(
      col = "black", 
      vjust = 2.5, hjust = 0.5, 
      size = 10/.pt
      ) +
    geom_point(
      aes( size = N_0), 
      shape = 15, 
      color = "white",
      position = position_nudge(y = 0.1)
      ) +
    geom_point(
      aes( size = N_max), 
      shape = 19,
      position = position_nudge(y = 0.1)
      ) +
    geom_point(
      aes( size = N_0), 
      shape = 22, 
      color = "darkblue",
      position = position_nudge(y = 0.1)
      ) +
    scale_size(range = c(1, 15), name = "N") +
    labs(
      x = NULL, y = NULL, 
      col = "Maximum\nresponse",
      fill = "Dose",
      title = "Best median response, stratified by one or two patient characteristics") +
    scale_color_gradient2(
      low = "white", high="darkblue", 
      limits = c(-0.25, 1.5)
      ) +
    scale_x_discrete(
      position = "top"
      ) +
    scale_y_discrete() +
    theme_light(base_size = 15) + 
    theme(
      axis.text.x = element_text(
        angle = 90, 
        vjust = 0.5,
        hjust = 0
        ),
      panel.grid = element_blank() 
    )

```
<br>

Tiles in the plot correspond to patient groups characterised by the row and column labels.
Magnitude of the maximum median response in each patient group is shown by the colour of the dots and the numerical values below them. The numbers (N) of patients in the different groups is indicated by the size of the dots (treated), and white squares with dark blue border (untreated).
The dose that achieved the maximum median response is shown by the colour of the tiles (dark green: 100, lighter green: 200).  
<br>

The diagonal shows groups stratified by a single characteristic, arranged so that the magnitude of the responses increases from bottom left to top right. The acute disease type was associated with the highest response, followed by female sex, and White ethnic. Conversely, patients with chronic disease, or were male or Black, had the lowest responses. BMI and age had relatively smaller effects as a single stratifier.  

When two characteristics were applied, females <40 years had the highest response, followed by Whites with acute disease, White females, and females or Blacks with acute disease.
The group wit the lowest median response were patients with chronic disease and high BMI. Low responses were also observed in patients who were Black and male, <40 years, with chronic disease, or high BMI. This is in contrast to the Blacks with acute disease having among the highest responses. However, numbers in these groups were relatively small and the result might need confirmation in a larger sample.

In most groups, the higher dose (200) was associated with the greater response, but Asians with chronic disease or high BMI, or patients with high BMI and acute disease might benefit more from the lower dose.
<br>
<br>

#### 4.3. Best response in patients stratified by demographic and clinical parameters - showing Wilcoxon / Mann-Whitney test p-values for difference between treated and matched untreated subroups 
<br>

```{r chunk_4}
## Calculate Wilcoxon test p-values for all comparisons

wilcox_p_value <- function(x, y) {
  test <- wilcox.test(x, y)
  return(test$p.value)
}

wilcox.test_results <- list ()

for (i in 1: length(pChar_pairs)) {
  wilcox.test_results_j <- list()

  for (j in 1: nrow(pChar_pairs[[i]])) {
    x <- pChar_pairs[[i]] %>% names
    y <- pChar_pairs[[i]] %>% .[j, ]%>% set_names(x)
    # Ensure names are preserved when cbinding as transformed dataframe below
    if (length(x) == 1) {
      y <- as.data.frame (t(y))
      }

  wilcox.test_results_j[[j]] <- 
    exampleData %>% 
      {if (length(x) == 1) {
        filter(.,
          get(x[1]) == paste(y[1])  
          ) 
        } else {
          filter(.,
            get(x[1]) == paste(y[1]) & 
            get(x[2]) == paste(y[2])
            ) 
          } 
        } %>% 
      summarise(
        p_value_0_vs_100 = wilcox_p_value(target[dose == "0"], target[dose == "100"] ),
        p_value_0_vs_200 = wilcox_p_value(target[dose == "0"], target[dose == "200"] )
        ) %>% 
      cbind(y, .)
    }
    wilcox.test_results[[i]] <- wilcox.test_results_j

  }

wilcox.test_results <- 
wilcox.test_results %>% 
  flatten() %>% 
  lapply(function(df)
      if(
        ncol(df) < 4) {
        cbind(df[, 1, drop = FALSE], df)    
        }else{
          df} 
      ) %>% 
    lapply(function(df)
      set_names(df,
        "Var1_value", "Var2_value", 
        "p_value_0_vs_100", "p_value_0_vs_200"
        ) 
      ) %>% 
    list_rbind() %>% 
    mutate(
      log.p_100 = log10(p_value_0_vs_100) %>% round(digits = 2),
      log.p_200 = log10(p_value_0_vs_200) %>% round(digits = 2)
    ) %>% 
    select(
      !c(p_value_0_vs_100, p_value_0_vs_200)
    )

```


```{r chunk_5, fig.dim = c(15,15)}
wilcox.test_results  <- 
  wilcox.test_results %>% 
    unite(
      Vars1_2,
      c(Var1_value, Var2_value), 
      sep = "_", 
      remove = F
      )

response_tbl %>% 
  unite(
    Vars1_2,
    c(Var1_value, Var2_value), 
    sep = "_", 
    remove = F
    ) %>% 
  left_join(
    wilcox.test_results) %>% 
  mutate(
     log.p_max.resp = case_when(
      max_resp_dose == "100" ~ log.p_100, 
      max_resp_dose == "200" ~ log.p_200
     )
    ) %>% 
  
# Select and reshape  
  select(
    #Var1,
    Var1_value, Var2_value, 
    log.p_max.resp, 
    max_resp_dose, max_response
    ) %>% 
  pivot_wider(
    names_from = "Var2_value",
    values_from = c(
      "max_resp_dose", "max_response", "log.p_max.resp"), 
      names_sep = "-"
      ) %>% 
  pivot_longer(
    cols = !c("Var1", "Var1_value"),
    names_to = c("resp", "Var2_value"),
    values_to = c("max_response"), names_sep = "-"
    ) %>% 
  pivot_wider(
    names_from = "resp", 
    values_from = "max_response") %>% 
  mutate(
    Var1_value = as.factor(Var1_value)
    ) %>% 

# Plot data
  ggplot(
    aes(
      x = Var1_value %>% 
        factor(., 
          levels = unique(.) %>% rev
          ), 
      y = Var2_value %>% 
        factor(., 
          levels = unique(.) %>% rev 
          ),
      col   = max_response,
      label = max_response %>% round(3) 
      )
    ) +
    geom_tile(
      aes(fill= factor(max_resp_dose)),
      col="lightgrey"
      ) +
    scale_fill_manual(
      values = c("100" = "#BBE0CF", "200" = "#D5F9E8"),
      na.translate = F
      ) +
    geom_text(
      col = "black", 
      vjust = 3.5, hjust = 0.5, 
      size = 10/.pt
      ) +
    geom_point(
      aes( size = log.p_max.resp), 
      shape = 19,
      position = position_nudge(y = 0.1)
      ) +
    scale_size(
      range = c(18, 1), 
      name = "log.p_max.resp") +
    labs(
      x = NULL, y = NULL, 
      col = "Maximum\nresponse",
      fill = "Dose",
      title = "Best median response, stratified by one or two patient characteristics",
      subtitle = "\nlog.p: Wilcox test"
      ) +
    scale_color_gradient2(
      low = "white", high="darkblue", 
      limits = c(-0.25, 1.5)
      ) +
    scale_x_discrete(
      position = "top"
      ) +
    scale_y_discrete() +
    theme_light(base_size = 15) + 
    theme(
      axis.text.x = element_text(
        angle = 90, 
        vjust = 0.5,
        hjust = 0
        ),
      panel.grid = element_blank() 
      )

wilcox.test_results %>% 
  select(!Vars1_2) %>% 
  kable(., "html") %>% 
    scroll_box(width = "50%", height = "150px") %>% 
    kable_styling( 
      font_size = 10,
      bootstrap_options = "striped"
      )

```
<br>
<br>

#### 4.4. Best response in patients stratified by demographic and clinical parameters - showing Mood test p-values for difference between treated and matched untreated subroups 
<br>

```{r chunk_6}

## Calculate Mood test p-values for all comparisons

mood_p_value <- function(x, y) {
  test <- mood.test(x, y)
  return(test$p.value)
}

mood.test_results <- list ()

for (i in 1: length(pChar_pairs)) {
  mood.test_results_j <- list()

  for (j in 1: nrow(pChar_pairs[[i]])) {
    x <- pChar_pairs[[i]] %>% names
    y <- pChar_pairs[[i]] %>% .[j, ]%>% set_names(x)
    # Ensure names are preserved when cbinding as transformed dataframe below
    if (length(x) == 1) {
      y <- as.data.frame (t(y))
      }

  mood.test_results_j[[j]] <- 
    exampleData %>% 
      {if (length(x) == 1) {
        filter(.,
          get(x[1]) == paste(y[1])  
          ) 
        } else {
          filter(.,
            get(x[1]) == paste(y[1]) & 
            get(x[2]) == paste(y[2])
            ) 
          } 
        } %>% 
      summarise(
        p_value_0_vs_100 = mood_p_value(target[dose == "0"], target[dose == "100"] ),
        p_value_0_vs_200 = mood_p_value(target[dose == "0"], target[dose == "200"] )
        ) %>% 
      cbind(y, .)
    }
    mood.test_results[[i]] <- mood.test_results_j

  }

mood.test_results <- 
mood.test_results %>% 
  flatten() %>% 
  lapply(function(df)
      if(
        ncol(df) < 4) {
        cbind(df[, 1, drop = FALSE], df)    
        }else{
          df} 
      ) %>% 
    lapply(function(df)
      set_names(df,
        "Var1_value", "Var2_value", 
        "p_value_0_vs_100", "p_value_0_vs_200"
        ) 
      ) %>% 
    list_rbind() %>% 
    mutate(
      log.p_100 = log10(p_value_0_vs_100) %>% round(digits = 2),
      log.p_200 = log10(p_value_0_vs_200) %>% round(digits = 2)
    ) %>% 
    select(
      !c(p_value_0_vs_100, p_value_0_vs_200)
    )

```


```{r chunk_7, fig.dim = c(15,15)}
mood.test_results  <- 
  mood.test_results %>% 
    unite(
      Vars1_2,
      c(Var1_value, Var2_value), 
      sep = "_", 
      remove = F
      )

response_tbl %>% 
  unite(
    Vars1_2,
    c(Var1_value, Var2_value), 
    sep = "_", 
    remove = F
    ) %>% 
  left_join(
    mood.test_results) %>% 
  mutate(
     log.p_max.resp = case_when(
      max_resp_dose == "100" ~ log.p_100, 
      max_resp_dose == "200" ~ log.p_200
     )
    ) %>% 
  
# Select and reshape  
  select(
    #Var1,
    Var1_value, Var2_value, 
    log.p_max.resp, 
    max_resp_dose, max_response
    ) %>% 
  pivot_wider(
    names_from = "Var2_value",
    values_from = c(
      "max_resp_dose", "max_response", "log.p_max.resp"), 
      names_sep = "-"
      ) %>% 
  pivot_longer(
    cols = !c("Var1", "Var1_value"),
    names_to = c("resp", "Var2_value"),
    values_to = c("max_response"), names_sep = "-"
    ) %>% 
  pivot_wider(
    names_from = "resp", 
    values_from = "max_response") %>% 
  mutate(
    Var1_value = as.factor(Var1_value)
    ) %>% 

# Plot data
  ggplot(
    aes(
      x = Var1_value %>% 
        factor(., 
          levels = unique(.) %>% rev
          ), 
      y = Var2_value %>% 
        factor(., 
          levels = unique(.) %>% rev 
          ),
      col   = max_response,
      label = max_response %>% round(3) 
      )
    ) +
    geom_tile(
      aes(fill= factor(max_resp_dose)),
      col="lightgrey"
      ) +
    scale_fill_manual(
      values = c("100" = "#BBE0CF", "200" = "#D5F9E8"),
      na.translate = F
      ) +
    geom_text(
      col = "black", 
      vjust = 3.5, hjust = 0.5, 
      size = 10/.pt
      ) +
    geom_point(
      aes( size = log.p_max.resp), 
      shape = 19,
      position = position_nudge(y = 0.1)
      ) +
    scale_size(
      range = c(18, 1), 
      name = "log.p_max.resp") +
    labs(
      x = NULL, y = NULL, 
      col = "Maximum\nresponse",
      fill = "Dose",
      title = "Best median response, stratified by one or two patient characteristics",
      subtitle = "\nlog.p: Mood test"
      ) +
    scale_color_gradient2(
      low = "white", high="darkblue", 
      limits = c(-0.25, 1.5)
      ) +
    scale_x_discrete(
      position = "top"
      ) +
    scale_y_discrete() +
    theme_light(base_size = 15) + 
    theme(
      axis.text.x = element_text(
        angle = 90, 
        vjust = 0.5,
        hjust = 0
        ),
      panel.grid = element_blank() 
      )

mood.test_results %>% 
  select(!Vars1_2) %>% 
  kable(., "html") %>% 
    scroll_box(width = "50%", height = "150px") %>% 
    kable_styling( 
      font_size = 10,
      bootstrap_options = "striped"
      )

```
<br>
<br>

### 5. Distribution of target values in patient subgroups treated with different doses  
<br>

The violins in the plots indicate whether the assumption of the Wilcoxon test (same shape of the two distributions whose medians are compared) are satisfied.

```{r chunk_8}

## Custom ggproto object for generating split violin plots
# From: https://stackoverflow.com/questions/35717353/split-violin-plot-with-ggplot2

GeomSplitViolin <- ggplot2::ggproto(
    "GeomSplitViolin",
    ggplot2::GeomViolin,
    draw_group = function(self,
                          data,
                          ...,
                          # add the nudge here
                          nudge = 0,
                          draw_quantiles = NULL) {
        data <- transform(data,
                          xminv = x - violinwidth * (x - xmin),
                          xmaxv = x + violinwidth * (xmax - x))
        grp <- data[1, "group"]
        newdata <- plyr::arrange(transform(data,
                                           x = if (grp %% 2 == 1) xminv else xmaxv),
                                 if (grp %% 2 == 1) y else -y)
        newdata <- rbind(newdata[1, ],
                         newdata,
                         newdata[nrow(newdata), ],
                         newdata[1, ])
        newdata[c(1, nrow(newdata)-1, nrow(newdata)), "x"] <- round(newdata[1, "x"])

        # now nudge them apart
        newdata$x <- ifelse(newdata$group %% 2 == 1,
                            newdata$x - nudge,
                            newdata$x + nudge)

        if (length(draw_quantiles) > 0 & !scales::zero_range(range(data$y))) {

            stopifnot(all(draw_quantiles >= 0), all(draw_quantiles <= 1))

            quantiles <- ggplot2:::create_quantile_segment_frame(data,
                                                             draw_quantiles)
            aesthetics <- data[rep(1, nrow(quantiles)),
                               setdiff(names(data), c("x", "y")),
                               drop = FALSE]
            aesthetics$alpha <- rep(1, nrow(quantiles))
            both <- cbind(quantiles, aesthetics)
            quantile_grob <- ggplot2::GeomPath$draw_panel(both, ...)
            ggplot2:::ggname("geom_split_violin",
                             grid::grobTree(ggplot2::GeomPolygon$draw_panel(newdata, ...),
                                            quantile_grob))
        }
    else {
            ggplot2:::ggname("geom_split_violin",
                             ggplot2::GeomPolygon$draw_panel(newdata, ...))
        }
    }
)

geom_split_violin <- function(mapping = NULL,
                              data = NULL,
                              stat = "ydensity",
                              position = "identity",
                              # nudge param here
                              nudge = 0,
                              ...,
                              draw_quantiles = NULL,
                              trim = TRUE,
                              scale = "area",
                              na.rm = FALSE,
                              show.legend = NA,
                              inherit.aes = TRUE) {

    ggplot2::layer(data = data,
                   mapping = mapping,
                   stat = stat,
                   geom = GeomSplitViolin,
                   position = position,
                   show.legend = show.legend,
                   inherit.aes = inherit.aes,
                   params = list(trim = trim,
                                 scale = scale,
                                 # don't forget the nudge
                                 nudge = nudge,
                                 draw_quantiles = draw_quantiles,
                                 na.rm = na.rm,
                                 ...))
}

```

<br>
<br>

#### 5.1. Dose vs. target values in patients stratified by sex and age  
<br>
(see also 3.6.: female patients stratified by sex and age)

```{r chunk_9, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- compare_means(
  data = exampleData,
  target ~ dose,
  group.by = c("sex", "age"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("sex", "age", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Sex", "Age", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select( dose, target) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200") 
        ), 
      y = target,
      fill = sex) 
      ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ age) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 2),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

#### 5.2. Dose vs. target values in patients stratified by sex and type of disease  

```{r chunk_10, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- compare_means(
  data = exampleData,
  target ~ dose,
  group.by = c("sex", "type"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("sex", "type", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Sex", "Type", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select( dose, target) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200") 
        ), 
      y = target,
      fill = sex) 
      ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ type) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1.5),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

#### 5.3. Dose vs. target values in patients stratified by ethnic and type of disease  
<br>
(see also 3.5.: female patients stratified by ethnic and type of disease)

```{r chunk_11, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- compare_means(
  data = exampleData,
  target ~ dose,
  group.by = c("type", "race"),
  ref.group = "0",
 ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select(!".y." & !"group1" & !"method")  %>% 
  set_names(
    "Sex", "Ethnic", "Dose", "p", "p.adj", "p.format", "p.signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by( bmi, age, race, sex, type) %>% 
  select( dose, target) %>% 
  ggplot(
    aes(
      x= factor(dose, levels = c("0", "100", "200") ), 
      y = target,
      fill = type) ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid( .~race) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 3),
widths = c(0.2, 1, 1),
align = "h"
)    
  
```
<br>
<br>
Interestingly, Blacks with chronic disease had high target levels, even when untreated,
<br>
<br>

#### 5.4. Dose vs. target values in patients stratified by race and sex  

```{r chunk_12, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- compare_means(
  data = exampleData,
  target ~ dose,
  group.by = c("sex", "race"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select(!".y." & !"group1" & !"method")  %>% 
  set_names(
    "Sex", "Ethnic", "Dose", "p", "p.adj", "p.format", "p.signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select (dose, target) %>% 
  ggplot(
    aes(
      x= factor(dose, levels = c("0", "100", "200") ), 
      y = target,
      fill = sex) 
      ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid( .~race) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 2),
widths = c(0.2, 1, 1),
align = "h"
)    
  
```
<br>
<br>

#### 5.5. Dose vs. target values in female patients stratified by ethnic and disease type  

```{r chunk_13, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- 
  exampleData %>% 
  filter(sex == "Female") %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = c("race", "type"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("race", "type", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Ethnic", "Type", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select (dose, target) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200") 
        ), 
         y = target,
         fill = type) 
      ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ race) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 3),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

#### 5.6. Dose vs. target values in female patients stratified by ethnic and age  

```{r chunk_14, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- 
  exampleData %>% 
  filter(sex == "Female") %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = c("race", "age"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("race", "age", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Ethnic", "Age", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select (dose, target) %>% 
  ggplot (
    aes (x= factor(dose, levels = c("0", "100", "200") ), 
         y = target,
         fill = age) ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ race) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 2.5),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

Younger white females appear to respond better than older, especially at the higher dose, whereas the opposite appears to be true for Asian females (not sure about the significance of that...).
<br>
<br>

#### 5.7. Dose vs. target values in White patients stratified by sex and disease type  

```{r chunk_15, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- 
  exampleData %>% 
  filter(race == "White") %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = c("sex", "type"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("sex", "type", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Sex", "Type", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select (dose, target) %>% 
  ggplot (
    aes (x= factor(dose, levels = c("0", "100", "200") ), 
         y = target,
         fill = sex) ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ type) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1.5),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

#### 5.8. Dose vs. target values in White patients stratified by sex and age  

```{r chunk_16, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- 
  exampleData %>% 
  filter(race == "White") %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = c("sex", "age"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("sex", "age", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Sex", "Age", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select (dose, target) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200") 
        ), 
      y = target,
      fill = sex
      ) 
    ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
     geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ age) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1.5),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

#### 5.9. Dose vs. target values in patients stratified by race and BMI 
<br>
(The difference between median targets in the Black/ low BMI/ dose 100 group had the highest significance in the Mood test)  

```{r chunk_17, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

sign_test <- 
  exampleData %>% 
  filter(race == "White") %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = c("race", "bmi"),
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("race", "bmi", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Ethnic", "BMI", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme("light")
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 
    

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  group_by(bmi, age, race, sex, type) %>% 
  select(dose, target) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200")
        ), 
      y = target,
      fill = bmi
      ) 
    ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
     geom_split_violin( 
      width = 1,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
        width = 0.3, 
        outlier.shape = NA) +
    facet_grid(. ~ race) +
    theme_bw() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) + 
    labs(
      x = "Dose", 
      y = "Target", 
      size = 12, 
      hjust = -15
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1),
widths = c(0.2, 1, 1),
align = "h"
)    

```
<br>
<br>

### 6. Groups with the highest and lowest responses
<br>

It appears that the groups the received the most significant benefit were women who were either <40 years (p.adj = 7.9 * 10^-13^, median difference 1.474), White (p.adj = 1.2 * 10^-12^, median difference 1.406), or with acute disease (p.adj = 3.9 * 10^-12^, median difference 1.407). 
Whites with acute disease or <40 years also showed significant benefit (p.adj = 2.7 * 10^-10^, median difference 1.421; median difference 1.474, 3.3 * 10^-9^, median difference 1.377), but this could be mainly because of the female sub-population of these groups.  
<br>

#### 6.1. White females <40 years respond better than the remaining patients
<br>

```{r chunk_18, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

exampleData <- 
  exampleData %>% 
    mutate(
      Group = 
        case_when(
          race == "White" &
          #type == "Acute disease" &
          age == "<40 years" &
          sex == "Female"
             ~ "White / F / <40 yrs",
        TRUE ~ "Remaining"
        )
      )

sign_test <- 
  exampleData %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = "Group",
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("Group", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Group", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme(
      "light", 
      base_size = 10
      ),
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  select (dose, target, type, Group) %>% 
  group_by(Group) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200")
        ), 
      y = target,
      fill = Group 
      ) 
    ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    fill_palette(
      palette = c("lightgrey","salmon")
      ) +
    geom_split_violin( 
      width = 1,
      nudge = 0.01,
      alpha = 0.3,
      color = "grey") +
    geom_boxplot(
      width = 0.2, 
      outlier.shape = NA) +
    geom_point(
      pch = 21,
      size = 3,
      position = 
        position_jitterdodge(
          dodge.width = 0.7, 
          jitter.width = 0.1
          ),
      color = "grey",
      alpha = 0.5
      ) +
    theme_light() +
    theme(
      text=element_text( size = 13), 
      axis.text = element_text( size = 12),
      ) +
    scale_y_continuous(
      breaks = c(-2: 5),
      minor_breaks = NULL
      ) +    
    labs(
      x = "Dose", 
      y = "Target", 
      size = 13, hjust = -15,
      title = "Target vs. dose levels in the group with highest responses\n"
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1),
widths = c(0.2, 1, 1),
align = "h"
)    

```
             
<br>
<br>

#### 6.2. Black males with chronic disease show no or negative response
<br>
However, this might need confirmation in a larger sample of this subgroup.
<br>

```{r chunk_19, fig.dim = c(10, 7.5)}
# - Requires R-libraries and objects exampleData (chunk: set-up) and GeomSplitViolin (chunk 5) - #

# Generate a table of significant differences (Wilcoxon test) 

exampleData <- 
  exampleData %>% 
    mutate(
      Group = 
        case_when(
          race == "Black" &
          # bmi == "high BMI" &
           type == "Chronic disease" &
          # age == ">=40 years" &
          sex == "Male"
             ~ "Black/ M / Chronic disease",
        TRUE ~ "Remaining"
        )
      )

sign_test <- 
  exampleData %>% 
  compare_means(
  data = .,
  target ~ dose,
  group.by = "Group",
  ref.group = "0",
  ) %>%
  filter (
    !group1 == "100" &
    !p.signif == "ns"  ) %>% 
  select("Group", "group2", "p.format", "p.adj", "p.signif")  %>% 
  set_names(
    "Group", "Dose", "p", "p.adj", "signif") %>% 
  ggtexttable(
    rows = NULL,
    theme = ttheme(
      "light", 
      base_size = 10
      ),
    ) %>% 
  tab_add_title(
    text = "Wilcoxon test (ref. dose = 0)", 
    face = "bold", size = 12,
    ) 

# Generate split violin plot and insert the Wilcoxon test table 

ggarrange(

exampleData %>% 
  select (dose, target, type, Group) %>% 
  group_by(Group) %>% 
  ggplot(
    aes(
      x= factor(
        dose, 
        levels = c("0", "100", "200")
        ), 
      y = target,
      fill = Group 
      ) 
    ) +
    geom_hline(
      yintercept = 0, 
      color = "darkgrey",
      size = 1.1
      ) +
    fill_palette(
      palette = c("turquoise", "lightgrey")
      ) +
    geom_split_violin( 
      width = 1,
      nudge = 0.01,
      alpha = 0.3,
      color = "grey") +
  geom_boxplot(
      width = 0.2, 
      outlier.shape = NA) +
  geom_point(
    pch = 21,
    size = 3,
    position = 
      position_jitterdodge(
        dodge.width = 0.7, 
        jitter.width = 0.1
        ),
    color = "grey",
    alpha = 0.5
    ) +
  theme_light() +
  theme(
    text=element_text( size = 13), 
    axis.text = element_text( size = 12),
    ) +
  scale_y_continuous(
    breaks = c(-2: 5),
    minor_breaks = NULL
    ) +    labs(
      x = "Dose", 
      y = "Target", 
      size = 13, hjust = -15,
      title = "Target vs. dose levels in the group with lowest responses\n"
      ),

# Add space between plot and table
NULL,

sign_test,

ncol = 1, nrow = 3,
heights = c(2, 0.1, 1),
widths = c(0.2, 1, 1),
align = "h"
)    

```