Nothing
params <-
list(EVAL = TRUE)
## ----setup, message=FALSE, warning=FALSE--------------------------------------
library(knitr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(purrr)
library(broom)
library(gganimate)
library(multiverse)
## ----include=FALSE------------------------------------------------------------
M = multiverse()
## ----chunk-setup, include=FALSE-----------------------------------------------
opts_chunk$set(
echo = TRUE,
eval = if (isTRUE(exists("params"))) params$EVAL else FALSE,
fig.width = 6,
fig.height = 4
)
## ----data---------------------------------------------------------------------
data("vis_correlation")
df <- vis_correlation |>
group_by( vis, rbase, approach, sign ) |>
select(-c(condition, visandsign, participant)) |>
summarise( jnd = list(jnd) ) |>
mutate(
median = map_dbl(jnd, ~median(.x)),
mads = map_dbl(jnd, ~mad(.x, constant = 1)),
jnd_limit = 3 * mads
) |>
ungroup()
## ----data-proc-errorbars------------------------------------------------------
df.error_bar <- df |>
unnest( cols = c(jnd) ) |>
filter( abs(jnd - median) <= jnd_limit ) |>
group_by( vis, rbase, approach, sign ) |>
summarise( jnd = list(jnd) ) |>
mutate(
sd = map_dbl(jnd, ~sd(.x)/sqrt(length(.x))),
mean = map_dbl(jnd, ~mean(.x))
)
## ----fig.height = 8, fig.width = 8--------------------------------------------
df.error_bar |>
ggplot() +
geom_errorbar(aes(x = rbase, ymin = (mean - sd), ymax = mean + sd, color = approach), width = 0.025) +
geom_point( aes(x = rbase, y = mean, color = approach )) +
geom_hline( yintercept = 0.45, linetype = "dashed", alpha = 0.25) +
geom_abline( slope = -1, intercept = 1, linetype = "dashed", alpha = 0.25) +
facet_wrap(vis ~ sign, ncol = 4) +
theme_minimal()
## ----data-proc-regression-1---------------------------------------------------
filter_outliers <- function(x, median, limit) {
return( x[abs(x - median) <= limit] )
}
df.corr <- df |>
# the following visualizations were excluded from the analysis
filter(
!((vis == "donut" | vis == "stackedarea" | vis == "stackedline" | vis == "stackedbar") & (sign == 1)) &
!((vis == "radar" | vis == "line") & (sign == -1))
) |>
mutate( jnd = pmap(list(jnd, median, jnd_limit), filter_outliers) ) |>
mutate(
mean_jnd = map_dbl(jnd, mean),
n = map_dbl(jnd, length)
)
## ----data-proc-regression-2---------------------------------------------------
rbase_adj_coef <- df.corr |>
group_by( vis, sign, rbase ) |>
summarise( jnd = list(jnd), mean_jnd = list(mean_jnd), n = list(n), approach = list(approach) ) |>
mutate( rbase_adj_coef = map2_dbl(mean_jnd, n, ~ sum(.x * .y) / sum(.y)) ) |>
mutate( rbase_adj_coef = map2_dbl(mean_jnd, n, ~ sum(.x * .y) / sum(.y)) ) |>
unnest(cols = c(jnd, mean_jnd, approach) ) |>
magrittr::extract2("rbase_adj_coef")
df.corr_fitted <- df.corr |>
tibble::add_column( rbase_adj_coef = rbase_adj_coef ) |>
mutate(
multiplier = ifelse(approach == "above", 1, -1),
rbase = rbase + 0.5 * multiplier * rbase_adj_coef
) |>
group_by( vis, sign ) |>
summarise( mean_jnd = list(mean_jnd), rbase = list(rbase), .groups = "drop_last" ) |>
mutate(
fit = map2(rbase, mean_jnd, ~as.list(coef(lm(.y ~ .x)))),
sign = factor(ifelse(sign == 1, "positive", "negative"), levels = c("positive", "negative"))
) |>
unnest_wider( col = c(fit) ) |>
rename( intercept = `(Intercept)`, coef = .x ) |>
mutate(
x = 0,
xend = 1,
y = intercept + coef * x,
yend = intercept + coef * xend
)
## ----regression-vis, fig.width = 8, fig.height = 5----------------------------
df.corr_fitted |>
ggplot() +
geom_segment( aes( x=x, y=y, xend=xend, yend=yend, color = vis, linetype = sign) ) +
coord_cartesian( xlim = c(0, 1), ylim = c(0, 0.6) ) +
scale_y_continuous( breaks = seq(0, 1, by = 0.1)) +
scale_x_continuous( breaks = seq(0, 1, by = 0.2)) +
theme_minimal()
## -----------------------------------------------------------------------------
#data_original <- read.csv("master-alt.csv")
n = 20
M = multiverse()
inside(M, {
set.seed(branch(seed, .options = 1:n))
data.i = vis_correlation |>
group_by(rbase, sign, vis, approach) |>
summarise( jnd = list(jnd), .groups = "drop_last" ) |>
mutate(
sample_size = map_dbl(jnd, length ),
bootstrap_samples = map2(jnd, sample_size, ~ sample( .x, size = .y, replace = TRUE))
) |>
select(-jnd) |>
unnest( cols = c(bootstrap_samples)) |>
rename( jnd = bootstrap_samples )
})
## -----------------------------------------------------------------------------
inside(M, {
df.i <- data.i |>
group_by( vis, rbase, approach, sign ) |>
summarise( jnd = list(jnd), .groups = "drop_last" ) |>
mutate(
median = map_dbl(jnd, ~median(.x)),
mads = map_dbl(jnd, ~mad(.x, constant = 1)),
jnd_limit = 3 * mads
) |>
ungroup()
df.error_bar.i <- df.i |>
unnest( cols = c(jnd) ) |>
filter( abs(jnd - median) <= jnd_limit ) |>
group_by( vis, rbase, approach, sign ) |>
summarise( jnd = list(jnd), .groups = "drop_last" ) |>
mutate(
sd = map_dbl(jnd, ~sd(.x)/sqrt(length(.x))),
mean = map_dbl(jnd, ~mean(.x))
)
df.corr.i <- df.i |>
# the following visualizations were excluded from the analysis
filter(
!((vis == "donut" | vis == "stackedarea" | vis == "stackedline" | vis == "stackedbar") & (sign == 1)) &
!((vis == "radar" | vis == "line") & (sign == -1))
) |>
mutate( jnd = pmap(list(jnd, median, jnd_limit), filter_outliers) ) |>
mutate(
mean_jnd = map_dbl(jnd, mean),
n = map_dbl(jnd, length)
)
rbase_adj_coef.i <- df.corr.i |>
group_by( vis, sign, rbase ) |>
summarise(
jnd = list(jnd), mean_jnd = list(mean_jnd), n = list(n), approach = list(approach),
.groups = "drop_last"
) |>
mutate( rbase_adj_coef = map2_dbl(mean_jnd, n, ~ sum(.x * .y) / sum(.y)) ) |>
mutate( rbase_adj_coef = map2_dbl(mean_jnd, n, ~ sum(.x * .y) / sum(.y)) ) |>
unnest(cols = c(jnd, mean_jnd, approach) ) |>
magrittr::extract2("rbase_adj_coef")
df.corr_fitted.i <- df.corr.i |>
tibble::add_column( rbase_adj_coef = rbase_adj_coef ) |>
mutate(
multiplier = ifelse(approach == "above", 1, -1),
rbase = rbase + 0.5 * multiplier * rbase_adj_coef
) |>
group_by( vis, sign ) |>
summarise( mean_jnd = list(mean_jnd), rbase = list(rbase), .groups = "drop_last" ) |>
mutate(
fit = map2(rbase, mean_jnd, ~as.list(coef(lm(.y ~ .x)))),
sign = factor(ifelse(sign == 1, "positive", "negative"), levels = c("positive", "negative"))
) |>
unnest_wider( col = c(fit) ) |>
rename( intercept = `(Intercept)`, coef = .x ) |>
mutate(
x = 0,
xend = 1,
y = intercept + coef * x,
yend = intercept + coef * xend
)
})
## -----------------------------------------------------------------------------
execute_multiverse(M)
## ----vis-errorbars-above, fig.width = 8, fig.height = 5-----------------------
p.above <- expand(M) |>
mutate(data = map(.results, "df.error_bar.i")) |>
unnest( cols = c(data) ) |>
filter( sign == 1 ) |>
ggplot() +
geom_errorbar(aes(x = rbase, ymin = (mean - sd), ymax = mean + sd, color = approach), width = 0.025) +
geom_point( aes(x = rbase, y = mean, color = approach )) +
geom_hline( yintercept = 0.45, linetype = "dashed", alpha = 0.25) +
geom_abline( slope = -1, intercept = 1, linetype = "dashed", alpha = 0.25) +
facet_wrap( ~ vis, nrow = 2) +
theme_minimal() +
transition_manual(.universe)
animate(p.above, nframes = n, fps = 3, width = 840, height = 320, units = "px")
## ----vis-errorbars-below------------------------------------------------------
p.below <- expand(M) |>
mutate(data = map(.results, "df.error_bar.i")) |>
unnest( cols = c(data) ) |>
filter( sign == -1 ) |>
ggplot() +
geom_errorbar(aes(x = rbase, ymin = (mean - sd), ymax = mean + sd, color = approach), width = 0.025) +
geom_point( aes(x = rbase, y = mean, color = approach )) +
geom_hline( yintercept = 0.45, linetype = "dashed", alpha = 0.25) +
geom_abline( slope = -1, intercept = 1, linetype = "dashed", alpha = 0.25) +
facet_wrap( ~ vis, nrow = 2) +
theme_minimal() +
transition_manual(.universe)
animate(p.below, nframes = n, fps = 3, width = 840, height = 320, units = "px")
## ----vis-regression-lines-----------------------------------------------------
p.fitted_lines <- expand(M) |>
mutate(data = map(.results, "df.corr_fitted.i")) |>
unnest( cols = c(data) ) |>
ggplot() +
geom_segment( aes( x=x, y=y, xend=xend, yend=yend, color = vis, linetype = sign) ) +
coord_cartesian( xlim = c(0, 1), ylim = c(0, 0.6) ) +
scale_y_continuous( breaks = seq(0, 1, by = 0.1)) +
scale_x_continuous( breaks = seq(0, 1, by = 0.2)) +
theme_minimal() +
transition_manual(.universe)
animate(p.fitted_lines, nframes = n, fps = 3, width = 840, height = 480, units = "px")
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.