Nothing
## ----setup, include=FALSE-----------------------------------------------------
knitr::opts_chunk$set(
message = FALSE,
warning = FALSE,
include = TRUE,
collapse = TRUE,
comment = "#>",
dev = "png",
dpi = 144,
fig.width = 7,
fig.height = 5
)
library(beezdemand)
library(dplyr)
library(purrr)
library(tidyr)
library(ggplot2)
# Load package datasets
data("etm", package = "beezdemand")
data("lowNicClean", package = "beezdemand")
data("cannabisCigarettes", package = "beezdemand")
data("ongoingETM", package = "beezdemand")
lnic <- lowNicClean |>
mutate(
target = if_else(commodity == "cigarettesAdj", "adjusting", "fixed"),
group = "cigarettes"
) |>
select(
-commodity
) |>
relocate(condition, .after = group)
can_cig <- cannabisCigarettes |>
select(
id,
x,
y,
target = commodity
)
ongoing_etm <- ongoingETM |>
pivot_longer(
-c(id, x, flavor),
names_to = "target",
values_to = "y",
values_drop_na = TRUE
) |>
select(id, x, y, target)
## -----------------------------------------------------------------------------
glimpse(etm)
## ----load-cp------------------------------------------------------------------
# Load the cross-price example dataset
data("cp", package = "beezdemand")
# Examine structure
glimpse(cp)
# View conditions
table(cp$target)
## ----fit-alone----------------------------------------------------------------
# Filter to alone condition
alone_data <- cp |>
dplyr::filter(target == "alone")
# Fit demand curve (modern interface)
fit_alone <- fit_demand_fixed(
data = alone_data,
equation = "koff",
k = 2
)
# View results
fit_alone
## ----fit-own------------------------------------------------------------------
# Filter to own condition
own_data <- cp |>
dplyr::filter(target == "own")
# Fit demand curve
fit_own <- fit_demand_fixed(
data = own_data,
equation = "koff",
k = 2
)
# View results
fit_own
## ----fit-alt-cp---------------------------------------------------------------
# Filter to alt condition
alt_data <- cp |>
dplyr::filter(target == "alt")
# Fit cross-price model
fit_alt <- fit_cp_nls(
data = alt_data,
equation = "exponentiated",
return_all = TRUE
)
# View results
summary(fit_alt)
## ----compare-conditions-------------------------------------------------------
# Extract key parameters for each condition
coef_alone <- coef(fit_alone)
Q0_alone <- coef_alone$estimate[coef_alone$term == "q0"]
Alpha_alone <- coef_alone$estimate[coef_alone$term == "alpha"]
coef_own <- coef(fit_own)
Q0_own <- coef_own$estimate[coef_own$term == "q0"]
Alpha_own <- coef_own$estimate[coef_own$term == "alpha"]
comparison <- data.frame(
Condition = c("Alone (Target)", "Own (Target)", "Alt (Cross-Price)"),
Q0_or_Qalone = c(
Q0_alone,
Q0_own,
coef(fit_alt)["qalone"]
),
Alpha_or_I = c(
Alpha_alone,
Alpha_own,
coef(fit_alt)["I"]
)
)
comparison
## ----combined-plot, fig.width=8, fig.height=4---------------------------------
# Create prediction data
x_seq <- seq(0.01, max(cp$x), length.out = 100)
# Get demand predictions for each condition
pred_alone <- predict(fit_alone, newdata = data.frame(x = x_seq))$.fitted
pred_own <- predict(fit_own, newdata = data.frame(x = x_seq))$.fitted
# Cross-price model predictions (always on the natural y scale)
pred_alt <- predict(fit_alt, newdata = data.frame(x = x_seq))$y_pred
# Combine into plot data
plot_data <- data.frame(
x = rep(x_seq, 3),
y = c(pred_alone, pred_own, pred_alt),
Condition = rep(c("Target (Alone)", "Target (Own)", "Alternative (Cross-Price)"), each = length(x_seq))
)
# Plot
ggplot() +
geom_point(data = cp, aes(x = x, y = y, color = target), alpha = 0.6) +
geom_line(data = plot_data, aes(x = x, y = y, color = Condition), linewidth = 1) +
scale_x_log10() +
scale_y_log10() +
labs(
x = "Target Price",
y = "Consumption",
title = "Cross-Price Analysis: All Conditions",
color = "Condition"
) +
theme_bw()
## -----------------------------------------------------------------------------
etm |>
dplyr::filter(group %in% "E-Cigarettes" & id %in% 1)
unsys_one <- etm |>
filter(group %in% "E-Cigarettes" & id %in% 1) |>
check_systematic_cp()
unsys_one$results
unsys_one_lnic <- lnic |>
filter(
target == "adjusting",
id == "R_00Q12ahGPKuESBT"
) |>
check_systematic_cp()
unsys_one_lnic$results
## ----compute-unsys-etm, results='hide'----------------------------------------
unsys_all <- etm |>
group_by(id, group) |>
nest() |>
mutate(
sys = map(data, check_systematic_cp),
results = map(sys, ~ dplyr::select(.x$results, -id))
) |>
select(-data, -sys) |>
unnest(results)
## ----show-unsys-etm-----------------------------------------------------------
knitr::kable(
unsys_all |>
group_by(group) |>
summarise(
n_subjects = n(),
pct_systematic = round(mean(systematic, na.rm = TRUE) * 100, 1),
.groups = "drop"
),
caption = "Systematicity check by product group (ETM dataset)"
)
## ----compute-unsys-lnic, results='hide'---------------------------------------
unsys_all_lnic <- lnic |>
filter(target == "fixed") |>
group_by(id, condition) |>
nest() |>
mutate(
sys = map(
data,
check_systematic_cp
)
) |>
mutate(results = map(sys, ~ dplyr::select(.x$results, -id))) |>
select(-data, -sys) |>
unnest(results) |>
arrange(id)
## ----show-unsys-lnic----------------------------------------------------------
knitr::kable(
unsys_all_lnic |>
group_by(condition) |>
summarise(
n_subjects = n(),
pct_systematic = round(mean(systematic, na.rm = TRUE) * 100, 1),
.groups = "drop"
),
caption = "Systematicity check by condition (Low Nicotine study, Kaplan et al., 2018)"
)
## ----compute-unsys-can-cig, results='hide'------------------------------------
unsys_all_can_cig <- can_cig |>
filter(target %in% c("cannabisFix", "cigarettesFix")) |>
group_by(id, target) |>
nest() |>
mutate(
sys = map(data, check_systematic_cp),
results = map(sys, ~ dplyr::select(.x$results, -id))
) |>
select(-data, -sys) |>
unnest(results) |>
arrange(id)
## ----show-unsys-can-cig-------------------------------------------------------
knitr::kable(
unsys_all_can_cig |>
group_by(target) |>
summarise(
n_subjects = n(),
pct_systematic = round(mean(systematic, na.rm = TRUE) * 100, 1),
.groups = "drop"
),
caption = "Systematicity check by target (Cannabis/Cigarettes, unpublished data)"
)
## ----compute-unsys-ongoing-etm, results='hide'--------------------------------
unsys_all_ongoing_etm <- ongoing_etm |>
# one person is doubled up
distinct() |>
filter(target %in% c("FixCig", "ECig")) |>
group_by(id, target) |>
nest() |>
mutate(
sys = map(data, check_systematic_cp),
results = map(sys, ~ dplyr::select(.x$results, -id))
) |>
select(-data, -sys) |>
unnest(results)
## ----show-unsys-ongoing-etm---------------------------------------------------
knitr::kable(
unsys_all_ongoing_etm |>
group_by(target) |>
summarise(
n_subjects = n(),
pct_systematic = round(mean(systematic, na.rm = TRUE) * 100, 1),
.groups = "drop"
),
caption = "Systematicity check by target (Ongoing ETM data)"
)
## -----------------------------------------------------------------------------
fit_one <- etm |>
dplyr::filter(group %in% "E-Cigarettes" & id %in% 1) |>
fit_cp_nls(
equation = "exponentiated",
return_all = TRUE
)
summary(fit_one)
plot(fit_one, x_trans = "log10")
## ----fit-individual, results='hide'-------------------------------------------
fit_all <- etm |>
group_by(id, group) |>
nest() |>
mutate(
unsys = map(data, check_systematic_cp),
fit = map(data, fit_cp_nls, equation = "exponentiated", return_all = TRUE),
summary = map(fit, summary),
plot = map(fit, plot, x_trans = "log10"),
glance = map(fit, glance),
tidy = map(fit, tidy)
)
## ----show-individual-fits-----------------------------------------------------
# Show parameter estimates for first 3 subjects only
knitr::kable(
fit_all |>
slice(1:3) |>
unnest(tidy) |>
select(id, group, term, estimate, std.error),
digits = 3,
caption = "Example parameter estimates (first 3 subjects)"
)
# Show one example plot
fit_all$plot[[2]]
## ----fit-pooled, results='hide'-----------------------------------------------
fit_pooled <- etm |>
group_by(group) |>
nest() |>
mutate(
unsys = map(data, check_systematic_cp),
fit = map(data, fit_cp_nls, equation = "exponentiated", return_all = TRUE),
summary = map(fit, summary),
plot = map(fit, plot, x_trans = "log10"),
glance = map(fit, glance),
tidy = map(fit, tidy)
)
## ----show-pooled-results------------------------------------------------------
# Show tidy results instead of summary
knitr::kable(
fit_pooled |>
unnest(tidy) |>
select(group, term, estimate, std.error),
digits = 3,
caption = "Pooled model parameter estimates by product group"
)
# Show one plot example
fit_pooled |>
dplyr::filter(group == "E-Cigarettes") |>
dplyr::pull(plot) |>
pluck(1)
## ----fit-mean, results='hide'-------------------------------------------------
fit_mean <- etm |>
group_by(group, x) |>
summarise(
y = mean(y),
.groups = "drop"
) |>
group_by(group) |>
nest() |>
mutate(
unsys = map(data, check_systematic_cp),
fit = map(data, fit_cp_nls, equation = "exponentiated", return_all = TRUE),
summary = map(fit, summary),
plot = map(fit, plot, x_trans = "log10"),
glance = map(fit, glance),
tidy = map(fit, tidy)
)
## ----show-mean-results--------------------------------------------------------
# Show tidy results
knitr::kable(
fit_mean |>
unnest(tidy) |>
select(group, term, estimate, std.error),
digits = 3,
caption = "Mean model parameter estimates by product group"
)
# Show parameter estimates plot
fit_mean |>
unnest(cols = c(glance, tidy)) |>
select(
group,
term,
estimate
) |>
ggplot(aes(x = group, y = estimate, group = term)) +
geom_bar(stat = "identity") +
geom_point() +
facet_wrap(~term, ncol = 1, scales = "free_y")
# Show one example plot
fit_mean |>
dplyr::filter(group %in% "E-Cigarettes") |>
dplyr::pull(plot) |>
pluck(1)
## -----------------------------------------------------------------------------
fit_one_linear <- etm |>
dplyr::filter(group %in% "E-Cigarettes" & id %in% 1) |>
fit_cp_linear(
type = "fixed",
log10x = TRUE,
return_all = TRUE
)
summary(fit_one_linear)
plot(fit_one_linear, x_trans = "log10")
## -----------------------------------------------------------------------------
fit_mixed <- fit_cp_linear(
etm,
type = "mixed",
log10x = TRUE,
group_effects = "interaction",
random_slope = FALSE,
return_all = TRUE
)
summary(fit_mixed)
# plot fixed effects only
plot(fit_mixed, x_trans = "log10", pred_type = "fixed")
# plot random effects only
plot(fit_mixed, x_trans = "log10", pred_type = "random")
# plot both fixed and random effects
plot(fit_mixed, x_trans = "log10", pred_type = "all")
## -----------------------------------------------------------------------------
glance(fit_one)
tidy(fit_one)
## -----------------------------------------------------------------------------
extract_coefficients(fit_mixed)
## -----------------------------------------------------------------------------
cp_posthoc_slopes(fit_mixed)
cp_posthoc_intercepts(fit_mixed)
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.