---
title: "
"
output:
html_document:
self_containded: TRUE
code_download: yes
code_folding: none # none hide show
toc: false
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(warning = FALSE, message = FALSE, comment = NA, include = FALSE)
knitr::opts_chunk$set(cache = FALSE)
```
```{r}
pacman::p_load(tidyverse, rio)
pacman::p_load(gt, gtsummary)
pacman::p_load(tidybayes)
library(brms)
pacman::p_load(sjstats)
pacman::p_load(labelled)
```
```{r}
d1 <- import("https://raw.githubusercontent.com/VIS-SIG/Wonderful-Wednesdays/master/data/2020/2020-10-14/mediation_data.csv") %>%
janitor::clean_names(case = 'old_janitor')%>%
mutate(trt = as.factor(trt))
d1 %>%
export("mediation_data.csv")
```
```{r}
set.seed(12345)
d2 <- d1 %>%
mutate(itch_miss = ifelse(itch_locf == TRUE, NA, itch),
bsa_miss = ifelse(bsa_locf == TRUE, NA, bsa),
redness_miss = ifelse(redness_locf == TRUE, NA, redness),
dlqi_miss = ifelse(dlqi_locf == TRUE, NA, dlqi)) %>%
select(trt,
itch_locf = itch, bsa_locf = bsa, redness_locf = redness,
dlqi_locf = dlqi,
contains("_miss")) %>%
pivot_longer(cols = c('itch_locf', 'bsa_locf', 'redness_locf',
'itch_miss', 'bsa_miss', 'redness_miss'),
names_to = "med_name",
values_to = "med_value") %>%
drop_na(med_value) %>%
pivot_longer(cols = c('dlqi_locf','dlqi_miss'),
names_to = "dv_name",
values_to = "dv_values") %>%
drop_na(dv_values) %>%
group_by(dv_name, med_name) %>%
nest_by() %>%
filter(dv_name == "dlqi_locf") %>%
mutate(med = list( brm( bf(med_value ~ trt) +
bf(dv_values ~ trt + med_value) + set_rescor(FALSE),
data = data )
)
)
```
```{r}
pacman::p_load(DiagrammeR, vtree)
grViz("digraph causal {
# Nodes
node [shape = reactangle, fontname = Arial, style = filled]
iv [label = 'TRT', fillcolor = '#7FC97F']
me [label = 'Mediator', shape = ellipse]
dv [label = 'DLQI', fillcolor = '#7FC97F']
# Edges
edge [color = black, arrowhead = normal]
rankdir = LR
iv -> me
iv -> dv [label = 'DIRECT', fontcolor = '#7FC97F', color = '#7FC97F']
me -> dv
# Graph
graph [overlap = true, fontsize = 10]
}") %>%
grVizToPNG(width = 300,
height = 100,
filename = "_direct.png")
grViz("digraph causal {
# Nodes
node [shape = reactangle, fontname = Arial, style = filled]
iv [label = 'TRT', fillcolor = '#BEAED4']
me [label = 'Mediator', fillcolor = '#BEAED4', shape = ellipse]
dv [label = 'DLQI', fillcolor = '#BEAED4']
# Edges
edge [color = black, arrowhead = normal]
rankdir = LR
iv -> me [label = 'INDIRECT', fontcolor = '#BEAED4', color = '#BEAED4']
iv -> dv [label = ' ']
me -> dv [label = 'INDIRECT', fontcolor = '#BEAED4', color = '#BEAED4']
# Graph
graph [overlap = true, fontsize = 10]
}") %>%
grVizToPNG(width = 450,
height = 100,
filename = "_indirect.png")
```
```{r}
d3 <- d2 %>%
mutate(med_results = list( sjstats::mediation(med, prob = 0.95, typical = "mean") %>%
as.data.frame() %>%
pivot_wider(names_from = "effect",
values_from = c("value","hdi.low","hdi.high"),
names_glue = "{effect}_{.value}")),
post_data = list( posterior_samples(med) %>%
transmute(direct = b_dvvalues_trtRx,
indirect = b_medvalue_trtRx * b_dvvalues_med_value,
total = direct + indirect,
p_mediated = indirect/total) ),
p_mediated_col = cut( med_results$`proportion mediated_value`,
breaks = seq(-1, 1, 0.2),
labels = RColorBrewer::brewer.pal(10,"RdYlBu") ),
gg_mediated = list(post_data %>%
ggplot(aes(x = p_mediated)) +
stat_slab(fill = p_mediated_col, alpha = 0.5) +
geom_vline(xintercept = 0, color = "black", size = 3) +
labs(x = NULL,
y = NULL) +
coord_cartesian(xlim = c(-2.5, 2.5),
ylim = c(-0.01, 1),
expand = FALSE) +
theme_void()),
gg_effect = list(post_data %>%
select(direct, indirect) %>%
pivot_longer(cols = 1:2) %>%
ggplot(aes(x = value, fill = name)) +
stat_slab(alpha = 0.75) +
geom_vline(xintercept = 0, color = "black", size = 3) +
labs(x = NULL,
y = NULL) +
scale_fill_brewer(palette = "Accent") +
coord_cartesian(xlim = c(-10, 5),
ylim = c(-0.01, 1),
expand = FALSE) +
theme_void()+
guides( fill = FALSE))
)
```
```{r}
fmt_ggplot <- function(
data,
columns,
rows = NULL,
height = 100,
aspect_ratio = 1.0) {
rows <- rlang::enquo(rows)
fmt(
data = data,
columns = columns,
rows = !!rows,
fns = list(
html = function(x) {
map(
x,
ggplot_image,
height = height,
aspect_ratio = aspect_ratio
)
}
)
)
}
```
```{r include = TRUE, echo = FALSE}
t1 <- d3 %>%
ungroup() %>%
separate(med_name, c("var","anly"), "_") %>%
mutate(var = factor(var, labels = c("BSA","Itch","Redness")) %>%
fct_relevel("Itch","Redness","BSA"),
anly = factor(anly, labels = c("Analyses w/ LOCF","Analyses w/ Observed"))) %>%
filter(dv_name %>% str_detect("locf")) %>%
group_by(anly) %>%
select(-data, -med, -post_data) %>%
unnest(cols = med_results) %>%
arrange(var) %>%
gt() %>%
cols_hide(vars(dv_name, total_value,
total_hdi.low, total_hdi.high, p_mediated_col,
mediator_value, mediator_hdi.low, mediator_hdi.high)) %>%
cols_move(vars(gg_effect), vars(indirect_value)) %>%
cols_align(align = "left", columns = vars(var)) %>%
fmt_number(columns = vars(direct_value, direct_hdi.low, direct_hdi.high),
n_sigfig = 2) %>%
cols_merge(columns = vars(direct_value, direct_hdi.low, direct_hdi.high),
pattern = "{1}
({2}, {3})"
) %>%
fmt_number(columns = vars(indirect_value, indirect_hdi.low, indirect_hdi.high),
n_sigfig = 2) %>%
cols_merge(columns = vars(indirect_value, indirect_hdi.low, indirect_hdi.high),
pattern = "{1}
({2}, {3})"
) %>%
fmt_number(columns = vars(`proportion mediated_value`, `proportion mediated_hdi.low`, `proportion mediated_hdi.high`),
n_sigfig = 2) %>%
cols_merge(columns = vars(`proportion mediated_value`, `proportion mediated_hdi.low`, `proportion mediated_hdi.high`),
pattern = "{1}
({2}, {3})"
) %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body(
columns = vars(direct_value),
rows = sign(direct_hdi.low) == sign(direct_hdi.high)
)
) %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body(
columns = vars(indirect_value),
rows = sign(indirect_hdi.low) == sign(indirect_hdi.high)
)
) %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body(
columns = vars(`proportion mediated_value`),
rows = sign(`proportion mediated_hdi.low`) == sign(`proportion mediated_hdi.high`)
)
) %>%
data_color(
columns = vars(`proportion mediated_value`),
colors = scales::col_bin(
palette = RColorBrewer::brewer.pal(10,"RdYlBu"),
domain = seq(-1, 1, 0.2),
bins = 10),
alpha = 0.5,
autocolor_text = FALSE
) %>%
fmt_ggplot(
columns = vars(gg_mediated, gg_effect),
height = 40,
aspect_ratio = 3
) %>%
cols_label(var = "Mediator",
direct_value = html(' Direct '),
indirect_value = html(' Indirect '),
`proportion mediated_value` = html("Proportion
Mediated"),
gg_mediated = html("Viz(Mediated)
− ←‒ 0 ‒→ +"),
gg_effect = html("Viz(Effect)
− ←‒‒‒‒‒‒ 0 → +")
)%>%
tab_header(
title = md("**Mediation Results** based on Bayesian models"),
subtitle = md("Is the **Treatment** Effect on **DLQI** mediated?")
) %>%
tab_footnote(locations = cells_title("subtitle"),
footnote = "Dermatology Life Quality Index (DLQI) at 24 weeks. DLQI ranges from 0 to 30
the lower score the better") %>%
tab_footnote(locations = cells_body(
columns = "var",
rows = var %in% c("Itch","Redness")
),
footnote = "Patient self report daily, ranges from 0-10 and averaged every week. The lower the score the better") %>%
tab_footnote(locations = cells_body(
columns = "var",
rows = var == "BSA"
),
footnote = "Physician measure, ranges from 0-100%. The lower the score the better") %>%
tab_footnote(locations = cells_row_groups(groups = "Analyses w/ LOCF"),
footnote = "Missing data was imputed using Last Observation Carried Forward (LOCF)") %>%
tab_footnote(locations = cells_column_labels(
columns = vars(`proportion mediated_value`)
),
footnote = html('Proportion Mediated: is the ratio of the INDIRECT effect to the total effect ( DIRECT + INDIRECT )')) %>%
tab_source_note(html(
details::details(
'%
tab_source_note(html(
details::details(
'%
opt_align_table_header( align = "left") %>%
opt_all_caps(locations = "column_labels") %>%
tab_options(table.font.size = px(14),
data_row.padding = px(2),
row_group.font.weight = "bold",
footnotes.font.size = px(12),
footnotes.padding = px(1)) %>%
opt_table_font(
font = list(google_font(name = "Source Sans Pro"))
)
t1
```