<- function (palette = "black_and_white", base_size = 14, base_family = "sans",
mytheme base_fontface = "plain", base_line_size = base_size/20, base_rect_size = base_size/14,
axis_text_angle = 0, border = FALSE) {
<- function(x) {
is_bool is_logical(x, n = 1) && !is.na(x)
} <- axis_text_angle[1]
angle if (!angle %in% c(0, 45, 90, 270))
stop(sprintf("'axis_text_angle' must be one of [%s]",
paste(c(0, 45, 90, 270), collapse = ", ")), ".\nFor other angles, use the guide_axis() function in ggplot2 instead",
call. = FALSE)
if (!palette %in% names(ggprism::ggprism_data$themes)) {
stop("The palette ", paste(palette), " does not exist.\n See names(ggprism_data$themes) for valid palette names")
}<- tibble::deframe(ggprism::ggprism_data$themes[[palette]])
colours if (!is_bool(border)) {
stop("border must be either: TRUE or FALSE")
}else {
if (border) {
<- element_rect(fill = NA)
panel.border <- element_blank()
axis.line
}else if (!border) {
<- element_blank()
panel.border <- element_line()
axis.line
}
}<- theme(line = element_line(colour = colours["axisColor"],
t size = base_line_size, linetype = 1, lineend = "square"),
rect = element_rect(fill = "white", colour = colours["axisColor"],
size = base_rect_size, linetype = 1), text = element_text(family = base_family,
face = base_fontface, colour = colours["graphTitleColor"],
size = base_size, lineheight = 0.9, hjust = 0.5,
vjust = 0.5, angle = 0, margin = margin(), debug = FALSE),
prism.ticks.length = unit(base_size/50, "pt"), axis.line = axis.line,
axis.line.x = NULL, axis.line.y = NULL, axis.text = element_text(size = rel(0.95),
colour = colours["axisLabelColor"]), axis.text.x = element_text(margin = margin(t = 0.8 *
/4), angle = axis_text_angle, hjust = ifelse(axis_text_angle %in%
base_sizec(45, 90, 270), 1, 0.5), vjust = ifelse(axis_text_angle %in%
c(0, 90, 270), 0.5, 1)), axis.text.x.top = element_text(margin = margin(b = 0.8 *
/4), vjust = 0), axis.text.y = element_text(margin = margin(r = 0.5 *
base_size/4), hjust = 1), axis.text.y.right = element_text(margin = margin(l = 0.5 *
base_size/4), hjust = 0), axis.ticks = element_line(),
base_sizeaxis.ticks.length = unit(3, "points"), axis.ticks.length.x = NULL,
axis.ticks.length.x.top = NULL, axis.ticks.length.x.bottom = NULL,
axis.ticks.length.y = NULL, axis.ticks.length.y.left = NULL,
axis.ticks.length.y.right = NULL, axis.title = element_text(colour = colours["axisTitleColor"]),
axis.title.x = element_text(margin = margin(t = base_size *
0.6), vjust = 1), axis.title.x.top = element_text(margin = margin(b = base_size *
0.6), vjust = 0), axis.title.y = element_text(angle = 90,
margin = margin(r = base_size * 0.6), vjust = 1),
axis.title.y.right = element_text(angle = -90, margin = margin(l = base_size *
0.6), vjust = 0), legend.background = element_blank(),
legend.spacing = unit(base_size, "pt"), legend.spacing.x = NULL,
legend.spacing.y = NULL, legend.margin = margin(base_size/2,
/2, base_size/2, base_size/2), legend.key = element_blank(),
base_sizelegend.key.size = unit(1.2, "lines"), legend.key.height = NULL,
legend.key.width = unit(base_size * 1.8, "pt"), legend.text = element_text(size = rel(0.8),
face = "plain"), legend.text.align = NULL, legend.title = element_blank(),
legend.title.align = NULL, legend.position = "right",
legend.direction = NULL, legend.justification = "center",
legend.box = NULL, legend.box.margin = margin(0, 0, 0,
0, "cm"), legend.box.background = element_blank(),
legend.box.spacing = unit(base_size, "pt"), panel.background = element_rect(fill = ifelse(palette ==
"office", colours["plottingAreaColor"], NA), colour = NA),
panel.border = panel.border, panel.grid = element_blank(),
panel.grid.minor = element_blank(), panel.spacing = unit(base_size/2,
"pt"), panel.spacing.x = NULL, panel.spacing.y = NULL,
panel.ontop = FALSE, strip.background = element_blank(),
strip.text = element_text(colour = colours["axisTitleColor"],
size = rel(0.8), margin = margin(base_size/2.5, base_size/2.5,
/2.5, base_size/2.5)), strip.text.x = element_text(margin = margin(b = base_size/3)),
base_sizestrip.text.y = element_text(angle = -90, margin = margin(l = base_size/3)),
strip.text.y.left = element_text(angle = 90), strip.placement = "inside",
strip.placement.x = NULL, strip.placement.y = NULL, strip.switch.pad.grid = unit(base_size/4,
"pt"), strip.switch.pad.wrap = unit(base_size/4,
"pt"), plot.background = element_rect(fill = colours["pageBackgroundColor"],
colour = NA), plot.title = element_text(size = rel(1.2),
hjust = 0.5, vjust = 1, margin = margin(b = base_size)),
plot.title.position = "panel", plot.subtitle = element_text(hjust = 0.5,
vjust = 1, margin = margin(b = base_size/2)), plot.caption = element_text(size = rel(0.8),
hjust = 1, vjust = 1, margin = margin(t = base_size/2)),
plot.caption.position = "panel", plot.tag = element_text(size = rel(1.2),
hjust = 0.5, vjust = 0.5), plot.tag.position = "topleft",
plot.margin = margin(base_size/2, base_size/2, base_size/2,
/2), complete = TRUE)
base_size::ggprism_data$themes[["all_null"]] %+replace% t
ggprism }
# Load libraries
library(dplyr)
library(purrr)
library(stringr)
library(ggplot2)
library(ggpubr)
library(jcolors)
library(cowplot)
library(ggprism)
library(tidybayes)
library(reshape2)
library(parallel)
library(rstan)
= c("Paper Effect Size", "Paper Effect Size/2", "Paper Effect Size/3",
effect_size "Paper Effect Size/4")
# Functions
<- function(b) exp(c(0, b))/sum(exp(c(0, b)))
psoftmax
<- function(variable, words_to_replace, replace_with = "") {
words_replace
library(dplyr)
if (!require(dplyr)) {
install.packages("dplyr")
library(dplyr)
}
# variable <- enquo(variable) var <- select(data, !!variable) %>% .[,]
if (!is.character(variable))
<- as.character(variable)
variable
for (word_i in 1:length(words_to_replace)) {
<- which(str_detect(variable, fixed(words_to_replace[word_i])))
word_to_rm_index
if (any(word_to_rm_index)) {
<- words_to_replace[word_i]
words_to_replace_i <- sapply(seq_along(word_to_rm_index), function(i) {
new_words <- gsub(words_to_replace_i, replace_with,
variable[word_to_rm_index][i] fixed = TRUE)
variable[word_to_rm_index][i],
})<- new_words
variable[word_to_rm_index] else {
} warning(paste0("Sting '", words_to_replace, "' not found"))
}
}
return(variable)
}
<- function(x) {
seq_vector <- c(which(diff(x) != 0), length(x))
idx <- c(idx[1], diff(idx))
time rep(x = 1:length(idx), times = time)
}
# Load data
<- readRDS("../Pilot/Short Version/Data/data_short.rds")$data %>%
data_short mutate(subject = 1:n()) %>%
rename(age = Age., A3 = A3.)
<- readRDS("../Pilot/Short Version/Data/data_short.rds")$question
questions
# ----- Mental Accounting ----- # Remove final questionnaires
<- data_short[, -(48:75)]
data_short_MA # Remove response time
<- str_detect(names(data_short_MA), "time_")
idx_time <- data_short_MA[, !idx_time]
data_short_MA
<- data_short_MA %>%
data_short_MA rename_with(~gsub(".", "", .x, fixed = TRUE)) %>%
rename_with(toupper, .cols = -contains("subject"))
<- nrow(data_short_MA) n_sbj
To test the replicability of the effects reported in the original papers we will run Bayesian modeling. We analyze the pilot data (short version) following the same procedure that we will follow to analyze the experimental data.
We analyze the data from the first study (“MrAB” scenarios) using a Bayesian binomial mixture regression model. We fit this model first to estimate the probability of choosing option A or B for each scenario and second, to estimate the conditional probability of choosing option A for each scenario.
# ---------- Mr. A vs Mr. B2 Scenario ---------- #
# Coding legend: response: 0 (Happier/More upset); 1 (Less Happy/Less upset) 2
# (No difference)
# Create dataframe scenario 1
<- data_short %>%
data_s1 select(subject, contains("A", ignore.case = FALSE)) %>%
# Recode response
mutate(`gain-gain VS gain` = case_when(A1 == "A" ~ 0, A1 == "B" ~ 1, T ~ 2), `loss-loss VS loss` = case_when(A2 ==
"A" ~ 0, A2 == "B" ~ 1, T ~ 2), `gain-loss VS gain` = case_when(A3 == "A" ~ 0,
== "B" ~ 1, T ~ 2), `loss-gain VS loss` = case_when(A4 == "A" ~ 0, A4 == "B" ~
A3 1, T ~ 2)) %>%
select(-contains("A", ignore.case = FALSE)) %>%
melt(id.var = "subject", variable.name = "scenario", value.name = "response") %>%
mutate(scenario_group = ifelse(scenario == "gain-gain VS gain" | scenario ==
"gain-loss VS gain", "gain", "loss"))
%>%
data_s1 ggplot(aes(response)) + geom_bar(aes(y = (..count..)/sum(..count..)), fill = jcolors::jcolors(palette = "pal6")[1]) +
mytheme() + theme(legend.position = "none", axis.title.y = element_blank(), axis.text.y = element_blank()) +
scale_fill_brewer(palette = "Set1") + scale_y_continuous(labels = scales::percent,
guide = "prism_offset") + scale_x_continuous(guide = "prism_offset", breaks = 0:2,
labels = c("A", "B", "Same")) + labs(y = NULL, x = NULL) + facet_wrap(~scenario)
Gain-Gain VS Gain
Mr. A was given two tickets to the
Regional lottery. He won $50 in one lottery and $25 in the other.
Mr. B was given a ticket to a single, larger Regional lottery.
He won $75.
Who is happier?
A/B/No difference
Loss-Loss VS Loss
Mr. A received a letter from the IRS
saying that he made a minor arithmetical mistake on his tax return and
owed $100. He received a similar letter the same day from his state
income tax authority saying he owed $50. There were no other
repercussions from either mistake.
Mr. B received a letter from
the IRS saying he made a minor arithmetical mistake on his tax return
and owed $150. There were no other repercussions from this mistake.
Who more upset?
A/B/No difference
Gain-Loss VS Gain
Mr. A bought his first National
lottery ticket and won $100. Also, in a freak accident, he damaged the
rug in his apartment and had to pay the landlord $80.
Mr. B
bought his first National lottery ticket and won $20.
Who is
happier?
A/B/No difference
Loss-Gain VS Loss
Mr. A’s car was damaged in a parking
lot. He had to spend $200 to repair the damage. The same day the car was
damaged, he won $25 in the office holiday raffle.
Mr. B’s car
was damaged in a parking lot. He had to spend $175 to repair the
damage.
Who is more upset?
A/B/No difference
functions {
/*
* Args:
* y: response value 0: A, 1: B, 2: No difference
* ds: different (0|1) - same (2) probability
* cA: conditional (different) A probability
* Returns:
* a scalar to be added to the log posterior
*/
real mental_accounting_lpdf(real y, real ds, real cA) {
if (y == 0) { // Stay (Explore)
return bernoulli_lpmf(1 | ds) + bernoulli_lpmf(1 | cA);
else if (y == 1) { // Switch (Explore)
} return bernoulli_lpmf(1 | ds) + bernoulli_lpmf(0 | cA);
else { // Select
} return bernoulli_lpmf(0 | ds);
}
}
}
data {
int<lower=1> N; // total number of observations
vector[N] Y; // response variable
int<lower=1> K_ds; // number of population-level effects
matrix[N, K_ds] X_ds; // population-level design matrix
int<lower=1> K_cA; // number of population-level effects
matrix[N, K_cA] X_cA; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}parameters {
vector[K_ds] b_ds; // population-level effects
vector[K_cA] b_cA; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
// initialize different - same linear predictor term
vector[N] ds = X_ds * b_ds;
// initialize linear predictor term
vector[N] cA = X_cA * b_cA;
for (n in 1:N) {
// apply the inverse link function
ds[n] = inv_logit(ds[n]);
}for (n in 1:N) {
// apply the inverse link function
cA[n] = inv_logit(cA[n]);
}for (n in 1:N) {
target += mental_accounting_lpdf(Y[n] | ds[n], cA[n]);
}
}// priors including constants
target += normal_lpdf(b_ds | 0, 5);
target += normal_lpdf(b_cA | 0, 5);
}
functions {
/*
* Args:
* y: response value 0: A, 1: B, 2: No difference
* ds: different (0|1) - same (2) probability
* cA: conditional (different) A probability
* Returns:
* a scalar to be added to the log posterior
*/
real mental_accounting_lpdf(real y, real ds, real cA) {
if (y == 0) { // Stay (Explore)
return bernoulli_lpmf(1 | ds) + bernoulli_lpmf(1 | cA);
} else if (y == 1) { // Switch (Explore)
return bernoulli_lpmf(1 | ds) + bernoulli_lpmf(0 | cA);
} else { // Select
return bernoulli_lpmf(0 | ds);
}
}
}
data {
int<lower=1> N; // total number of observations
vector[N] Y; // response variable
int<lower=1> K_ds; // number of population-level effects
matrix[N, K_ds] X_ds; // population-level design matrix
int<lower=1> K_cA; // number of population-level effects
matrix[N, K_cA] X_cA; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K_ds] b_ds; // population-level effects
vector[K_cA] b_cA; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
// initialize different - same linear predictor term
vector[N] ds = X_ds * b_ds;
// initialize linear predictor term
vector[N] cA = X_cA * b_cA;
for (n in 1:N) {
// apply the inverse link function
ds[n] = inv_logit(ds[n]);
}
for (n in 1:N) {
// apply the inverse link function
cA[n] = inv_logit(cA[n]);
}
for (n in 1:N) {
target += mental_accounting_lpdf(Y[n] | ds[n], cA[n]);
}
}
// priors including constants
target += normal_lpdf(b_ds | 0, 5);
target += normal_lpdf(b_cA | 0, 5);
}
# ---- Fit Model ---- #
library(rstan)
library(tidybayes)
options(mc.cores = 4)
rstan_options(auto_write = TRUE)
# ------------- ~ scenario ------------- #
# Create Stan Data
<- model.matrix(~ 0 + scenario, data_s1 %>% filter)
X
#Stan Data
<- list(
stan_data N = nrow(data_s1),
Y = data_s1$response,
X_ds = X,
X_cA = X,
K_ds = ncol(X),
K_cA = ncol(X),
N_sbj = n_sbj,
J_sbj = data_s1$subject,
prior_only = 0
)
# Fit the model
<- rstan::sampling(mixture_scenario_1,
fit_S1 iter = 2000,
cores = 4,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
<- extract(fit_S1)
draws colnames(draws$b_ds) <- words_replace(colnames(X), "scenario")
colnames(draws$b_cA) <- words_replace(colnames(X), "scenario")
<- as.data.frame(draws$b_cA)
df
rbind(data.frame(post = with(df, `gain-gain VS gain` - `gain-loss VS gain`), effect = "gain-gain VS gain\n-\ngain-loss VS gain"),
data.frame(post = with(df, `loss-loss VS loss` - `loss-gain VS loss`), effect = "loss-loss VS loss\n-\nloss-gain VS loss")) %>%
ggplot(aes(x = post, y = effect)) + stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) + mytheme() + theme(axis.text.y = NULL) +
geom_vline(xintercept = 0, linetype = 2) + labs(y = NULL, x = "Posterior Probability")
To analyze the data from the second study (“Game” scenarios) we use a Bayesian multinomial regression model in order to estimate the probability of choosing each of the four options for each scenario.
# --------- Coding legend: --------- #
# -- Dependent Variable -- #
# response: 0
# 5
# 10
# Other
# -- Explanatory Variables -- #
# cost: 0, 5, 10 (defined as p in Thaler 1985)
# [cost influence the "fair price" (p_star), which is operationalized
# with the price asked to a friend]
# market_value : 5, 10
# buyer: friend (proxy for a fair price), stranger
# Create dataframe scenario 2
<- data_short_MA %>%
df select(contains('B', ignore.case = F))
<- names(df)
col_names <- rep(c(0, 5, 10), each=2)
cost <- rep(c(5, 10), 3)
market_value <- seq(1,ncol(df),2)
col_idx <- map_df(seq_along(col_idx), function(i){
df1
data.frame( response = c(df[,col_names[col_idx[i]]], df[,col_names[col_idx[i]+1]]),
cost = cost[i],
market_value = market_value[i],
buyer = c(rep('Friend', n_sbj), rep('Stranger', n_sbj)) )
})
<- df1 %>%
data_s2 mutate(response=ifelse(response%in%unique(cost), response, 'Other'),
response = factor(response, levels = c('0', '5', '10', 'Other')))
%>%
data_s2group_by(cost, market_value, buyer) %>%
count(response, .drop = F) %>%
ggplot(aes(response, n, fill=buyer)) +
geom_bar(stat="identity", position=position_dodge(), color="black") +
mytheme() +
scale_fill_jcolors(palette = 'pal6') +
labs(y=NULL, x=NULL) +
facet_grid(cost~market_value)
<- df1 %>%
data_s2 mutate(response = ifelse(response >= market_value, 1, 0))
%>%
data_s2 group_by(buyer) %>%
summarise(m = mean(response)) %>%
ggplot(aes(buyer, m, fill = buyer)) + geom_bar(stat = "identity", position = position_dodge(),
color = "black") + scale_fill_jcolors(palette = "pal6") + labs(y = "P(Price ≥ Market Value)",
x = "Buyer") + mytheme() + theme(legend.position = "none") + scale_y_continuous(limits = 0:1)
You are going to a sold-out game of your favorite local sport-team, and
you have an extra ticket. The price marked on the ticket is $5 but [you
were given your tickets for free by a friend / which is what you paid
for each ticket / but you paid $10 for each ticket when you bought them
from another student].
You want to get rid of the extra ticket
and you know the going price is $5. You find someone who wants the
ticket. There is no law against charging more than the price marked on
the ticket.
What price do you ask for if…
a) He is a friend
b) He is a
stranger
What would you have said if you found out that the going market price
was $10 instead?
a) He is a friend
b) He is a stranger
<- rstan::stan_model("bernoulli_scenario_4.stan") bernoulli_scenario_2
data {
int<lower=1> N; // total number of observations
int Y[N]; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
vector[N] mu = X * b;
target += bernoulli_logit_lpmf(Y | mu);
}
// priors including constants
target += normal_lpdf(b | 0, 5);
}
# Create Stan Data
<- model.matrix(~ buyer, data_s2)
X
#Stan Data
<- list(
stan_data N = nrow(data_s2),
Y = data_s2$response,
K = ncol(X),
X = X,
prior_only = 0
)
# Fit the model
<- rstan::sampling(bernoulli_scenario_2,
fit_S2 iter = 2000,
cores = 4,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
extract(fit_S2)$b %>%
melt(value.name = "post") %>%
mutate(Var2 = ifelse(Var2 == 1, "Intercept", "")) %>%
filter(Var2 != "Intercept") %>%
ggplot(aes(x = post, y = Var2)) + stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) + mytheme() + geom_vline(xintercept = 0,
linetype = 2) + labs(y = NULL, x = "Posterior Probability", title = "Stranger - Friend")
To analyze the data from the third study (“Drink” scenarios) we fit a Bayesian gamma regression model. We estimate the mean offer difference between the “fancy resort hotel” and the “rundown grocery store” scenario.
# --------- Coding legend: --------- # -- Dependent Variable -- # response --
# Explanatory Variables -- # store: Resort hotel vs Grocery store
# Create dataframe scenario 3
<- data_short_MA %>%
data_s3 select(subject, contains("C", ignore.case = FALSE)) %>%
melt(id.var = "subject", variable.name = "store", value.name = "response") %>%
mutate(store = ifelse(store == "C1_1", "Resort Hotel", "Grocery Store"), response = as.numeric(response))
%>%
data_s3 ggplot(aes(response, fill = store, color = store)) + geom_density(alpha = 0.4,
adjust = 1.5, size = 2) + mytheme() + theme(legend.position = c(0.7, 0.8)) +
scale_fill_jcolors(palette = "pal6") + scale_color_jcolors(palette = "pal6") +
# scale_y_continuous(labels=scales::percent, guide = 'prism_offset') +
scale_x_continuous(breaks = seq(0, 40, 10), limits = c(0, 40)) + labs(y = NULL, x = NULL)
You are on the beach on a hot day, and you would really like a cold bottle of beer. A friend offers to go buy the beer from [a fancy resort hotel / a small, run-down grocery store]. They ask how much you are willing to pay for the beer: they will only buy it if it costs as much or less than the price you state. You trust your friend, and there is no possibility of bargaining with the bartender.
What price do you tell them?
data {
int<lower=1> N; // total number of observations
vector[N] Y; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
real<lower=0> shape; // shape parameter
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
// initialize linear predictor term
vector[N] mu = X * b;
for (n in 1:N) {
// apply the inverse link function
mu[n] = shape * exp(-(mu[n]));
}target += gamma_lpdf(Y | shape, mu);
}// priors including constants
target += normal_lpdf(b | 0, 5);
target += gamma_lpdf(shape | 0.01, 0.01);
}
data {
int<lower=1> N; // total number of observations
vector[N] Y; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
real<lower=0> shape; // shape parameter
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
// initialize linear predictor term
vector[N] mu = X * b;
for (n in 1:N) {
// apply the inverse link function
mu[n] = shape * exp(-(mu[n]));
}
target += gamma_lpdf(Y | shape, mu);
}
// priors including constants
target += normal_lpdf(b | 0, 5);
target += gamma_lpdf(shape | 0.01, 0.01);
}
# Create Stan Data
<- model.matrix(~ store, data_s3)
X
#Stan Data
<- list(
stan_data N = nrow(data_s3),
Y = data_s3$response,
X = X,
K = ncol(X),
N_sbj = n_sbj,
J_sbj = data_s3$subject,
prior_only = 0
)
# Fit the model
<- rstan::sampling(gamma_scenario_3,
fit_S3 iter = 2000,
cores = 4,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
<- extract(fit_S3)
draws
$b %>%
drawsmelt(value.name = "post") %>%
mutate(Var2 = ifelse(Var2 == 1, "Intercept", "")) %>%
filter(Var2 != "Intercept") %>%
ggplot(aes(x = post, y = Var2)) + stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) + mytheme() + geom_vline(xintercept = 0,
linetype = 2) + labs(y = NULL, x = "Posterior Probability", title = "Resort Hotel - Grocery Store")
We will analyze the data from the Jacket-Calculator study using a Bayesian binomial regression model in order to estimate the probability to respond ‘Yes’ in the two scenarios.
# --------- Coding legend: --------- #
# -- Dependent Variable -- #
# response
# -- Explanatory Variables -- #
# store: Resort hotel vs Grocery store
# Create dataframe scenario 3
<- data_short_MA %>%
data_s4 select(subject, contains('D', ignore.case = FALSE)) %>%
rename(low_price2 = D3, low_price1 = D2_1,
high_price2 = D4, high_price1 = D2_2) %>%
melt(id.var='subject',
variable.name='price',
value.name='response') %>%
mutate(price=ifelse(str_detect(price, 'low'), 'low', 'high'),
response=ifelse(response=='No', 0, 1))
%>%
data_s4 filter(response==1) %>%
group_by(price) %>%
count(response, .drop = F) %>%
ungroup() %>%
ggplot(aes(price, n, fill=price)) +
geom_bar(stat = "identity",
# aes(y = (..count..)/sum(..count..)),
position = position_dodge()) +
mytheme() + theme(legend.position = 'none') +
scale_fill_jcolors(palette = 'pal6') +
scale_color_jcolors(palette = 'pal6') +
# scale_y_continuous(labels=scales::percent, guide = "prism_offset") +
labs(y='Number of "Yes"', x='Price')
You are about to purchase a jacket for [$125 / $15] and a Bluetooth speaker for [$15 / $125]. The salesman informs you that the speaker you wish to buy is on sale for [$10 / $120] at the other branch store, located 20 minutes away.
Would you make the trip to the other store? a) Yes a) No
Imagine that you are about to purchase a jacket for [$125 / $15] and a calculator for [$15 / $125]. The salesman informs you that the calculator you wish to buy is on sale for [$10 / $120] at the other branch store, located 20 minutes away.
Would you make the trip to the other store? a) Yes a) No
<- rstan::stan_model("bernoulli_scenario_4.stan") bernoulli_scenario_4
Running /Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB foo.c
clang -mmacosx-version-min=10.13 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/Rcpp/include/" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/unsupported" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/BH/include" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/StanHeaders/include/src/" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/StanHeaders/include/" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppParallel/include/" -I"/Library/Frameworks/R.framework/Versions/4.1/Resources/library/rstan/include" -DEIGEN_NO_DEBUG -DBOOST_DISABLE_ASSERTS -DBOOST_PENDING_INTEGER_LOG2_HPP -DSTAN_THREADS -DBOOST_NO_AUTO_PTR -include '/Library/Frameworks/R.framework/Versions/4.1/Resources/library/StanHeaders/include/stan/math/prim/mat/fun/Eigen.hpp' -D_REENTRANT -DRCPP_PARALLEL_USE_TBB=1 -I/usr/local/include -fPIC -Wall -g -O2 -c foo.c -o foo.o
In file included from <built-in>:1:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/StanHeaders/include/stan/math/prim/mat/fun/Eigen.hpp:13:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/Eigen/Dense:1:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/Eigen/Core:88:
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/Eigen/src/Core/util/Macros.h:628:1: error: unknown type name 'namespace'
namespace Eigen {
^
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/Eigen/src/Core/util/Macros.h:628:16: error: expected ';' after top level declarator
namespace Eigen {
^
;
In file included from <built-in>:1:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/StanHeaders/include/stan/math/prim/mat/fun/Eigen.hpp:13:
In file included from /Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/Eigen/Dense:1:
/Library/Frameworks/R.framework/Versions/4.1/Resources/library/RcppEigen/include/Eigen/Core:96:10: fatal error: 'complex' file not found
#include <complex>
^~~~~~~~~
3 errors generated.
make: *** [foo.o] Error 1
data {
int<lower=1> N; // total number of observations
int Y[N]; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
vector[N] mu = X * b;
target += bernoulli_logit_lpmf(Y | mu);
}
// priors including constants
target += normal_lpdf(b | 0, 5);
}
# Create Stan Data
<- model.matrix(~ price, data_s4)
X
#Stan Data
<- list(
stan_data N = nrow(data_s4),
Y = data_s4$response,
X = X,
K = ncol(X),
N_sbj = n_sbj,
J_sbj = data_s4$subject,
prior_only = 0
)
# Fit the model
<- rstan::sampling(bernoulli_scenario_4,
fit_S4 iter = 2000,
cores = 4,
save_warmup = FALSE,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
extract(fit_S4)$b %>%
melt(value.name = "post") %>%
mutate(Var2 = ifelse(Var2 == 1, "Intercept", "")) %>%
filter(Var2 != "Intercept") %>%
ggplot(aes(x = post, y = Var2)) + stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) + mytheme() + geom_vline(xintercept = 0,
linetype = 2) + labs(y = NULL, x = "Posterior Probability", title = "Low - High")
We analyze the data from the Lost Ticket study using a Bayesian binomial regression model in order to estimate the probability to respond ‘Yes’ in the two scenarios.
# --------- Coding legend: --------- #
# -- Dependent Variable -- #
# response
# -- Explanatory Variables -- #
# loss: ticket vs cash
# Create dataframe scenario 3
<- data_short_MA %>%
data_s5 select(subject, contains('E', ignore.case = FALSE)) %>%
rename(ticket = E1,
cash = E2) %>%
melt(id.var='subject',
variable.name='loss',
value.name='response') %>%
mutate(response=ifelse(response=='No', 0, 1))
%>%
data_s5 filter(response==1) %>%
group_by(loss) %>%
count(response, .drop = F) %>%
ungroup() %>%
ggplot(aes(loss, n, fill=loss)) +
geom_bar(stat = "identity",
# aes(y = (..count..)/sum(..count..)),
position = position_dodge()) +
mytheme() + theme(legend.position = 'none') +
scale_fill_jcolors(palette = 'pal6') +
scale_color_jcolors(palette = 'pal6') +
# scale_y_continuous(labels=scales::percent, guide = "prism_offset") +
labs(y='Number of "Yes"', x='Loss')
Imagine you are on your way to a play with [a pair of tickets for which you have paid $40 / the intention of buying two tickets worth $40 in total]. On entering the theater, you discover that [you have lost the tickets / you have lost $40 in cash].
Would you pay $40 for another pair of tickets? a) Yes b) No
data {
int<lower=1> N; // total number of observations
int Y[N]; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
vector[N] mu = X * b;
target += bernoulli_logit_lpmf(Y | mu);
}
// priors including constants
target += normal_lpdf(b | 0, 5);
}
# Create Stan Data
<- model.matrix(~ loss, data_s5)
X
#Stan Data
<- list(
stan_data N = nrow(data_s5),
Y = data_s5$response,
X = X,
K = ncol(X),
N_sbj = n_sbj,
J_sbj = data_s3$subject,
prior_only = 0
)
# Fit the model
<- rstan::sampling(bernoulli_scenario_4,
fit_S5 iter = 2000,
cores = 4,
save_warmup = FALSE,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
extract(fit_S5)$b %>%
melt(value.name = 'post') %>%
mutate(Var2=ifelse(Var2==1, 'Intercept', '')) %>%
filter(Var2!='Intercept') %>%
ggplot(aes(x = post, y = Var2)) +
stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) +
mytheme() + geom_vline(xintercept = 0, linetype = 2) +
labs(y = NULL, x = "Posterior Probability", title='Ticket - Cash')
We analyze the data from the Membership Gym study using a Bayesian binomial regression model in order to estimate the probability to respond ‘Wasted $20’ in the two scenarios.
= c("I feel like I wasted $20", "I feel like I wasted something but no specific amount or measure comes to mind",
answers "I feel like I wasted nothing, since my visit had already been paid for")
# Create dataframe scenario 3
<- data_short_MA %>%
data_s6 select(subject, contains("F", ignore.case = FALSE)) %>%
mutate(F1 = case_when(F1 == answers[1] ~ 1, F1 == answers[2] ~ 0, F1 == answers[3] ~
0), F2 = case_when(F2 == answers[1] ~ 1, F2 == answers[2] ~ 0, F2 == answers[3] ~
0)) %>%
rename(`Per-session` = F1, Yearly = F2) %>%
melt(id.var = "subject", variable.name = "frame", value.name = "response")
%>%
data_s6 filter(response == 1) %>%
group_by(frame) %>%
count(response, .drop = F) %>%
ungroup() %>%
ggplot(aes(frame, n, fill = frame)) + geom_bar(stat = "identity", position = position_dodge()) +
mytheme() + theme(legend.position = "none") + scale_fill_jcolors(palette = "pal6") +
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + scale_color_jcolors(palette
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + =
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + "pal6")
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + +
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + #
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + scale_y_continuous(labels=scales::percent,
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + guide
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + =
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + 'prism_offset')
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + +
labs(y = "Number of \"Wasted $20\"", x = "Frame")
You have a gym membership in a nearby town that you travel to on a regular basis. You go to this gym every single Monday night. The membership allows you to pay [$20 (non-refundable) per session / $1000 a year (i.e., roughly $20 per visit)]. One Monday, just after you have arrived and changed into your gym clothes, you receive a phone call that requires you to leave and forego your exercise that evening.
Which of the following statements better captures your feelings about the cost of the missed workout? a) I feel like I wasted $20 b) I feel like I wasted nothing, since my visit had already been paid for c) I feel like I wasted something, but no specific amount or measure comes to mind
<- rstan::stan_model("bernoulli_scenario_6.stan") bernoulli_scenario_6
data {
int<lower=1> N; // total number of observations
int Y[N]; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
vector[N] mu = X * b;
target += bernoulli_logit_lpmf(Y | mu);
}
// priors including constants
target += normal_lpdf(b | 0, 5);
}
# Create Stan Data
<- model.matrix(~ frame, data_s6 %>% mutate(frame=ifelse(frame=='Per-session', 1, 0 )))
X
#Stan Data
<- list(
stan_data N = nrow(data_s6),
Y = data_s6$response,
X = X,
K = ncol(X),
N_sbj = n_sbj,
J_sbj = data_s6$subject,
prior_only = 0
)
# Fit the model
<- rstan::sampling(bernoulli_scenario_6,
fit_S6 iter = 2000,
cores = 4,
pars = c('b'),
save_warmup = FALSE,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
extract(fit_S6)$b %>%
as.data.frame() %>%
mutate(post = V2, type = "") %>%
ggplot(aes(x = post, y = type)) + stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) + mytheme() + geom_vline(xintercept = 0,
linetype = 2) + labs(y = NULL, x = "Posterior Probability", title = "Per-session - Yearly")
We analyze the data from the Membership Airplanes Coupons using a Bayesian binomial regression model in order to estimate the probability to respond ‘Pay your friend $35 for the coupon’ in the two scenarios.
# --------- Coding legend: --------- # -- Dependent Variable -- # response --
# Explanatory Variables -- # coupon: purchased vs free
= c("Pay your friend $35 for the coupon.", "Pay some, but not the full amount for the coupon (for example, half the price).",
answers "Consider it a gift and not pay for the coupon.")
# Create dataframe scenario 3
<- data_short_MA %>%
data_s7 select(subject, contains("G", ignore.case = FALSE)) %>%
mutate(G1 = case_when(G1 == answers[1] ~ 1, G1 == answers[2] ~ 0, G1 == answers[3] ~
0), G2 = case_when(G2 == answers[1] ~ 1, G2 == answers[2] ~ 0, G2 == answers[3] ~
0)) %>%
rename(purchased = G1, free = G2) %>%
melt(id.var = "subject", variable.name = "coupon", value.name = "response")
%>%
data_s7 filter(response == 1) %>%
group_by(coupon) %>%
count(response, .drop = F) %>%
ungroup() %>%
ggplot(aes(coupon, n, fill = coupon)) + geom_bar(stat = "identity", position = position_dodge()) +
mytheme() + theme(legend.position = "none") + scale_fill_jcolors(palette = "pal6") +
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + scale_color_jcolors(palette
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + =
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + "pal6")
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + +
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + #
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + scale_y_continuous(labels=scales::percent,
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + guide
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + =
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + 'prism_offset')
scale_color_jcolors(palette = "pal6") + # scale_y_continuous(labels=scales::percent, guide = 'prism_offset') + +
labs(y = "Pay your friend $35 for the coupon", x = "")
You are flying with a friend who has upgraded their ticket to business class and has two coupons, each worth $35, which can be used to upgrade your ticket/seat from economy to business class. They purchased one coupon for the standard price of $35 and received the other one for free. Just one coupon is required to upgrade your class on the current flight, and your friend offers you the coupon [which he purchased / which he got for free] so that you can upgrade as well.
What do you think is the most appropriate thing to do? a) Pay your friend $35 for the coupon. b) Consider it a gift and not pay for the coupon. c) Pay some, but not the full amount for the coupon (for example, half the price).
data {
int<lower=1> N; // total number of observations
int Y[N]; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // population-level design matrix
int prior_only; // should the likelihood be ignored?
}
parameters {
vector[K] b; // population-level effects
}
transformed parameters {
}
model {
// likelihood including constants
if (!prior_only) {
vector[N] mu = X * b;
target += bernoulli_logit_lpmf(Y | mu);
}
// priors including constants
target += normal_lpdf(b | 0, 5);
}
# Create Stan Data
<- model.matrix(~ coupon, data_s7)
X
#Stan Data
<- list(
stan_data N = nrow(data_s7),
Y = data_s7$response,
X = X,
K = ncol(X),
N_sbj = n_sbj,
J_sbj = data_s7$subject,
prior_only = 0
)
# Fit the model
<- rstan::sampling(bernoulli_scenario_6,
fit_S7 iter = 2000,
cores = 4,
pars = c('b'),
save_warmup = FALSE,
data = stan_data,
save_warmup = FALSE)
Plot Model Posteriors
extract(fit_S7)$b %>%
as.data.frame() %>%
mutate(post = V2, type = "") %>%
ggplot(aes(x = post, y = type)) + stat_halfeye(fill = jcolors::jcolors(palette = "pal8")[6],
color = jcolors::jcolors(palette = "pal8")[12]) + mytheme() + geom_vline(xintercept = 0,
linetype = 2) + labs(y = NULL, x = "Posterior Probability", title = "Per-session - Yearly")