| Title: | Behavioral Economic Easy Demand |
|---|---|
| Description: | Facilitates many of the analyses performed in studies of behavioral economic demand. The package supports commonly-used options for modeling operant demand including (1) data screening proposed by Stein, Koffarnus, Snider, Quisenberry, & Bickel (2015; <doi:10.1037/pha0000020>), (2) fitting models of demand such as linear (Hursh, Raslear, Bauman, & Black, 1989, <doi:10.1007/978-94-009-2470-3_22>), exponential (Hursh & Silberberg, 2008, <doi:10.1037/0033-295X.115.1.186>) and modified exponential (Koffarnus, Franck, Stein, & Bickel, 2015, <doi:10.1037/pha0000045>), and (3) calculating numerous measures relevant to applied behavioral economists (Intensity, Pmax, Omax). Also supports plotting and comparing data. |
| Authors: | Brent Kaplan [aut, cre, cph]
|
| Maintainer: | Brent Kaplan <[email protected]> |
| License: | GPL (>= 2) |
| Version: | 0.2.0 |
| Built: | 2026-06-01 09:56:31 UTC |
| Source: | https://github.com/brentkaplan/beezdemand |
AIC for Hurdle Demand Model
## S3 method for class 'beezdemand_hurdle' AIC(object, ..., k = 2)## S3 method for class 'beezdemand_hurdle' AIC(object, ..., k = 2)
object |
A |
... |
Additional arguments (unused). |
k |
Penalty per parameter. Default is 2 (standard AIC). |
A numeric AIC value.
Creates annotation layer
annotation_logticks2( base = 10, sides = "bl", scaled = TRUE, short = unit(0.1, "cm"), mid = unit(0.2, "cm"), long = unit(0.3, "cm"), colour = "black", size = 0.5, linetype = 1, alpha = 1, data = data.frame(x = NA), color = NULL, ... )annotation_logticks2( base = 10, sides = "bl", scaled = TRUE, short = unit(0.1, "cm"), mid = unit(0.2, "cm"), long = unit(0.3, "cm"), colour = "black", size = 0.5, linetype = 1, alpha = 1, data = data.frame(x = NA), color = NULL, ... )
base |
base for drawing in scale |
sides |
sides to draw, by default bottom and left |
scaled |
true by default |
short |
short tick settings |
mid |
mid tick settings |
long |
long tick settings |
colour |
default to black colour |
size |
size for labels |
linetype |
default linetype |
alpha |
default alpha level |
data |
data to include |
color |
colors to include |
... |
additional arguments |
Inherit and extend layer for use in ggplot draw
ggplot2 layer
Shawn Gilroy [email protected]
Compare nested hurdle demand models using likelihood ratio tests.
## S3 method for class 'beezdemand_hurdle' anova(object, ...)## S3 method for class 'beezdemand_hurdle' anova(object, ...)
object |
A |
... |
Additional |
All models must be fit to the same data. Models are ordered by degrees of freedom, and sequential likelihood ratio tests are performed.
An object of class anova.beezdemand containing:
Data frame with model comparison statistics
Likelihood ratio test results
data(apt) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) anova(fit2, fit3)data(apt) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) anova(fit2, fit3)
Compare nested NLME demand models using likelihood ratio tests.
## S3 method for class 'beezdemand_nlme' anova(object, ...)## S3 method for class 'beezdemand_nlme' anova(object, ...)
object |
A |
... |
Additional |
For NLME models, this method delegates to nlme::anova.lme() on the
underlying model objects when possible.
An object of class anova.beezdemand containing model comparison statistics.
data(ko) fit1 <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben", random_effects = Q0 ~ 1) fit2 <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben", random_effects = Q0 + alpha ~ 1) anova(fit1, fit2)data(ko) fit1 <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben", random_effects = Q0 ~ 1) fit2 <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben", random_effects = Q0 + alpha ~ 1) anova(fit1, fit2)
A dataset containing alcohol purchase task data for a small number of participants
aptapt
Long-form data.frame with columns: id, x, y. Participants were asked how many standard sized alcoholic beverages they would buy at various prices.
A larger dataset containing alcohol purchase task data with demographic covariates. Suitable for testing hurdle models and mixed-effects models with covariates.
apt_fullapt_full
A data frame with 18,700 rows and 8 columns:
Unique participant identifier (1-1100)
Participant gender (Male/Female)
Participant age in years
Number of binge drinking episodes
Total number of drinks consumed
Total hours spent drinking
Price point for the purchase task
Number of drinks participant would purchase at price x
data(apt_full) # Use a subset for quick demonstration apt_sub <- apt_full[apt_full$id %in% unique(apt_full$id)[1:20], ] fit <- fit_demand_hurdle(apt_sub, y_var = "y", x_var = "x", id_var = "id") summary(fit)data(apt_full) # Use a subset for quick demonstration apt_sub <- apt_full[apt_full$id %in% unique(apt_full$id)[1:20], ] fit <- fit_demand_hurdle(apt_sub, y_var = "y", x_var = "x", id_var = "id") summary(fit)
Returns the original data with fitted values and residuals from individual demand curve fits. This enables easy model diagnostics and visualization with the tidyverse.
## S3 method for class 'beezdemand_fixed' augment(x, newdata = NULL, ...)## S3 method for class 'beezdemand_fixed' augment(x, newdata = NULL, ...)
x |
An object of class |
newdata |
Optional data frame of new data for prediction. If NULL, uses the original data from the model. |
... |
Additional arguments (currently unused). |
For "hs" equation models where fitting is done on the log10 scale, fitted values are back-transformed to the natural scale.
A tibble containing the original data plus:
Fitted demand values on the response scale
Residuals (observed - fitted)
data(apt) fit <- fit_demand_fixed(apt, y_var = "y", x_var = "x", id_var = "id") augmented <- augment(fit) # Plot residuals by subject library(ggplot2) ggplot(augmented, aes(x = .fitted, y = .resid)) + geom_point(alpha = 0.5) + facet_wrap(~id) + geom_hline(yintercept = 0, linetype = "dashed")data(apt) fit <- fit_demand_fixed(apt, y_var = "y", x_var = "x", id_var = "id") augmented <- augment(fit) # Plot residuals by subject library(ggplot2) ggplot(augmented, aes(x = .fitted, y = .resid)) + geom_point(alpha = 0.5) + facet_wrap(~id) + geom_hline(yintercept = 0, linetype = "dashed")
Returns the original data with fitted values, residuals, and predictions from a hurdle demand model. This enables easy model diagnostics and visualization with the tidyverse.
## S3 method for class 'beezdemand_hurdle' augment(x, newdata = NULL, ...)## S3 method for class 'beezdemand_hurdle' augment(x, newdata = NULL, ...)
x |
An object of class |
newdata |
Optional data frame of new data for prediction. If NULL, uses the original data from the model. |
... |
Additional arguments (currently unused). |
For two-part hurdle models:
.fitted gives predicted demand on the natural consumption scale
.fitted_prob gives the predicted probability of positive consumption
.resid is defined only for positive observations as log(y) - .fitted_link
Observations with zero consumption have .resid = NA since they are
explained by Part I (the zero-probability component), not Part II
A tibble containing the original data plus:
Fitted demand values (natural scale)
Fitted values on log scale (Part II mean)
Predicted probability of consumption (1 - P(zero))
Residuals on log scale for positive observations, NA for zeros
Residuals on response scale (y - .fitted)
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") augmented <- augment(fit) # Plot residuals library(ggplot2) ggplot(augmented, aes(x = .fitted, y = .resid)) + geom_point(alpha = 0.5) + geom_hline(yintercept = 0, linetype = "dashed")data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") augmented <- augment(fit) # Plot residuals library(ggplot2) ggplot(augmented, aes(x = .fitted, y = .resid)) + geom_point(alpha = 0.5) + geom_hline(yintercept = 0, linetype = "dashed")
Returns the original data with fitted values and residuals from a nonlinear mixed-effects demand model. This enables easy model diagnostics and visualization with the tidyverse.
## S3 method for class 'beezdemand_nlme' augment(x, newdata = NULL, ...)## S3 method for class 'beezdemand_nlme' augment(x, newdata = NULL, ...)
x |
An object of class |
newdata |
Optional data frame of new data for prediction. If NULL, uses the original data from the model. |
... |
Additional arguments (currently unused). |
The fitted values and residuals are on the same scale as the response variable
used in the model. For equation_form = "zben", this is the LL4-transformed
scale. For equation_form = "simplified" or "exponentiated", this is the natural
consumption scale.
To back-transform predictions to the natural scale for "zben" models, use:
ll4_inv(augmented$.fitted)
A tibble containing the original data plus:
Fitted values on the model scale (may be transformed, e.g., LL4)
Residuals on the model scale
Fitted values from fixed effects only (population-level)
data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") augmented <- augment(fit) # Plot residuals library(ggplot2) ggplot(augmented, aes(x = .fitted, y = .resid)) + geom_point(alpha = 0.5) + geom_hline(yintercept = 0, linetype = "dashed")data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") augmented <- augment(fit) # Plot residuals library(ggplot2) ggplot(augmented, aes(x = .fitted, y = .resid)) + geom_point(alpha = 0.5) + geom_hline(yintercept = 0, linetype = "dashed")
Methods for printing, summarizing, and visualizing objects of class
beezdemand_descriptive created by get_descriptive_summary().
## S3 method for class 'beezdemand_descriptive' print(x, ...) ## S3 method for class 'beezdemand_descriptive' summary(object, ...) ## S3 method for class 'beezdemand_descriptive' plot(x, x_trans = "identity", y_trans = "identity", show_zeros = FALSE, ...)## S3 method for class 'beezdemand_descriptive' print(x, ...) ## S3 method for class 'beezdemand_descriptive' summary(object, ...) ## S3 method for class 'beezdemand_descriptive' plot(x, x_trans = "identity", y_trans = "identity", show_zeros = FALSE, ...)
x, object
|
A |
... |
Additional arguments (currently unused) |
x_trans |
Character string specifying x-axis transformation. Options:
"identity" (default), "log10", "log", "sqrt". See |
y_trans |
Character string specifying y-axis transformation. Options: "identity" (default), "log10", "log", "sqrt", "pseudo_log" (signed log). |
show_zeros |
Logical indicating whether to show proportion of zeros as labels on the boxplot (default: FALSE) |
Displays a compact summary showing the number of subjects and prices analyzed, plus a preview of the statistics table.
Provides extended information including:
Data summary (subjects, prices analyzed)
Distribution of means across prices (min, median, max)
Proportion of zeros by price (range)
Missing data summary
Creates a boxplot showing the distribution of consumption at each price point. Features:
Red cross markers indicate means
Boxes show median and quartiles
Whiskers extend to 1.5 * IQR
Supports axis transformations (log, sqrt, etc.)
Uses modern beezdemand styling via theme_apa()
print() - Returns the object invisibly (called for side effects)
summary() - Returns a list with extended summary information
plot() - Returns a ggplot2 object
data(apt, package = "beezdemand") desc <- get_descriptive_summary(apt) # Print compact summary print(desc) # Extended summary summary(desc) # Default boxplot plot(desc) # With log-transformed y-axis plot(desc, y_trans = "log10") # With pseudo-log y-axis (handles zeros gracefully) plot(desc, y_trans = "pseudo_log")data(apt, package = "beezdemand") desc <- get_descriptive_summary(apt) # Print compact summary print(desc) # Extended summary summary(desc) # Default boxplot plot(desc) # With log-transformed y-axis plot(desc, y_trans = "log10") # With pseudo-log y-axis (handles zeros gracefully) plot(desc, y_trans = "pseudo_log")
Methods for printing, summarizing, and visualizing objects of class
beezdemand_empirical created by get_empirical_measures().
## S3 method for class 'beezdemand_empirical' print(x, ...) ## S3 method for class 'beezdemand_empirical' summary(object, ...) ## S3 method for class 'beezdemand_empirical' plot(x, type = "histogram", ...)## S3 method for class 'beezdemand_empirical' print(x, ...) ## S3 method for class 'beezdemand_empirical' summary(object, ...) ## S3 method for class 'beezdemand_empirical' plot(x, type = "histogram", ...)
x, object
|
A |
... |
Additional arguments passed to plotting functions |
type |
Character string specifying plot type. Options:
|
Displays a compact summary showing the number of subjects analyzed and a preview of the empirical measures table.
Provides extended information including:
Data summary (subjects, zero consumption patterns, completeness)
Descriptive statistics for each empirical measure (min, median, mean, max, SD)
Missing data patterns
Creates visualizations of empirical measures across subjects.
Histogram type (default):
Six-panel faceted plot showing distribution of each measure
Helps identify central tendencies and outliers
Uses modern beezdemand styling
Matrix type:
Scatterplot matrix (pairs plot) showing relationships between measures
Useful for identifying correlated demand metrics
Lower triangle: scatterplots with smoothed trend lines
Diagonal: density plots
Upper triangle: correlation coefficients
print() - Returns the object invisibly (called for side effects)
summary() - Returns a list with extended summary information
plot() - Returns a ggplot2 object
data(apt, package = "beezdemand") emp <- get_empirical_measures(apt) # Print compact summary print(emp) # Extended summary summary(emp) # Histogram of measure distributions plot(emp) # Scatterplot matrix plot(emp, type = "matrix")data(apt, package = "beezdemand") emp <- get_empirical_measures(apt) # Print compact summary print(emp) # Extended summary summary(emp) # Histogram of measure distributions plot(emp) # Scatterplot matrix plot(emp, type = "matrix")
BIC for Hurdle Demand Model
## S3 method for class 'beezdemand_hurdle' BIC(object, ...)## S3 method for class 'beezdemand_hurdle' BIC(object, ...)
object |
A |
... |
Additional arguments (unused). |
A numeric BIC value.
Calculates group-level (population) Omax and Pmax from a fitted hurdle demand model.
calc_group_metrics(object)calc_group_metrics(object)
object |
A fitted |
A named list with group-level Pmax, Omax, and Qmax.
calc_omax_pmax, fit_demand_hurdle
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") calc_group_metrics(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") calc_group_metrics(fit)
Calculate Observed Pmax/Omax Grouped by ID
calc_observed_pmax_omax( data, id_var = "id", price_var = "x", consumption_var = "y" )calc_observed_pmax_omax( data, id_var = "id", price_var = "x", consumption_var = "y" )
data |
Data frame with id, price, and consumption columns |
id_var |
Name of ID column |
price_var |
Name of price column |
consumption_var |
Name of consumption column |
Data frame with observed pmax/omax for each subject
data(apt, package = "beezdemand") calc_observed_pmax_omax(apt, id_var = "id", price_var = "x", consumption_var = "y")data(apt, package = "beezdemand") calc_observed_pmax_omax(apt, id_var = "id", price_var = "x", consumption_var = "y")
Calculates the maximum expenditure (Omax) and the price at maximum expenditure (Pmax) for the exponential demand model used in the two-part hurdle model.
calc_omax_pmax(Q0, k, alpha, price_range = NULL)calc_omax_pmax(Q0, k, alpha, price_range = NULL)
Q0 |
Intensity parameter (consumption at price 0). |
k |
Scaling parameter for the exponential decay. |
alpha |
Elasticity parameter (rate of decay). |
price_range |
Numeric vector of length 2 specifying the price range
to search for Pmax. Default is |
For the demand function:
Expenditure is E(p) = p * Q(p). Omax is the maximum of E(p) and Pmax is the price at which this maximum occurs. These are found numerically.
The search range is automatically adjusted based on alpha to ensure the maximum is found. For small alpha values, Pmax can be quite large.
A named list with:
Price at maximum expenditure
Maximum expenditure (price * quantity)
Quantity at Pmax
calc_group_metrics, fit_demand_hurdle
# Calculate for group-level parameters calc_omax_pmax(Q0 = 10, k = 2, alpha = 0.5) # With k >= e (~2.718), a local maximum exists calc_omax_pmax(Q0 = 10, k = 3, alpha = 0.5)# Calculate for group-level parameters calc_omax_pmax(Q0 = 10, k = 2, alpha = 0.5) # With k >= e (~2.718), a local maximum exists calc_omax_pmax(Q0 = 10, k = 3, alpha = 0.5)
Calculates Amplitude and Persistence latent factors from demand metrics for various beezdemand model objects.
calculate_amplitude_persistence( fit, amplitude = c("Intensity", "Q0d", "Q0"), persistence = c("BP0", "Pmaxe", "Omaxe", "Alpha"), use_inv_alpha = TRUE, strict = TRUE, min_persistence_components = 2L, empirical_y_var = NULL, basis_means = NULL, basis_sds = NULL, ... )calculate_amplitude_persistence( fit, amplitude = c("Intensity", "Q0d", "Q0"), persistence = c("BP0", "Pmaxe", "Omaxe", "Alpha"), use_inv_alpha = TRUE, strict = TRUE, min_persistence_components = 2L, empirical_y_var = NULL, basis_means = NULL, basis_sds = NULL, ... )
fit |
An object of class |
amplitude |
Character vector of column names to consider for the Amplitude factor.
The function will use the first column found in the data. Default is
|
persistence |
Character vector of column names to include in the Persistence factor.
Default is |
use_inv_alpha |
Logical. If "Alpha" (or a variation) is present in |
strict |
Logical. If |
min_persistence_components |
Integer. Minimum number of non-missing standardized
persistence components required to compute |
empirical_y_var |
For |
basis_means |
Optional named numeric vector of means to use for Z-score standardization.
Names must match the columns used (e.g., |
basis_sds |
Optional named numeric vector of standard deviations to use for Z-score standardization. Names must match the columns used. If NULL (default), the sample SDs are used. |
... |
Additional arguments passed to methods. |
This function calculates Amplitude and Persistence by:
Extracting the relevant demand metrics from the fit object.
Resolving requested metric columns (case-insensitive, with limited synonym support for common beezdemand outputs).
Inverting Alpha if requested (1/Alpha).
Standardizing (Z-scoring) the metrics. If basis_means and basis_sds are provided,
they are used; otherwise, the current sample's statistics are used.
Aggregating the Z-scores into the two latent factors.
Amplitude is defined by the variable specified in amplitude (typically Intensity/Q0).
Persistence is defined as the mean of the standardized values of the variables
specified in persistence (typically Breakpoint, Pmax, Omax, and 1/Alpha).
A data frame with the original ID and calculated Amplitude and Persistence scores, along with the standardized (Z-scored) constituent metrics.
beezdemand_fixed: Extracts metrics from fit$results.
beezdemand_hurdle: Extracts metrics from fit$subject_pars.
beezdemand_nlme: Calculates subject-specific parameters from fixed and random effects.
Parameters Q0 and Alpha are assumed to be on log10 scale for zben and simplified
equations and are converted to linear scale. Omax and Pmax are calculated empirically
from predictions. Breakpoint is calculated empirically from the raw data.
data(apt, package = "beezdemand") fit <- FitCurves(apt, "hs", k = "share") calculate_amplitude_persistence(fit)data(apt, package = "beezdemand") fit <- FitCurves(apt, "hs", k = "share") calculate_amplitude_persistence(fit)
Cross-price style data with cannabis and cigarette context.
cannabisCigarettescannabisCigarettes
A data frame with columns including: id, x, y, commodity, and auxiliary fields (Q1035, CigPrice, CanPrice, variable, value).
# data(cannabisCigarettes)# data(cannabisCigarettes)
Changes demand data
ChangeData( dat, nrepl = 1, replnum = 0.01, rem0 = FALSE, remq0e = FALSE, replfree = NULL, xcol = "x", ycol = "y", idcol = "id" )ChangeData( dat, nrepl = 1, replnum = 0.01, rem0 = FALSE, remq0e = FALSE, replfree = NULL, xcol = "x", ycol = "y", idcol = "id" )
dat |
A long form dataframe |
nrepl |
Number of zeros to replace with replacement value (replnum). Can accept either a number or "all" if all zeros should be replaced. Default is to replace the first zero only |
replnum |
Value to replace zeros. Default is .01 |
rem0 |
If TRUE, removes all 0s in consumption data prior to analysis. Default value is FALSE |
remq0e |
If TRUE, removes consumption and price where price == 0. Default value is FALSE |
replfree |
Optionally replaces price == 0 with specified value. |
xcol |
Column name in dataframe that signifies x values (usually price or the IV) |
ycol |
Column name in dataframe that signifies y values (usually consumption or the DV) |
idcol |
Column name in dataframe that signifies identifying id grouping |
Change demand data in various ways. Ways include replacing any number of 0 values with a replacement number (or remove them completely), removing price and consumption at free, replacing free with some number. This will soon replace ReplaceZeros and certain arguments in FitCurves.
Long form dataframe resembling the originally provided dataframe
Brent Kaplan [email protected]
## Change just the first instance of 0 within each unique value of id with .1 ChangeData(apt, nrepl = 1, replnum = .1)## Change just the first instance of 0 within each unique value of id with .1 ChangeData(apt, nrepl = 1, replnum = .1)
Performs diagnostic checks on fitted demand models, returning information about convergence, boundary conditions, and residual patterns.
check_demand_model(object, ...) ## S3 method for class 'beezdemand_hurdle' check_demand_model(object, ...) ## S3 method for class 'beezdemand_nlme' check_demand_model(object, ...) ## S3 method for class 'beezdemand_fixed' check_demand_model(object, ...)check_demand_model(object, ...) ## S3 method for class 'beezdemand_hurdle' check_demand_model(object, ...) ## S3 method for class 'beezdemand_nlme' check_demand_model(object, ...) ## S3 method for class 'beezdemand_fixed' check_demand_model(object, ...)
object |
A fitted model object of class |
... |
Additional arguments passed to methods. |
The function checks for:
Convergence status and optimization messages
Parameters at or near boundaries
Residual patterns (heteroscedasticity, outliers)
Random effect variance estimates near zero
Correlation matrices near singularity
An object of class beezdemand_diagnostics containing:
List with convergence status and messages
List with boundary condition warnings
Summary statistics for residuals
Summary of random effects (if applicable)
Character vector of identified issues
Character vector of recommendations
This function is named check_demand_model() to avoid potential conflicts
with performance::check_model() from the performance package.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") diagnostics <- check_demand_model(fit) print(diagnostics)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") diagnostics <- check_demand_model(fit) print(diagnostics)
Modern interface for screening cross-price data with standardized output
vocabulary aligned with check_systematic_demand().
check_systematic_cp( data, trend_threshold = 0.025, bounce_threshold_down = 0.1, bounce_threshold_up = 0.1, bounce_threshold_none = 0.1, consecutive_zeros = 2, consecutive_nonzeros = 2, expected_down = FALSE, x_var = "x", y_var = "y", id_var = "id" )check_systematic_cp( data, trend_threshold = 0.025, bounce_threshold_down = 0.1, bounce_threshold_up = 0.1, bounce_threshold_none = 0.1, consecutive_zeros = 2, consecutive_nonzeros = 2, expected_down = FALSE, x_var = "x", y_var = "y", id_var = "id" )
data |
Data frame with columns: |
trend_threshold |
Numeric. Threshold for trend detection. Default |
bounce_threshold_down |
Numeric. Bounce threshold for upward trends. Default |
bounce_threshold_up |
Numeric. Bounce threshold for downward trends. Default |
bounce_threshold_none |
Numeric. Bounce threshold when no trend. Default |
consecutive_zeros |
Integer. Zeros for reversal detection. Default |
consecutive_nonzeros |
Integer. Non-zeros for return detection. Default |
expected_down |
Logical. Suppress reversal detection if TRUE. Default |
x_var |
Character. Name of the price column. Default |
y_var |
Character. Name of the consumption column. Default |
id_var |
Character. Name of the subject identifier column. Default |
If the data contains an id column (or column specified by id_var), each
unique ID is checked separately. Otherwise, the entire dataset is treated
as a single pattern.
For cross-price data, the wrapper preserves the legacy meaning of
check_unsystematic_cp():
trend_direction and bounce_direction are taken directly from the legacy
function outputs.
trend_pass is set to NA because cross-price systematicity does not use a
separate trend “pass/fail” criterion in the same way as purchase-task
screening; instead, trend classification determines which bounce rule
applies.
bounce_stat is reported as the proportion relevant to the legacy bounce
rule for the detected trend_direction (or expected_down case), computed
from the legacy bounce counts and the number of price steps.
An object of class beezdemand_systematicity with the same structure
as check_systematic_demand(), with type = "cp".
data(etm) check <- check_systematic_cp(etm)data(etm) check <- check_systematic_cp(etm)
Modern interface for screening purchase task data using Stein et al. (2015)
criteria. Returns a structured object with standardized output vocabulary
that is consistent with check_systematic_cp().
check_systematic_demand( data, trend_threshold = 0.025, bounce_threshold = 0.1, max_reversals = 0, consecutive_zeros = 2, x_var = "x", y_var = "y", id_var = "id" )check_systematic_demand( data, trend_threshold = 0.025, bounce_threshold = 0.1, max_reversals = 0, consecutive_zeros = 2, x_var = "x", y_var = "y", id_var = "id" )
data |
Data frame in long format with columns: |
trend_threshold |
Numeric. Threshold for trend detection (log-log slope).
Default |
bounce_threshold |
Numeric. Threshold for bounce proportion. Default |
max_reversals |
Integer. Maximum allowed reversals from zero. Default |
consecutive_zeros |
Integer. Consecutive zeros required for reversal detection.
Default |
x_var |
Character. Name of the price column. Default |
y_var |
Character. Name of the consumption column. Default |
id_var |
Character. Name of the subject identifier column. Default |
The results tibble contains standardized columns for both demand and
cross-price systematicity checks:
Subject identifier
"demand" for this function
DeltaQ statistic (log-log slope)
Threshold used
"down", "up", or "none"
Logical: passed trend criterion
Bounce proportion
Threshold used
"significant" or "none"
Logical: passed bounce criterion
Count of reversals from zero
Logical: passed reversals criterion
NA for demand (CP-specific)
Count of positive values
Logical: passed all criteria
An object of class beezdemand_systematicity with components:
Tibble with one row per subject containing systematicity metrics
"demand"
The original function call
Total number of subjects
Number of subjects passing all criteria
Number of subjects failing at least one criterion
data(apt) check <- check_systematic_demand(apt) print(check) summary(check) tidy(check)data(apt) check <- check_systematic_demand(apt) print(check) summary(check) tidy(check)
Analyzes whether consumption data shows systematic trends or unsystematic patterns ("bounces") with respect to price. Includes detection of zero-value reversal/return sequences and allows flexible output based on the level of detail requested. See Rzeszutek et al. (in press) for more details.
check_unsystematic_cp( data, delta_threshold = 0.025, bounce_down_threshold = 0.1, bounce_up_threshold = 0.1, bounce_none_threshold = 0.1, rev_zeroes = 2, ret_nums = 2, expected_down = FALSE, verbose = FALSE, detailed = FALSE )check_unsystematic_cp( data, delta_threshold = 0.025, bounce_down_threshold = 0.1, bounce_up_threshold = 0.1, bounce_none_threshold = 0.1, rev_zeroes = 2, ret_nums = 2, expected_down = FALSE, verbose = FALSE, detailed = FALSE )
data |
A data frame with columns 'x' and 'y', where 'x' is price and 'y' is consumption. |
delta_threshold |
Numeric. Threshold for detecting log-scale trends (default 0.025). |
bounce_down_threshold |
Numeric. Minimum downward bounce proportion to count as significant in upward trends. |
bounce_up_threshold |
Numeric. Minimum upward bounce proportion to count as significant in downward trends. |
bounce_none_threshold |
Numeric. Minimum bounce proportion to count as significant in no-trend cases. |
rev_zeroes |
Integer. Length of zero sequences to detect reversals (default 2). |
ret_nums |
Integer. Length of non-zero sequences to detect returns (default 2). |
expected_down |
Logical. If TRUE, suppress reversal detection. |
verbose |
Logical. If TRUE, print intermediate values (default FALSE). |
detailed |
Logical. If TRUE, return additional columns including all trend/bounce flags. |
A data frame of class cp_unsystematic with core results:
Character: 'down', 'up', or 'none'.
Character: 'up', 'down', 'significant', or 'none'.
Logical. TRUE if any bounce pattern detected.
Integer. Number of upward changes meeting threshold.
Integer. Number of downward changes meeting threshold.
Integer. Detected reversals from 0 to non-0.
Integer. Detected returns from non-0 to 0.
If detailed = TRUE, returns additional columns:
Logical. Significant downward trend.
Logical. Significant upward trend.
Logical. No significant trend.
Logical. Significant bounce up in a downward trend.
Logical. Significant bounce down in an upward trend.
Logical. Significant bounces in no-trend data.
x_seq <- 10^(seq(-2, 2, length.out = 10)) pattern <- data.frame(x = x_seq, y = c(10, 5, 10, 9, 10, 13, 10, 10, 7, 9)) check_unsystematic_cp(pattern)x_seq <- 10^(seq(-2, 2, length.out = 10)) pattern <- data.frame(x = x_seq, y = c(10, 5, 10, 9, 10, 13, 10, 10, 7, 9)) check_unsystematic_cp(pattern)
Checks to ensure column names are specified
CheckCols(dat, xcol, ycol, idcol, groupcol = NULL)CheckCols(dat, xcol, ycol, idcol, groupcol = NULL)
dat |
Dataframe |
xcol |
Name of x column |
ycol |
Name of y column |
idcol |
Name of id column |
groupcol |
Name of group column |
Check column names
Dataframe
Brent Kaplan [email protected]
dat <- data.frame(price = 1:5, quantity = c(10, 8, 5, 2, 0), subj = rep(1, 5)) CheckCols(dat, xcol = "price", ycol = "quantity", idcol = "subj")dat <- data.frame(price = 1:5, quantity = c(10, 8, 5, 2, 0), subj = rep(1, 5)) CheckCols(dat, xcol = "price", ycol = "quantity", idcol = "subj")
Applies Stein, Koffarnus, Snider, Quisenberry, & Bickel's (2015) criteria for identification of nonsystematic purchase task data.
CheckUnsystematic(dat, deltaq = 0.025, bounce = 0.1, reversals = 0, ncons0 = 2)CheckUnsystematic(dat, deltaq = 0.025, bounce = 0.1, reversals = 0, ncons0 = 2)
dat |
Dataframe in long form. Colums are id, x, y. |
deltaq |
Numeric vector of length equal to one. The criterion by which the relative change in quantity purchased will be compared. Relative changes in quantity purchased below this criterion will be flagged. Default value is 0.025. |
bounce |
Numeric vector of length equal to one. The criterion by which the number of price-to-price increases in consumption that exceed 25% of initial consumption at the lowest price, expressed relative to the total number of price increments, will be compared. The relative number of price-to-price increases above this criterion will be flagged. Default value is 0.10. |
reversals |
Numeric vector of length equal to one. The criterion by which the number of reversals from number of consecutive (see ncons0) 0s will be compared. Number of reversals above this criterion will be flagged. Default value is 0. |
ncons0 |
Numer of consecutive 0s prior to a positive value is used to flag for a reversal. Value can be either 1 (relatively more conservative) or 2 (default; as recommended by Stein et al., (2015). |
This function applies the 3 criteria proposed by Stein et al., (2015) for identification of nonsystematic purchase task data. The three criteria include trend (deltaq), bounce, and reversals from 0. Also reports number of positive consumption values.
Dataframe
Brent Kaplan [email protected]
## Using all default values CheckUnsystematic(apt, deltaq = 0.025, bounce = 0.10, reversals = 0, ncons0 = 2) ## Specifying just 1 zero to flag as reversal CheckUnsystematic(apt, deltaq = 0.025, bounce = 0.10, reversals = 0, ncons0 = 1)## Using all default values CheckUnsystematic(apt, deltaq = 0.025, bounce = 0.10, reversals = 0, ncons0 = 2) ## Specifying just 1 zero to flag as reversal CheckUnsystematic(apt, deltaq = 0.025, bounce = 0.10, reversals = 0, ncons0 = 1)
Methods to extract coefficients from various cross-price demand model objects.
## S3 method for class 'cp_model_nls' coef(object, ...) ## S3 method for class 'cp_model_lm' coef(object, ...) ## S3 method for class 'cp_model_lmer' coef(object, fixed_only = FALSE, combine = TRUE, ...)## S3 method for class 'cp_model_nls' coef(object, ...) ## S3 method for class 'cp_model_lm' coef(object, ...) ## S3 method for class 'cp_model_lmer' coef(object, fixed_only = FALSE, combine = TRUE, ...)
object |
A cp_model_lm object |
... |
Additional arguments (not used). |
fixed_only |
Logical; if TRUE, returns only fixed effects. Default is FALSE. |
combine |
Logical; if TRUE and fixed_only=FALSE, returns fixed + random effects combined. Default is TRUE. |
Named vector of coefficients
A named numeric vector of model coefficients.
coef(cp_model_nls): Extract coefficients from a nonlinear cross-price model
coef(cp_model_lm): Extract coefficients from a linear cross-price model
coef(cp_model_lmer): Extract coefficients from a mixed-effects cross-price model
Extract Coefficients from Fixed-Effect Demand Fit
## S3 method for class 'beezdemand_fixed' coef(object, report_space = c("internal", "natural", "log10"), ...)## S3 method for class 'beezdemand_fixed' coef(object, report_space = c("internal", "natural", "log10"), ...)
object |
A |
report_space |
One of |
... |
Unused. |
A tibble with columns id, term, estimate, estimate_scale, term_display.
Extract Coefficients from Hurdle Demand Model
## S3 method for class 'beezdemand_hurdle' coef(object, report_space = c("natural", "log10", "internal"), ...)## S3 method for class 'beezdemand_hurdle' coef(object, report_space = c("natural", "log10", "internal"), ...)
object |
An object of class |
report_space |
Character. One of |
... |
Additional arguments (currently unused). |
Named numeric vector of fixed effect coefficients.
Provides methods to extract fixed effects, random effects, or subject-specific
(combined fixed + random) coefficients from a beezdemand_nlme object.
This is an S3 method for the generic coef function.
## S3 method for class 'beezdemand_nlme' coef( object, type = "combined", report_space = c("internal", "natural", "log10"), ... )## S3 method for class 'beezdemand_nlme' coef( object, type = "combined", report_space = c("internal", "natural", "log10"), ... )
object |
A |
type |
Character, type of coefficients to extract. One of:
|
report_space |
Character. One of |
... |
Additional arguments passed to the underlying |
Depending on type:
type="fixed": A named numeric vector of fixed-effect coefficients.
type="random": A data frame (or list of data frames if multiple levels of grouping)
of random effects, as returned by ranef.nlme().
type="combined": A data frame where rows are subjects (from id_var)
and columns are the Q0 and alpha parameters, representing subject-specific
estimates (on the log10 scale).
fixef.beezdemand_nlme, ranef.beezdemand_nlme
data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") coef(fit, type = "fixed") coef(fit, type = "random") coef(fit, type = "combined")data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") coef(fit, type = "fixed") coef(fit, type = "random") coef(fit, type = "combined")
Performs a likelihood ratio test comparing two nested hurdle demand models. Typically used to test whether adding the random effect on alpha (c_i) significantly improves model fit (3-RE vs 2-RE models).
compare_hurdle_models(model_full, model_reduced)compare_hurdle_models(model_full, model_reduced)
model_full |
A |
model_reduced |
A |
Invisibly returns a list with:
Likelihood ratio test statistic
Degrees of freedom
P-value from chi-squared distribution
Data frame with model comparison statistics
data(apt) fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) compare_hurdle_models(fit3, fit2)data(apt) fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) compare_hurdle_models(fit3, fit2)
Compare multiple demand models using information criteria and likelihood ratio tests (when applicable). Works with all beezdemand model classes.
compare_models(..., test = c("auto", "lrt", "none"))compare_models(..., test = c("auto", "lrt", "none"))
... |
Two or more model objects of class |
test |
Character; type of statistical test. One of:
|
Models are compared using AIC and BIC. For models from the same statistical backend (e.g., two hurdle models or two NLME models), likelihood ratio tests can be performed if the models are nested.
When comparing models from different backends (e.g., hurdle vs NLME), only information criteria comparisons are possible since the likelihoods are not directly comparable for LRT purposes.
| Backend 1 | Backend 2 | LRT Possible? |
| hurdle | hurdle | Yes (if nested) |
| nlme | nlme | Yes (if nested) |
| fixed | fixed | No (no likelihood) |
| hurdle | nlme | No |
| hurdle | fixed | No |
| nlme | fixed | No |
An object of class beezdemand_model_comparison containing:
Data frame with model fit statistics
Type of test performed
LRT results if performed (NULL otherwise)
Index of best model by BIC
Character vector of notes/warnings
Logical; always FALSE since nesting is not automatically verified. Users must ensure models are properly nested for valid LRT interpretation.
The likelihood ratio test (LRT) assumes that:
The models are nested (the reduced model is a special case of the full model obtained by constraining parameters).
Both models are fit to identical data.
Under the null hypothesis, the LR statistic follows a chi-square distribution with degrees of freedom equal to the difference in the number of parameters.
Important caveat for mixed-effects models: When variance components are tested at the boundary (e.g., testing whether a random effect variance is zero), the standard chi-square distribution is not appropriate. The correct null distribution is a mixture of chi-squares (Stram & Lee, 1994). The p-values reported here use the standard chi-square approximation, which is conservative (p-values are too large) for boundary tests.
This function does not automatically verify that models are nested. Users should ensure models are properly nested before interpreting LRT p-values.
Stram, D. O., & Lee, J. W. (1994). Variance components testing in the longitudinal mixed effects model. Biometrics, 50(4), 1171-1177.
compare_hurdle_models() for the legacy hurdle-specific comparison
data(apt) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) compare_models(fit2, fit3)data(apt) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) compare_models(fit2, fit3)
Computes confidence intervals for Q0, alpha, and k parameters from individual demand curve fits. Uses asymptotic normal approximation based on standard errors when available.
## S3 method for class 'beezdemand_fixed' confint(object, parm = NULL, level = 0.95, ...)## S3 method for class 'beezdemand_fixed' confint(object, parm = NULL, level = 0.95, ...)
object |
A |
parm |
Character vector of parameter names to compute CIs for. Default includes all available parameters. |
level |
Confidence level (default 0.95). |
... |
Additional arguments (ignored). |
For beezdemand_fixed objects, confidence intervals are computed using
the asymptotic normal approximation: estimate +/- z * SE. If standard errors
are not available for a parameter, the confidence bounds will be NA.
When the underlying NLS fit objects are available (from detailed = TRUE),
this method attempts to use nlstools::confint2() for more accurate
profile-based intervals.
A tibble with columns: id, term, estimate, conf.low,
conf.high, level.
fit <- fit_demand_fixed(apt, equation = "hs", k = 2) confint(fit) confint(fit, level = 0.90) confint(fit, parm = "Q0")fit <- fit_demand_fixed(apt, equation = "hs", k = 2) confint(fit) confint(fit, level = 0.90) confint(fit, parm = "Q0")
Computes confidence intervals for fixed effect parameters from a TMB-based hurdle demand model using the asymptotic normal approximation.
## S3 method for class 'beezdemand_hurdle' confint( object, parm = NULL, level = 0.95, report_space = c("internal", "natural"), ... )## S3 method for class 'beezdemand_hurdle' confint( object, parm = NULL, level = 0.95, report_space = c("internal", "natural"), ... )
object |
A |
parm |
Character vector of parameter names to compute CIs for. Default includes all fixed effect parameters. |
level |
Confidence level (default 0.95). |
report_space |
Character. Reporting space for parameters:
|
... |
Additional arguments (ignored). |
Confidence intervals are computed using the asymptotic normal approximation
based on standard errors from TMB::sdreport(). For parameters estimated
on the log scale (Q0, alpha, k), intervals can be back-transformed to the
natural scale using report_space = "natural".
The transformation uses:
For log-scale parameters: exp(estimate +/- z * SE)
A tibble with columns: term, estimate, conf.low, conf.high,
level, component, estimate_scale.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") confint(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") confint(fit)
Computes confidence intervals for fixed effect parameters from an NLME-based mixed-effects demand model.
## S3 method for class 'beezdemand_nlme' confint(object, parm = NULL, level = 0.95, method = c("wald", "profile"), ...)## S3 method for class 'beezdemand_nlme' confint(object, parm = NULL, level = 0.95, method = c("wald", "profile"), ...)
object |
A |
parm |
Character vector of parameter names to compute CIs for. Default includes all fixed effect parameters. |
level |
Confidence level (default 0.95). |
method |
Character. Method for computing intervals:
|
... |
Additional arguments passed to |
For Wald intervals, confidence bounds are computed as estimate ± z * SE using standard errors from the model summary.
For profile intervals, nlme::intervals() is called on the underlying
nlme model object. This method provides more accurate intervals but can be
computationally intensive for complex models.
A tibble with columns: term, estimate, conf.low, conf.high,
level, component.
data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") confint(fit)data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") confint(fit)
Computes confidence intervals for parameters from a nonlinear cross-price
demand model using nlstools::confint2().
## S3 method for class 'cp_model_nls' confint( object, parm = NULL, level = 0.95, method = c("asymptotic", "profile"), ... )## S3 method for class 'cp_model_nls' confint( object, parm = NULL, level = 0.95, method = c("asymptotic", "profile"), ... )
object |
A |
parm |
Character vector of parameter names to compute CIs for. Default includes all parameters. |
level |
Confidence level (default 0.95). |
method |
Character. Method for computing intervals passed to
|
... |
Additional arguments passed to |
This method wraps nlstools::confint2() to provide confidence intervals
for the log10-parameterized coefficients (log10_qalone, I, log10_beta).
For back-transformed natural-scale confidence intervals, apply the
transformation: 10^conf.low and 10^conf.high for log10-scale parameters.
A tibble with columns: term, estimate, conf.low, conf.high,
level, method.
data(etm) fit <- fit_cp_nls(etm, equation = "exponentiated") confint(fit)data(etm) fit <- fit_cp_nls(etm, equation = "exponentiated") confint(fit)
A small illustrative dataset of price (x) and consumption (y) target (target), and group (group).
cpcp
A data frame with N rows and columns:
unique identifier
price of the alternative
consumption/demand
target (e.g., alone, own, alt)
e.g., drug or product
This function performs pairwise comparisons of intercepts between groups in a cross-price demand model, but only when a significant interaction is present. The emmeans table showing estimated marginal means for intercepts is always returned.
cp_posthoc_intercepts(object, alpha = 0.05, adjust = "tukey", ...)cp_posthoc_intercepts(object, alpha = 0.05, adjust = "tukey", ...)
object |
A cp_model_lmer object from fit_cp_linear |
alpha |
Significance level for testing (default: 0.05) |
adjust |
Method for p-value adjustment; see emmeans::contrast (default: "tukey") |
... |
Additional arguments passed to emmeans |
List containing the emmeans table and optionally pairwise comparisons if interaction is significant
data(etm) fit <- fit_cp_linear(etm, type = "mixed", group_effects = TRUE) cp_posthoc_intercepts(fit)data(etm) fit <- fit_cp_linear(etm, type = "mixed", group_effects = TRUE) cp_posthoc_intercepts(fit)
This function performs pairwise comparisons of slopes between groups in a cross-price demand model, but only when a significant interaction is present. The emmeans table showing estimated marginal means for slopes is always returned.
cp_posthoc_slopes(object, alpha = 0.05, adjust = "tukey", ...)cp_posthoc_slopes(object, alpha = 0.05, adjust = "tukey", ...)
object |
A cp_model_lmer object from fit_cp_linear |
alpha |
Significance level for testing (default: 0.05) |
adjust |
Method for p-value adjustment; see emmeans::contrast (default: "tukey") |
... |
Additional arguments passed to emmeans |
List containing the emmeans table and optionally pairwise comparisons if interaction is significant
data(etm) fit <- fit_cp_linear(etm, type = "mixed", group_effects = TRUE) cp_posthoc_slopes(fit)data(etm) fit <- fit_cp_linear(etm, type = "mixed", group_effects = TRUE) cp_posthoc_slopes(fit)
A dataset containing ETM data for a small number of participants
etmetm
Long-form data.frame with columns: id, x, y, target, group. Participants were asked how many cigarettes, e-cigarettes, combustible, and non-combustible products they would buy at various prices.
A convenience function to extract coefficients from any type of cross-price demand model in a unified format. For mixed effects models, returns a list with different coefficient types.
extract_coefficients(object, ...)extract_coefficients(object, ...)
object |
A cross-price demand model object (cp_model_nls, cp_model_lm, or cp_model_lmer) |
... |
Additional arguments passed to the appropriate coef method |
For cp_model_nls and cp_model_lm, returns the model coefficients. For cp_model_lmer, returns a list with fixed, random, and combined coefficients.
data(etm, package = "beezdemand") fit <- fit_cp_nls(etm, equation = "exponentiated") extract_coefficients(fit)data(etm, package = "beezdemand") fit <- fit_cp_nls(etm, equation = "exponentiated") extract_coefficients(fit)
Extra Sum of Squares F-test
ExtraF( dat, equation = "hs", groups = NULL, verbose = FALSE, k, compare = "alpha", idcol = "id", xcol = "x", ycol = "y", groupcol = NULL, start_alpha = 0.001 )ExtraF( dat, equation = "hs", groups = NULL, verbose = FALSE, k, compare = "alpha", idcol = "id", xcol = "x", ycol = "y", groupcol = NULL, start_alpha = 0.001 )
dat |
Long form data frame |
equation |
"hs" |
groups |
NULL for all. Character vector matching groups in groupcol |
verbose |
If TRUE, prints all output including models |
k |
User-defined k value; if missing will attempt to find shared k and then mean emprirical range (in log units) |
compare |
Specify whether to compare alpha or Q0. Default is alpha |
idcol |
The column name that should be treated as dataset identifier |
xcol |
The column name that should be treated as "x" data |
ycol |
The column name that should be treated as "y" data |
groupcol |
The column name that should be treated as the groups |
start_alpha |
Optional numeric to inform starting value for alpha |
One alpha better than individual alphas?
List of results and models
Brent Kaplan [email protected]
## Compare two groups using equation by Koffarnus et al., 2015 and a fixed k of 2 apt$group <- NA apt[apt$id %in% sample(unique(apt$id), length(unique(apt$id))/2), "group"] <- "a" apt$group[is.na(apt$group)] <- "b" ExtraF(apt, "koff", k = 2, groupcol = "group")## Compare two groups using equation by Koffarnus et al., 2015 and a fixed k of 2 apt$group <- NA apt[apt$id %in% sample(unique(apt$id), length(unique(apt$id))/2), "group"] <- "a" apt$group[is.na(apt$group)] <- "b" ExtraF(apt, "koff", k = 2, groupcol = "group")
Fit a Linear Cross-Price Demand Model
fit_cp_linear( data, type = c("fixed", "mixed"), x_var = "x", y_var = "y", id_var = "id", group_var = "group", target_var = "target", filter_target = TRUE, target_level = "alt", formula = NULL, log10x = FALSE, group_effects = FALSE, random_slope = FALSE, return_all = TRUE, ... ) fit_cp_linear.default( data, formula = NULL, log10x = FALSE, return_all = FALSE, ... ) fit_cp_linear.mixed( data, formula = NULL, log10x = FALSE, return_all = FALSE, ... )fit_cp_linear( data, type = c("fixed", "mixed"), x_var = "x", y_var = "y", id_var = "id", group_var = "group", target_var = "target", filter_target = TRUE, target_level = "alt", formula = NULL, log10x = FALSE, group_effects = FALSE, random_slope = FALSE, return_all = TRUE, ... ) fit_cp_linear.default( data, formula = NULL, log10x = FALSE, return_all = FALSE, ... ) fit_cp_linear.mixed( data, formula = NULL, log10x = FALSE, return_all = FALSE, ... )
data |
A data frame containing columns for price, consumption, and optionally target indicator, subject identifier, and group. |
type |
The type of model: |
x_var |
Character string; name of the price column. Default is |
y_var |
Character string; name of the consumption column. Default is
|
id_var |
Character string; name of the subject identifier column.
Default is |
group_var |
Character string; name of the group column. Default is
|
target_var |
Character string; name of the target indicator column.
Default is |
filter_target |
Logical; if TRUE (default), filters to rows where the
target column equals |
target_level |
Character string; value of the target column to retain
when |
formula |
Optional formula override. If NULL, a formula will be
constructed based on other parameters. If non-NULL and any |
log10x |
Logical; if TRUE and formula is NULL, uses |
group_effects |
Logical or character; if TRUE, includes group as a factor
with interactions. Can also be |
random_slope |
Logical; for mixed models, if TRUE, includes random slopes for x. Default is FALSE. |
return_all |
Logical; if TRUE, returns additional model metadata. |
... |
Additional arguments passed to underlying modeling functions. |
Fitted linear model.
data(etm) ## Fixed-effects linear cross-price model fit_fixed <- fit_cp_linear(etm, type = "fixed", group_effects = TRUE) summary(fit_fixed) ## Mixed-effects linear cross-price model fit_mixed <- fit_cp_linear(etm, type = "mixed", group_effects = TRUE) summary(fit_mixed)data(etm) ## Fixed-effects linear cross-price model fit_fixed <- fit_cp_linear(etm, type = "fixed", group_effects = TRUE) summary(fit_fixed) ## Mixed-effects linear cross-price model fit_mixed <- fit_cp_linear(etm, type = "mixed", group_effects = TRUE) summary(fit_mixed)
Fits a cross-price demand curve using log10-parameterization for numerical stability. The optimizer estimates parameters on the log10 scale where applicable, ensuring positive constraints are naturally satisfied.
Equation forms:
Exponentiated (default):
Exponential (fits on log10 response scale):
Additive (level on ):
where is the alternative product price (or "cross" price) and
is consumption of the target good.
Optimizer parameters (log10 parameterization):
log10_qalone: - baseline consumption
when the alternative is effectively absent.
I: cross-price interaction intensity; sign and magnitude reflect
substitution/complementarity. Unconstrained (can be negative for substitutes).
log10_beta: - rate at which cross-price
influence decays as increases.
Natural-scale values are recovered as and
.
The function first attempts a multi-start nonlinear least squares fit
(nls.multstart). If that fails—or if explicit start_values are provided—it
falls back to minpack.lm::nlsLM. Optionally, it will make a final attempt
with nlsr::wrapnlsr. Returns either the fitted model or a structured object
with metadata for downstream methods.
fit_cp_nls( data, equation = c("exponentiated", "exponential", "additive"), x_var = "x", y_var = "y", start_values = NULL, start_vals = lifecycle::deprecated(), iter = 100, bounds = NULL, fallback_to_nlsr = TRUE, return_all = TRUE )fit_cp_nls( data, equation = c("exponentiated", "exponential", "additive"), x_var = "x", y_var = "y", start_values = NULL, start_vals = lifecycle::deprecated(), iter = 100, bounds = NULL, fallback_to_nlsr = TRUE, return_all = TRUE )
data |
A data frame with columns for price and consumption. Additional columns are ignored. Input is validated internally. |
equation |
Character string; model family, one of
|
x_var |
Character string; name of the price column in |
y_var |
Character string; name of the consumption column in |
start_values |
Optional named list of initial values for parameters
|
start_vals |
|
iter |
Integer; number of random starts for |
bounds |
Deprecated. Log10-parameterized parameters are naturally unbounded. This argument is ignored but retained for backwards compatibility. |
fallback_to_nlsr |
Logical; if |
return_all |
Logical; if |
Start values. When start_values is missing, the function:
(1) estimates a reasonable range for log10_qalone from the observed y,
(2) estimates log10_beta from the price range, and (3) launches a multi-start
grid in nls.multstart.
Zero handling for exponential equation. Since the exponential equation fits
on the scale, observations with are automatically
removed with a warning. Use the exponentiated or additive forms if you need to
retain zero consumption values.
Fitting pipeline (short-circuiting):
nls.multstart::nls_multstart() with random starts.
If that fails (or if start_values provided): minpack.lm::nlsLM() using
start_values (user or internally estimated).
If that fails and fallback_to_nlsr = TRUE: nlsr::wrapnlsr().
The returned object has class "cp_model_nls" (when return_all = TRUE) with
components: model, method (the algorithm used), equation, start_vals,
nlsLM_fit, nlsr_fit, and the data used. This is convenient for custom
print/summary/plot methods.
If return_all = TRUE (default): a list of class "cp_model_nls":
model: the fitted object from the successful backend.
method: one of "nls_multstart", "nlsLM", or "wrapnlsr".
equation: the model family used.
start_vals: named list of starting values (final used; kept for backward compatibility).
nlsLM_fit, nlsr_fit: fits from later stages (if attempted).
data: the 2-column data frame actually fit.
If return_all = FALSE: the fitted model object from the successful backend.
Check convergence codes and residual diagnostics from the underlying fit.
Poor scaling or extreme y dispersion can make parameters weakly identified.
For "exponential", the model fits on the scale internally.
check_unsystematic_cp for pre-fit data screening,
validate_cp_data for input validation.
## --- Example: Real data (E-Cigarettes, id = 1) --- dat <- structure(list( id = c(1, 1, 1, 1, 1, 1), x = c(2, 4, 8, 16, 32, 64), y = c(3, 5, 5, 16, 17, 13), target = c("alt", "alt", "alt", "alt", "alt", "alt"), group = c("E-Cigarettes", "E-Cigarettes", "E-Cigarettes", "E-Cigarettes", "E-Cigarettes", "E-Cigarettes") ), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame")) ## Fit the default (exponentiated) cross-price form fit_ecig <- fit_cp_nls(dat, equation = "exponentiated", return_all = TRUE) summary(fit_ecig) # model summary fit_ecig$method # backend actually used (e.g., "nls_multstart") coef(fit_ecig$model) # parameter estimates: log10_qalone, I, log10_beta## --- Example: Real data (E-Cigarettes, id = 1) --- dat <- structure(list( id = c(1, 1, 1, 1, 1, 1), x = c(2, 4, 8, 16, 32, 64), y = c(3, 5, 5, 16, 17, 13), target = c("alt", "alt", "alt", "alt", "alt", "alt"), group = c("E-Cigarettes", "E-Cigarettes", "E-Cigarettes", "E-Cigarettes", "E-Cigarettes", "E-Cigarettes") ), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame")) ## Fit the default (exponentiated) cross-price form fit_ecig <- fit_cp_nls(dat, equation = "exponentiated", return_all = TRUE) summary(fit_ecig) # model summary fit_ecig$method # backend actually used (e.g., "nls_multstart") coef(fit_ecig$model) # parameter estimates: log10_qalone, I, log10_beta
Modern interface for fitting individual demand curves via nonlinear
least squares. Returns a structured S3 object with standard methods
including summary(), tidy(), and glance().
fit_demand_fixed( data, equation = c("hs", "koff", "simplified", "linear", "exponential", "exponentiated"), k = 2, agg = NULL, x_var = "x", y_var = "y", id_var = "id", param_space = c("natural", "log10"), ... )fit_demand_fixed( data, equation = c("hs", "koff", "simplified", "linear", "exponential", "exponentiated"), k = 2, agg = NULL, x_var = "x", y_var = "y", id_var = "id", param_space = c("natural", "log10"), ... )
data |
Data frame in long format with columns: |
equation |
Character. Equation type: |
k |
Scaling constant. Numeric value (fixed), |
agg |
Character. Aggregation method: |
x_var |
Character. Name of the price column. Default |
y_var |
Character. Name of the consumption column. Default |
id_var |
Character. Name of the subject identifier column. Default |
param_space |
Character. Parameterization used for fitting. One of:
|
... |
Additional arguments passed to the underlying |
This function is a modern wrapper around the legacy FitCurves() function.
It provides the same fitting capabilities but returns a structured S3 object
with standardized methods for model interrogation.
An object of class beezdemand_fixed with components:
Data frame of fitted parameters for each subject
List of model fit objects (if detailed = TRUE internally)
List of prediction data frames
List of data frames used for each fit
The original function call
The equation form used
Description of k specification
Aggregation method used
Total number of subjects/fits attempted
Number of successful fits
Number of failed fits
data(apt) fit <- fit_demand_fixed(apt, equation = "hs", k = 2) print(fit) summary(fit) tidy(fit) glance(fit)data(apt) fit <- fit_demand_fixed(apt, equation = "hs", k = 2) print(fit) summary(fit) tidy(fit) glance(fit)
Fits a two-part hurdle model for demand data using TMB (Template Model Builder). Part I models the probability of zero consumption using logistic regression. Part II models log-consumption given positive response using a nonlinear mixed effects model.
fit_demand_hurdle( data, y_var, x_var, id_var, random_effects = c("zeros", "q0", "alpha"), epsilon = 0.001, start_values = NULL, tmb_control = list(max_iter = 200, eval_max = 1000, trace = 0), verbose = 1, part2 = c("zhao_exponential", "exponential", "simplified_exponential"), ... )fit_demand_hurdle( data, y_var, x_var, id_var, random_effects = c("zeros", "q0", "alpha"), epsilon = 0.001, start_values = NULL, tmb_control = list(max_iter = 200, eval_max = 1000, trace = 0), verbose = 1, part2 = c("zhao_exponential", "exponential", "simplified_exponential"), ... )
data |
A data frame containing the demand data. |
y_var |
Character string specifying the column name for consumption values. |
x_var |
Character string specifying the column name for price. |
id_var |
Character string specifying the column name for subject IDs. |
random_effects |
Character vector specifying which random effects to include.
Options are |
epsilon |
Small constant added to price before log transformation in Part I.
Used to handle zero prices: |
start_values |
Optional named list of starting values for optimization.
If |
tmb_control |
List of control parameters for TMB optimization:
|
verbose |
Integer controlling output verbosity: 0 = silent, 1 = progress messages, 2 = detailed optimization trace. Default is 1. |
part2 |
Character string selecting the Part II mean function. Options are
|
... |
Additional arguments (reserved for future use). |
The model structure is:
Part I (Binary - probability of zero consumption):
Part II (Continuous - log consumption given positive):
With 3 random effects (random_effects = c("zeros", "q0", "alpha")):
where and .
With 2 random effects (random_effects = c("zeros", "q0")):
where and .
Random effects follow a multivariate normal distribution with unstructured
covariance matrix. Use compare_hurdle_models for likelihood
ratio tests comparing nested models.
An object of class beezdemand_hurdle containing:
List with coefficients, se, variance_components, correlations
Matrix of empirical Bayes random effect estimates
Data frame of subject-specific parameters including Q0, alpha, breakpoint, Pmax, Omax
TMB objective function object
Optimization result from nlminb
TMB sdreport object
The matched call
Original data used for fitting
List with y_var, x_var, id_var, n_subjects, n_obs, etc.
Logical indicating convergence
Log-likelihood at convergence
Information criteria
Error message if fitting failed, NULL otherwise
The TMB backend estimates positive-constrained parameters on the natural-log
scale: , , and . Reporting methods
(summary(), tidy(), coef()) can back-transform to the natural scale or
present parameters on the scale.
To compare estimates with models fit in space,
use:
summary.beezdemand_hurdle, predict.beezdemand_hurdle,
plot.beezdemand_hurdle, compare_hurdle_models,
simulate_hurdle_data
# Load example data data(apt) # Fit full model with 3 random effects fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) # Fit simplified model with 2 random effects (fixed alpha) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) # View results summary(fit3) # Compare models with likelihood ratio test compare_hurdle_models(fit3, fit2)# Load example data data(apt) # Fit full model with 3 random effects fit3 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0", "alpha")) # Fit simplified model with 2 random effects (fixed alpha) fit2 <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id", random_effects = c("zeros", "q0")) # View results summary(fit3) # Compare models with likelihood ratio test compare_hurdle_models(fit3, fit2)
Fits a nonlinear mixed-effects model for behavioral economic demand data. The function allows Q0 and alpha parameters to vary by specified factors and supports different demand equation forms.
fit_demand_mixed( data, y_var, x_var, id_var, factors = NULL, factor_interaction = FALSE, equation_form = c("zben", "simplified", "exponentiated"), param_space = c("log10", "natural"), k = NULL, custom_model_formula = NULL, fixed_rhs = NULL, continuous_covariates = NULL, start_value_method = c("heuristic", "pooled_nls"), random_effects = Q0 + alpha ~ 1, covariance_structure = c("pdDiag", "pdSymm"), start_values = NULL, collapse_levels = NULL, nlme_control = list(msMaxIter = 200, niterEM = 100, maxIter = 200, pnlsTol = 0.001, tolerance = 1e-06, apVar = TRUE, minScale = 1e-09, opt = "nlminb", msVerbose = FALSE), method = "ML", ... )fit_demand_mixed( data, y_var, x_var, id_var, factors = NULL, factor_interaction = FALSE, equation_form = c("zben", "simplified", "exponentiated"), param_space = c("log10", "natural"), k = NULL, custom_model_formula = NULL, fixed_rhs = NULL, continuous_covariates = NULL, start_value_method = c("heuristic", "pooled_nls"), random_effects = Q0 + alpha ~ 1, covariance_structure = c("pdDiag", "pdSymm"), start_values = NULL, collapse_levels = NULL, nlme_control = list(msMaxIter = 200, niterEM = 100, maxIter = 200, pnlsTol = 0.001, tolerance = 1e-06, apVar = TRUE, minScale = 1e-09, opt = "nlminb", msVerbose = FALSE), method = "ML", ... )
data |
A data frame. |
y_var |
Character string, the name of the dependent variable column.
For |
x_var |
Character string, the name of the independent variable column (e.g., "x", price). |
id_var |
Character string, the name of the subject/group identifier column for random effects. |
factors |
A character vector of factor names (up to two) by which Q0 and alpha
are expected to vary (e.g., |
factor_interaction |
Logical. If |
equation_form |
Character string specifying the demand equation form. Options are:
|
param_space |
Character. Parameterization used for fitting core demand parameters. One of:
Notes:
|
k |
Numeric. Range parameter (in log10 units) used with |
custom_model_formula |
An optional custom nonlinear model formula (nlme format).
If provided, this overrides |
fixed_rhs |
Optional one-sided formula or character string specifying the
right-hand side (RHS) for the fixed-effects linear models of |
continuous_covariates |
Optional character vector of continuous (numeric)
predictor names to be included additively in the fixed-effects RHS when
|
start_value_method |
Character, method to generate starting values if |
random_effects |
A formula or a list of formulas for the random effects structure.
Default |
covariance_structure |
Character, covariance structure for random effects.
Options: |
start_values |
Optional named list of starting values for fixed effects.
If |
collapse_levels |
Optional named list specifying factor level collapsing separately for Q0 and alpha parameters. Structure: list( Q0 = list(factor_name = list(new_level = c(old_levels), ...)), alpha = list(factor_name = list(new_level = c(old_levels), ...)) ) Either |
nlme_control |
Control parameters for |
method |
Fitting method for |
... |
Additional arguments passed to |
An object of class beezdemand_nlme.
# Basic mixed-effects demand fit with apt data # Transform consumption using LL4 for the zben equation apt_ll4 <- apt |> dplyr::mutate(y_ll4 = ll4(y)) fit <- fit_demand_mixed( data = apt_ll4, y_var = "y_ll4", x_var = "x", id_var = "id", equation_form = "zben" ) print(fit) summary(fit)# Basic mixed-effects demand fit with apt data # Transform consumption using LL4 for the zben equation apt_ll4 <- apt |> dplyr::mutate(y_ll4 = ll4(y)) fit <- fit_demand_mixed( data = apt_ll4, y_var = "y_ll4", x_var = "x", id_var = "id", equation_form = "zben" ) print(fit) summary(fit)
Analyzes purchase task data
FitCurves( dat, equation, k, agg = NULL, detailed = FALSE, xcol = "x", ycol = "y", idcol = "id", groupcol = NULL, lobound, hibound, constrainq0 = NULL, startq0 = NULL, startalpha = NULL, param_space = c("natural", "log10") )FitCurves( dat, equation, k, agg = NULL, detailed = FALSE, xcol = "x", ycol = "y", idcol = "id", groupcol = NULL, lobound, hibound, constrainq0 = NULL, startq0 = NULL, startalpha = NULL, param_space = c("natural", "log10") )
dat |
data frame (long form) of purchase task data. |
equation |
Character vector of length one. Accepts either "hs" for Hursh and Silberberg (2008) or "koff" for Koffarnus, Franck, Stein, and Bickel (2015). |
k |
A numeric (or character) vector of length one. Reflects the range of consumption in log10 units. If none provided, k will be calculated based on the max/min of the entire sample + .5. If k = "ind", k will be calculated per individual using max/min + .5. If k = "fit", k will be a free parameter on an individual basis. If k = "range", k will be calculated based on the max/min of the entire sample + .5. |
agg |
Character vector of length one accepts either "Mean" or "Pooled". If not NULL (default), data will be aggregrated appropriately and analyzed in the specified way. |
detailed |
If TRUE, output will be a 3 element list including (1) dataframe of results, (2) list of model objects, (3) list of individual dataframes used in fitting. Default value is FALSE, which returns only the dataframe of results. |
xcol |
The column name that should be treated as "x" data |
ycol |
The column name that should be treated as "y" data |
idcol |
The column name that should be treated as dataset identifier |
groupcol |
The column name that should be treated as the groups |
lobound |
Optional. A named vector of length 2 ("q0", "alpha") or 3 ("q0", "k", "alpha"), the latter length if k = "fit", specifying the lower bounds. |
hibound |
Optional. A named vector of length 2 ("q0", "alpha") or 3 ("q0", "k", "alpha"), the latter length if k = "fit", specifying the upper bounds. |
constrainq0 |
Optional. A number that will be used to constrain Q0 in the fitting process. Currently experimental and only works with a fixed k value. |
startq0 |
Optional. A number that will be used to start Q0 in the fitting process. Currently experimental. |
startalpha |
Optional. A number that will be used to start Alpha in the fitting process. Currently experimental. |
param_space |
Character. One of "natural" (default) or "log10". Specifies whether parameters (Q0, alpha) are estimated in natural space or log10-transformed space. |
FitCurves() has been superseded by fit_demand_fixed(), which provides a
modern S3 interface with standardized methods (summary(), tidy(),
glance(), predict()). FitCurves() will continue to work but is no
longer recommended for new code. See vignette("migration-guide") for
migration instructions.
If detailed == FALSE (default), a dataframe of results. If detailed == TRUE, a 3 element list consisting of (1) dataframe of results, (2) list of model objects, (3) list of individual dataframes used in fitting
Brent Kaplan [email protected] Shawn Gilroy [email protected]
fit_demand_fixed() for the modern interface
## Analyze using Hursh & Silberberg, 2008 equation with a k fixed to 2 FitCurves(apt[sample(apt$id, 5), ], "hs", k = 2)## Analyze using Hursh & Silberberg, 2008 equation with a k fixed to 2 FitCurves(apt[sample(apt$id, 5), ], "hs", k = 2)
Fits curve to pooled or mean data
FitMeanCurves( dat, equation, k, remq0e = FALSE, replfree = NULL, rem0 = FALSE, nrepl = NULL, replnum = NULL, plotcurves = FALSE, method = NULL, indpoints = TRUE, vartext = NULL )FitMeanCurves( dat, equation, k, remq0e = FALSE, replfree = NULL, rem0 = FALSE, nrepl = NULL, replnum = NULL, plotcurves = FALSE, method = NULL, indpoints = TRUE, vartext = NULL )
dat |
data frame (long form) of purchase task data. |
equation |
Character vector of length one. Accepts either "hs" for Hursh and Silberberg (2008) or "koff" for Koffarnus, Franck, Stein, and Bickel (2015). |
k |
A numeric vector of length one. Reflects the range of consumption in log10 units. If none provided, k will be calculated based on the max/min of the entire sample. If k = "fit", k will be a free parameter |
remq0e |
If TRUE, removes consumption and price where price == 0. Default value is FALSE |
replfree |
Optionally replaces price == 0 with specified value. Note, if fitting using equation == "hs", and 0 is first price, 0 gets replaced by replfree. Default value is .01 |
rem0 |
If TRUE, removes all 0s in consumption data prior to analysis. Default value is FALSE. |
nrepl |
Number of zeros to replace with replacement value (replnum). Can accept either a number or "all" if all zeros should be replaced. Default is to replace the first zero only. |
replnum |
Value to replace zeros. Default is .01 |
plotcurves |
Boolean whether to create plot. If TRUE, a "plots/" directory is created one level above working directory. Default is FALSE. |
method |
Character string of length 1. Accepts "Mean" to fit to mean data or "Pooled" to fit to pooled data |
indpoints |
Boolean whether to plot individual points in gray. Default is TRUE. |
vartext |
Character vector specifying indices to report on plots. Valid indices include "Q0d", "Alpha", "Q0e", "EV", "Pmaxe", "Omaxe", "Pmaxd", "Omaxd", "K", "Q0se", "Alphase", "R2", "AbsSS" |
FitMeanCurves() has been superseded by fit_demand_fixed() with the
agg parameter. FitMeanCurves() will continue to work but is no longer
recommended for new code. See vignette("migration-guide") for migration
instructions.
Data frame
Brent Kaplan [email protected]
fit_demand_fixed() for the modern interface with agg parameter
## Fit aggregated data (mean only) using Hursh & Silberberg, 2008 equation with a k fixed at 2 FitMeanCurves(apt[sample(apt$id, 5), ], "hs", k = 2, method = "Mean")## Fit aggregated data (mean only) using Hursh & Silberberg, 2008 equation with a k fixed at 2 FitMeanCurves(apt[sample(apt$id, 5), ], "hs", k = 2, method = "Mean")
Modern wrapper for fitting individual demand curves via nonlinear least squares. Returns a structured S3 object with standard methods.
S3 method for fixef for objects of class beezdemand_nlme.
Extracts the fixed-effect coefficients from the fitted nlme model.
## S3 method for class 'beezdemand_nlme' fixef(object, ...)## S3 method for class 'beezdemand_nlme' fixef(object, ...)
object |
A |
... |
Additional arguments passed to |
A named numeric vector of fixed-effect coefficients.
coef.beezdemand_nlme, ranef.beezdemand_nlme
Extract Fixed Effects from Mixed-Effects Cross-Price Model
## S3 method for class 'cp_model_lmer' fixef(object, ...)## S3 method for class 'cp_model_lmer' fixef(object, ...)
object |
A cp_model_lmer object |
... |
Additional arguments passed to fixef |
Named vector of fixed effects
Conducts pairwise comparisons for Q0 and/or alpha parameters from a
beezdemand_nlme model across levels of specified factors.
Comparisons are performed on the log10 scale of the parameters.
Results include estimates of differences (on log10 scale) and
optionally, ratios (on the natural scale by applying 10^difference).
get_demand_comparisons( fit_obj, params_to_compare = c("Q0", "alpha"), compare_specs = NULL, contrast_type = "pairwise", contrast_by = NULL, adjust = "tukey", at = NULL, ci_level = 0.95, report_ratios = TRUE, ... )get_demand_comparisons( fit_obj, params_to_compare = c("Q0", "alpha"), compare_specs = NULL, contrast_type = "pairwise", contrast_by = NULL, adjust = "tukey", at = NULL, ci_level = 0.95, report_ratios = TRUE, ... )
fit_obj |
A |
params_to_compare |
Character vector: "Q0", "alpha", or |
compare_specs |
A formula specifying the factors whose levels are to be included in the EMM calculation
prior to contrasting. This defines the "cells" of your design for EMMs.
E.g., |
contrast_type |
Character string specifying the type of contrast (passed to |
contrast_by |
Optional character vector of factor names to condition the contrasts by (passed to |
adjust |
P-value adjustment method. Default "tukey". |
at |
Optional named list for |
ci_level |
Confidence level. Default 0.95. |
report_ratios |
Logical. If TRUE, reports contrasts as ratios. Default |
... |
Additional arguments passed to |
A list named by parameter. Each element contains:
emmeans |
Tibble of EMMs (log10 scale) with CIs. |
contrasts_log10 |
Tibble of comparisons (log10 differences) with CIs and p-values. |
contrasts_ratio |
(If |
S3 class beezdemand_comparison is assigned.
data(ko, package = "beezdemand") ko$y_ll4 <- ll4(ko$y, lambda = 4) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") get_demand_comparisons(fit)data(ko, package = "beezdemand") ko$y_ll4 <- ll4(ko$y, lambda = 4) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") get_demand_comparisons(fit)
Calculates Estimated Marginal Means (EMMs) for Q0 and alpha parameters
from a beezdemand_nlme model for all combinations of specified factor levels.
Reports parameters on both their estimation scale (log10) and their
natural, back-transformed scale. Optionally includes Essential Value (EV).
get_demand_param_emms( fit_obj, factors_in_emm = NULL, at = NULL, ci_level = 0.95, include_ev = FALSE, ... )get_demand_param_emms( fit_obj, factors_in_emm = NULL, at = NULL, ci_level = 0.95, include_ev = FALSE, ... )
fit_obj |
A |
factors_in_emm |
Character vector of factor names to compute EMMs over.
Defaults to all factors present in the |
at |
Optional named list specifying levels of conditioning variables for |
ci_level |
Confidence level for the EMMs (default 0.95). |
include_ev |
Logical. If TRUE, calculates and includes Essential Value (EV)
derived from alpha, along with its confidence interval (calculated by
back-transforming the CI of alpha_param_log10). Default |
... |
Additional arguments passed to |
A tibble containing:
Factor levels |
Columns for each factor in |
Q0_param_log10, alpha_param_log10
|
EMMs for the model parameters (log10 scale) with their respective confidence intervals (LCL_Q0_param, UCL_Q0_param, etc.). |
Q0_natural, alpha_natural
|
EMMs back-transformed to the natural scale (10^param) with their respective confidence intervals (LCL_Q0_natural, UCL_Q0_natural, etc.). |
EV, LCL_EV, UCL_EV
|
(If |
data(ko, package = "beezdemand") ko$y_ll4 <- ll4(ko$y, lambda = 4) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") get_demand_param_emms(fit)data(ko, package = "beezdemand") ko$y_ll4 <- ll4(ko$y, lambda = 4) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") get_demand_param_emms(fit)
Computes the trend (slope) of Q0 and/or alpha with respect to one or more
continuous covariates using emmeans::emtrends() on a fitted beezdemand_nlme
model. Trends are computed on the parameter estimation scale (log10), consistent
with how parameters are modeled.
get_demand_param_trends( fit_obj, params = c("Q0", "alpha"), covariates, specs = ~1, at = NULL, ci_level = 0.95, ... )get_demand_param_trends( fit_obj, params = c("Q0", "alpha"), covariates, specs = ~1, at = NULL, ci_level = 0.95, ... )
fit_obj |
A |
params |
Character vector of parameters to analyze: any of "Q0", "alpha".
Default |
covariates |
Character vector of continuous covariate names for which to compute trends. |
specs |
A formula specifying the factors over which to produce trends
(e.g., |
at |
Optional named list to condition variables (factors or continuous)
when computing trends (passed through to |
ci_level |
Confidence level for intervals. Default 0.95. |
... |
Additional args passed to |
A tibble combining trends for each requested parameter and covariate,
including columns for grouping factors (from specs), parameter,
covariate, trend (slope on log10 scale), and its CI (lower.CL, upper.CL).
data(ko) ko$dose_num <- as.numeric(as.character(ko$dose)) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "drug", equation_form = "zben") trends <- get_demand_param_trends(fit, covariates = "dose_num", specs = ~ drug)data(ko) ko$dose_num <- as.numeric(as.character(ko$dose)) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "drug", equation_form = "zben") trends <- get_demand_param_trends(fit, covariates = "dose_num", specs = ~ drug)
Calculates summary statistics for consumption data at each price point, including measures of central tendency (mean, median), variability (SD), range (min, max), and data quality (proportion of zeros, missing values).
This is the modern replacement for GetDescriptives(), returning a structured
S3 object with dedicated methods for printing, summarizing, and visualizing.
get_descriptive_summary(data, x_var = "x", y_var = "y", id_var = "id")get_descriptive_summary(data, x_var = "x", y_var = "y", id_var = "id")
data |
A data frame in long format with columns for subject ID, price, and consumption |
x_var |
Character string specifying the column name for price (default: "x") |
y_var |
Character string specifying the column name for consumption (default: "y") |
id_var |
Character string specifying the column name for subject ID (default: "id") |
For each unique price in the dataset, the function calculates:
Mean - Average consumption across subjects (rounded to 2 decimals)
Median - Median consumption (rounded to 2 decimals)
SD - Standard deviation (rounded to 2 decimals)
PropZeros - Proportion of subjects with zero consumption (0-1)
NAs - Count of missing values
Min - Minimum consumption value (rounded to 2 decimals)
Max - Maximum consumption value (rounded to 2 decimals)
An S3 object of class beezdemand_descriptive containing:
statistics - Data frame with 8 columns (Price, Mean, Median, SD, PropZeros, NAs, Min, Max) and one row per unique price
call - The matched call
data_summary - List with n_subjects, n_prices, and prices vector
GetDescriptives() - Legacy function (superseded)
plot.beezdemand_descriptive() - Visualization method
summary.beezdemand_descriptive() - Extended summary
data(apt, package = "beezdemand") # Calculate descriptive statistics desc <- get_descriptive_summary(apt) print(desc) # View statistics table desc$statistics # Create visualization plot(desc) # Extended summary with distribution info summary(desc)data(apt, package = "beezdemand") # Calculate descriptive statistics desc <- get_descriptive_summary(apt) print(desc) # View statistics table desc$statistics # Create visualization plot(desc) # Extended summary with distribution info summary(desc)
Calculates empirical (model-free) measures of demand from purchase task data. These metrics characterize consumption patterns without fitting a demand curve model.
This is the modern replacement for GetEmpirical(), returning a structured
S3 object with dedicated methods for printing, summarizing, and visualizing.
get_empirical_measures(data, x_var = "x", y_var = "y", id_var = "id")get_empirical_measures(data, x_var = "x", y_var = "y", id_var = "id")
data |
A data frame in long format with columns for subject ID, price, and consumption |
x_var |
Character string specifying the column name for price (default: "x") |
y_var |
Character string specifying the column name for consumption (default: "y") |
id_var |
Character string specifying the column name for subject ID (default: "id") |
Intensity - The consumption value at the lowest price point. Reflects unrestricted demand or preferred level of consumption.
BP0 (Breakpoint 0) - The first price at which consumption drops to zero. If consumption never reaches zero, BP0 = NA. Indicates the price threshold where the commodity becomes unaffordable or undesirable.
BP1 (Breakpoint 1) - The highest price at which consumption is still non-zero. If all consumption is zero, BP1 = NA. Represents the upper limit of the commodity's value to the consumer.
Omaxe (Empirical Omax) - The maximum observed expenditure across all prices (max of price × consumption). Represents peak spending on the commodity.
Pmaxe (Empirical Pmax) - The price at which maximum expenditure occurs. If maximum expenditure is zero, Pmaxe = 0. If multiple prices have the same maximum expenditure, the highest price is returned.
An S3 object of class beezdemand_empirical containing:
measures - Data frame with one row per subject and columns:
id - Subject identifier
Intensity - Consumption at lowest price (demand intensity)
BP0 - Breakpoint 0: first price where consumption = 0
BP1 - Breakpoint 1: last price with non-zero consumption
Omaxe - Empirical Omax: maximum total expenditure (price × consumption)
Pmaxe - Empirical Pmax: price at which maximum expenditure occurs
call - The matched call
data_summary - List with n_subjects, has_zeros, and complete_cases
Data must not contain duplicate prices within a subject (will error)
Missing values (NA) in consumption are preserved in calculations where applicable
Breakpoints require at least one zero consumption value to be meaningful
GetEmpirical() - Legacy function (superseded)
plot.beezdemand_empirical() - Visualization method
summary.beezdemand_empirical() - Extended summary
data(apt, package = "beezdemand") # Calculate empirical measures emp <- get_empirical_measures(apt) print(emp) # View measures table emp$measures # Extended summary with distribution info summary(emp) # Visualize distribution of measures plot(emp) # histogram by default plot(emp, type = "matrix") # scatterplot matrixdata(apt, package = "beezdemand") # Calculate empirical measures emp <- get_empirical_measures(apt) print(emp) # View measures table emp$measures # Extended summary with distribution info summary(emp) # Visualize distribution of measures plot(emp) # histogram by default plot(emp, type = "matrix") # scatterplot matrix
Provides summary statistics for subject-level demand parameters from a hurdle demand model. This is analogous to EMMs but based on empirical Bayes estimates of subject-specific parameters.
get_hurdle_param_summary(fit_obj, ci_level = 0.95)get_hurdle_param_summary(fit_obj, ci_level = 0.95)
fit_obj |
A |
ci_level |
Confidence level for intervals (default 0.95). |
A data frame with summary statistics for each parameter:
Parameter name
Mean across subjects
Standard deviation across subjects
Median across subjects
Lower confidence limit (based on percentiles)
Upper confidence limit (based on percentiles)
Minimum value
Maximum value
fit_demand_hurdle, get_subject_pars
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") get_hurdle_param_summary(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") get_hurdle_param_summary(fit)
This function extracts and combines fixed and random effects to calculate individual-level predicted coefficients for all parameter-factor combinations from a beezdemand_nlme model object. It automatically detects the factor structure and calculates coefficients for each individual and factor level.
get_individual_coefficients( fit_obj, params = c("Q0", "alpha"), format = c("wide", "long") )get_individual_coefficients( fit_obj, params = c("Q0", "alpha"), format = c("wide", "long") )
fit_obj |
A |
params |
Character vector specifying which parameters to calculate. Options are "Q0", "alpha", or c("Q0", "alpha"). Default is c("Q0", "alpha"). |
format |
Character, output format. "wide" returns one row per individual with separate columns for each parameter-factor combination. "long" returns one row per individual-parameter-factor combination. Default is "wide". |
Individual-level coefficients represent the predicted parameter values for each subject in the study. For models with factors, these coefficients combine:
The baseline intercept effect (fixed + random)
The factor-specific effect (fixed + random) for each factor level
This is equivalent to manually calculating:
coefficient = intercept_fixed + intercept_random + factor_fixed + factor_random
The function automatically handles:
Models with or without factors
Any number of factor levels
Missing random effects (defaults to 0)
Complex factor structures with multiple factors
For models without factors, only intercept coefficients are calculated. For models with factors, both intercept and factor-level coefficients are provided.
A data frame with individual-level predicted coefficients.
In "wide" format: rows are individuals, columns are parameter-factor combinations
In "long" format: columns are id, parameter, condition, coefficient_value
Column naming convention for wide format:
estimated_\{param\}_intercept: Baseline/reference level coefficient
estimated_\{param\}_\{factor\}\{level\}: Factor level-specific coefficient
All coefficients are on the log10 scale (same as model estimation scale).
To convert to natural scale, use 10^coefficient.
fit_demand_mixed for fitting the original model
coef.beezdemand_nlme for extracting model coefficients
get_demand_param_emms for estimated marginal means
data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "drug", equation_form = "zben") individual_coefs <- get_individual_coefficients(fit) head(individual_coefs)data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "drug", equation_form = "zben") individual_coefs <- get_individual_coefficients(fit) head(individual_coefs)
Calculates the k scaling parameter used in demand curve equations to normalize consumption across different units or ranges. The k value is derived from the logarithmic range of consumption values.
This is the modern replacement for GetK(), with explicit parameters for
the adjustment value and optional verbose output.
get_k( data, use_means = TRUE, adjustment = 0.5, x_var = "x", y_var = "y", verbose = FALSE )get_k( data, use_means = TRUE, adjustment = 0.5, x_var = "x", y_var = "y", verbose = FALSE )
data |
A data frame in long format with columns for price and consumption |
use_means |
Logical indicating whether to calculate k from mean consumption by price (TRUE, default) or from individual consumption values (FALSE) |
adjustment |
Numeric adjustment added to the log range (default: 0.5). This value ensures k is slightly larger than the observed range. |
x_var |
Character string specifying the column name for price (default: "x") |
y_var |
Character string specifying the column name for consumption (default: "y") |
verbose |
Logical indicating whether to print calculation details (default: FALSE) |
The k parameter is calculated as:
where max and min are the maximum and minimum non-zero consumption values.
The k parameter appears in several demand curve equations:
Hursh & Silberberg (2008): Scales the exponential term
Koffarnus et al. (2015): Normalizes the exponentiated model
Ensures numerical stability during model fitting
use_means = TRUE (default): Calculates k from mean consumption at each price point. Recommended when data has multiple subjects, as it reduces influence of individual outliers.
use_means = FALSE: Calculates k from the full range of individual consumption values. May be preferable for single-subject data or when individual variability is theoretically important.
A single numeric value representing the k scaling parameter
Only non-zero consumption values are used (zero values are excluded)
Missing values (NA) are automatically removed via na.rm = TRUE
The default adjustment of 0.5 is conventional but can be modified
GetK() - Legacy function (superseded)
FitCurves() - Uses k parameter in demand curve fitting
data(apt, package = "beezdemand") # Calculate k using default settings (mean range + 0.5) k_val <- get_k(apt) # Calculate k from individual values k_ind <- get_k(apt, use_means = FALSE) # Calculate with custom adjustment k_custom <- get_k(apt, adjustment = 1.0) # Show calculation details k_verbose <- get_k(apt, verbose = TRUE)data(apt, package = "beezdemand") # Calculate k using default settings (mean range + 0.5) k_val <- get_k(apt) # Calculate k from individual values k_ind <- get_k(apt, use_means = FALSE) # Calculate with custom adjustment k_custom <- get_k(apt, adjustment = 1.0) # Show calculation details k_verbose <- get_k(apt, verbose = TRUE)
This function is a wrapper around get_demand_param_emms. It first calls
get_demand_param_emms to calculate Estimated Marginal Means (EMMs) for
Q0 and alpha parameters over all combinations of the specified factor levels.
It then filters these results to return EMMs only for the combinations of
factor levels that were actually present in the original dataset used to
fit the beezdemand_nlme model.
get_observed_demand_param_emms( fit_obj, factors_in_emm = NULL, at = NULL, ci_level = 0.95, include_ev = FALSE, ... )get_observed_demand_param_emms( fit_obj, factors_in_emm = NULL, at = NULL, ci_level = 0.95, include_ev = FALSE, ... )
fit_obj |
A |
factors_in_emm |
Character vector of factor names to compute EMMs over.
Defaults to all factors present in the |
at |
Optional named list specifying levels of conditioning variables for |
ci_level |
Confidence level for the EMMs (default 0.95).
Passed to |
include_ev |
Logical. If TRUE, calculates and includes Essential Value (EV)
derived from alpha. Passed to |
... |
Additional arguments passed to |
A tibble similar to the output of get_demand_param_emms, but filtered
to include only rows corresponding to factor level combinations that were
observed in the original fit_obj$data. Contains:
Factor levels |
Columns for each factor in |
Q0_param_log10, alpha_param_log10
|
EMMs for model parameters (log10 scale) and CIs. |
Q0_natural, alpha_natural
|
EMMs back-transformed to natural scale and CIs. |
EV, LCL_EV, UCL_EV
|
(If |
data(ko, package = "beezdemand") ko$y_ll4 <- ll4(ko$y, lambda = 4) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") get_observed_demand_param_emms(fit)data(ko, package = "beezdemand") ko$y_ll4 <- ll4(ko$y, lambda = 4) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", factors = "dose", equation_form = "zben") get_observed_demand_param_emms(fit)
Convenience function to extract subject-specific demand parameters from
a fitted hurdle demand model. Equivalent to accessing object$subject_pars.
get_subject_pars(object)get_subject_pars(object)
object |
A fitted |
Data frame with subject-specific parameters including:
Subject identifier
Random effect for Part I (zeros)
Random effect for Part II (Q0)
Random effect for alpha (3-RE model only)
Subject-specific intensity (consumption at price 0)
Subject-specific elasticity
Price where P(quit) = 0.5
Price at maximum expenditure
Maximum expenditure
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") pars <- get_subject_pars(fit) head(pars)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") pars <- get_subject_pars(fit) head(pars)
...
GetAnalyticPmax(Alpha, K, Q0)GetAnalyticPmax(Alpha, K, Q0)
Alpha |
alpha parameter |
K |
k parameter ( > lower limit ) |
Q0 |
Q0 |
...
Numeric
Shawn Gilroy [email protected]
GetAnalyticPmax(Alpha = 0.001, K = 3, Q0 = 10)GetAnalyticPmax(Alpha = 0.001, K = 3, Q0 = 10)
Fallback method for Analytic Pmax
GetAnalyticPmaxFallback(K_, A_, Q0_)GetAnalyticPmaxFallback(K_, A_, Q0_)
K_ |
k parameter |
A_ |
alpha parameter |
Q0_ |
q0 parameter |
Derivative-based optimization strategy
numeric
Shawn Gilroy [email protected]
GetAnalyticPmaxFallback(K_ = 1, A_ = 0.001, Q0_ = 10)GetAnalyticPmaxFallback(K_ = 1, A_ = 0.001, Q0_ = 10)
Calculates descriptive statistics from purchase task data.
GetDescriptives( dat, bwplot = FALSE, outdir = "../plots/", device = "png", filename = "bwplot" )GetDescriptives( dat, bwplot = FALSE, outdir = "../plots/", device = "png", filename = "bwplot" )
dat |
Dataframe (long form) |
bwplot |
Boolean. If TRUE, a ggplot2 box and whisker plot is saved. Default is FALSE. |
outdir |
Character. Directory where plot will be saved. Be sure to include trailing '/'. Default location is one level up in "../plots/". |
device |
Character. Type of file. Default is "png". Can be "pdf". |
filename |
Character. Specify filename. Defualt is "bwplot". |
GetDescriptives() has been superseded by get_descriptive_summary(), which
provides a modern S3 interface with standardized methods (print(), summary(), plot()).
GetDescriptives() will continue to work but is no longer recommended for new code.
Provides the following descriptive statistics from purchase task data at each price: mean consumption, median consumption, standard deviation of consumption, proportion of 0 values, number of NAs, minimum consumption, and maximum consumption.
Dataframe with descriptive statistics
Brent Kaplan [email protected]
get_descriptive_summary() for the modern interface
GetDescriptives(apt)GetDescriptives(apt)
Calculates empirical measures for purchase task data
GetEmpirical(dat, xcol = "x", ycol = "y", idcol = "id")GetEmpirical(dat, xcol = "x", ycol = "y", idcol = "id")
dat |
data frame (long form) of purchase task data. |
xcol |
The column name that should be treated as "x" data |
ycol |
The column name that should be treated as "y" data |
idcol |
The column name that should be treated as dataset identifier |
GetEmpirical() has been superseded by get_empirical_measures(), which
provides a modern S3 interface with standardized methods (print(), summary(), plot()).
GetEmpirical() will continue to work but is no longer recommended for new code.
Will calculate and return the following empirical measures: Intensity, BP0, BP1, Omax, and Pmax
Data frame of empirical measures
Brent Kaplan [email protected]
get_empirical_measures() for the modern interface
## Obtain empirical measures GetEmpirical(apt)## Obtain empirical measures GetEmpirical(apt)
Calculates a k value by looking for the max/min consumption across entire dataset and adds .5 to that range
GetK(dat, mnrange = TRUE)GetK(dat, mnrange = TRUE)
dat |
Dataframe (long form) |
mnrange |
Boolean for whether k should be calculated based on the mean range + .5 |
GetK() has been superseded by get_k(), which provides explicit parameters
for the adjustment value and optional verbose output for better transparency.
GetK() will continue to work but is no longer recommended for new code.
Will look for maximum/minimum greater zero
Numeric
Brent Kaplan [email protected]
get_k() for the modern interface
GetK(apt)GetK(apt)
Gets values used in SimulateDemand
GetValsForSim(dat)GetValsForSim(dat)
dat |
Dataframe (long form) |
Gets values used in SimulateDemand
List of 3: setaparams, sdindex, x
Brent Kaplan [email protected]
GetValsForSim(apt)GetValsForSim(apt)
Glance Method for beezdemand_fixed
## S3 method for class 'beezdemand_fixed' glance(x, ...)## S3 method for class 'beezdemand_fixed' glance(x, ...)
x |
A beezdemand_fixed object |
... |
Additional arguments (ignored) |
A one-row tibble of model statistics
Returns a one-row tibble of model-level statistics.
## S3 method for class 'beezdemand_hurdle' glance(x, ...)## S3 method for class 'beezdemand_hurdle' glance(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
A one-row tibble with columns:
"beezdemand_hurdle"
"TMB"
Number of observations
Number of subjects
Number of random effects
Convergence status
Log-likelihood
Akaike Information Criterion
Bayesian Information Criterion
Glance method for beezdemand_nlme
## S3 method for class 'beezdemand_nlme' glance(x, ...)## S3 method for class 'beezdemand_nlme' glance(x, ...)
x |
A beezdemand_nlme object |
... |
Additional arguments (ignored) |
A one-row tibble of model statistics with columns:
model_class: "beezdemand_nlme"
backend: "nlme"
equation_form: The equation form used
nobs: Number of observations
n_subjects: Number of subjects
converged: Convergence status
logLik, AIC, BIC: Model fit statistics
sigma: Residual standard error
Glance Method for beezdemand_systematicity
## S3 method for class 'beezdemand_systematicity' glance(x, ...)## S3 method for class 'beezdemand_systematicity' glance(x, ...)
x |
A beezdemand_systematicity object |
... |
Additional arguments (ignored) |
A one-row tibble of overall statistics
Get model summaries from a linear cross-price model
## S3 method for class 'cp_model_lm' glance(x, ...)## S3 method for class 'cp_model_lm' glance(x, ...)
x |
A cp_model_lm object. |
... |
Additional arguments (unused). |
A tibble with model summary statistics.
Get model summaries from a mixed-effects cross-price model
## S3 method for class 'cp_model_lmer' glance(x, ...)## S3 method for class 'cp_model_lmer' glance(x, ...)
x |
A cp_model_lmer object. |
... |
Additional arguments passed to broom.mixed::glance. |
A tibble with model summary statistics.
This function extracts model summary statistics from a cross-price demand model into a single-row data frame, following the conventions of the broom package. It returns goodness-of-fit measures and other model information.
## S3 method for class 'cp_model_nls' glance(x, ...)## S3 method for class 'cp_model_nls' glance(x, ...)
x |
A model object from fit_cp_nls or fit_cp_linear |
... |
Additional arguments (unused) |
A one-row data frame with model summary statistics:
r.squared |
R-squared value indicating model fit |
aic |
Akaike Information Criterion |
bic |
Bayesian Information Criterion |
equation |
The equation type used in the model |
method |
The method used to fit the model |
transform |
The transformation applied to the data, if any |
data(etm) fit <- fit_cp_nls(etm, equation = "exponentiated") glance(fit)data(etm) fit <- fit_cp_nls(etm, equation = "exponentiated") glance(fit)
Data from Ko et al. (2002)
koko
A tibble with 135 rows and 6 columns:
unique identifier
fixed-ratio requirement
consumption
consumption transformed via ll4
drug
dose
Ben Bolker's port of Lambert W from GNU Scientific Library (GPLV3)
lambertW(z, b = 0, maxiter = 10, eps = .Machine$double.eps, min.imag = 1e-09)lambertW(z, b = 0, maxiter = 10, eps = .Machine$double.eps, min.imag = 1e-09)
z |
input value |
b |
branch, set to principal by default |
maxiter |
Halley iteration count |
eps |
error precision |
min.imag |
minimum for imaginary solution |
Ben Bolker's port of Lambert W from GNU Scientific Library
numeric
Benjamin Bolker (port)
## Principal branch: W(1) ~ 0.5671 lambertW(1) ## Verify: W(z) * exp(W(z)) == z w <- lambertW(2) w * exp(w)## Principal branch: W(1) ~ 0.5671 lambertW(1) ## Verify: W(z) * exp(W(z)) == z w <- lambertW(2) w * exp(w)
Applies a log-logistic like transformation, specifically log_base(x^lambda + 1) / lambda.
This transformation is useful for compressing data that spans several orders of
magnitude while handling zero values gracefully (as x=0 yields 0).
It's a variation related to the Box-Cox transformation or a generalized logarithm.
ll4(x, lambda = 4, base = 10)ll4(x, lambda = 4, base = 10)
x |
A numeric vector or scalar of non-negative values to be transformed. |
lambda |
A positive numeric scalar, the lambda parameter of the transformation.
Controls the curvature. Default is |
base |
A positive numeric scalar, the base of the logarithm. Default is |
A numeric vector or scalar of the transformed values.
Returns NaN for x < 0 if lambda results in non-real numbers (e.g., even root of negative).
However, the intended domain is x >= 0.
ll4(0) ll4(1) ll4(10) ll4(100) ll4(c(0, 1, 10, 100, 1000)) # Using a different lambda or base ll4(10, lambda = 2) ll4(10, base = exp(1)) # Natural log basell4(0) ll4(1) ll4(10) ll4(100) ll4(c(0, 1, 10, 100, 1000)) # Using a different lambda or base ll4(10, lambda = 2) ll4(10, base = exp(1)) # Natural log base
Applies the inverse of the ll4 transformation.
Given y = ll4(x), this function calculates x = (base^(y * lambda) - 1)^(1/lambda).
ll4_inv(y, lambda = 4, base = 10)ll4_inv(y, lambda = 4, base = 10)
y |
A numeric vector or scalar of transformed values (output from |
lambda |
A positive numeric scalar, the lambda parameter used in the original
|
base |
A positive numeric scalar, the base of the logarithm used in the
original |
A numeric vector or scalar of the original, untransformed values.
May return NaN if (base^(y * lambda) - 1) is negative and 1/lambda implies
an even root (e.g., if lambda is 2 or 4).
original_values <- c(0, 1, 10, 100, 1000) transformed_values <- ll4(original_values) back_transformed_values <- ll4_inv(transformed_values) print(data.frame(original_values, transformed_values, back_transformed_values)) all.equal(original_values, back_transformed_values) # Should be TRUE or very close # Example with negative y (log-transformed value) # If y_ll4 = -0.5 (meaning original value was between 0 and 1 for log10) ll4_inv(-0.5, lambda = 4, base = 10) # (10^(-0.5*4) - 1)^(1/4) = (0.01 - 1)^(1/4) -> NaN # The ll4_inv function as provided will return NaN here. # A more robust version for demand might floor at 0 if NaN occurs.original_values <- c(0, 1, 10, 100, 1000) transformed_values <- ll4(original_values) back_transformed_values <- ll4_inv(transformed_values) print(data.frame(original_values, transformed_values, back_transformed_values)) all.equal(original_values, back_transformed_values) # Should be TRUE or very close # Example with negative y (log-transformed value) # If y_ll4 = -0.5 (meaning original value was between 0 and 1 for log10) ll4_inv(-0.5, lambda = 4, base = 10) # (10^(-0.5*4) - 1)^(1/4) = (0.01 - 1)^(1/4) -> NaN # The ll4_inv function as provided will return NaN here. # A more robust version for demand might floor at 0 if NaN occurs.
Extracts the log-likelihood from a fitted hurdle demand model. Useful for likelihood ratio tests comparing nested models.
## S3 method for class 'beezdemand_hurdle' logLik(object, ...)## S3 method for class 'beezdemand_hurdle' logLik(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
An object of class logLik with the log-likelihood value
and attributes for degrees of freedom and number of observations.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") logLik(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") logLik(fit)
Long-form purchase task data across nicotine conditions.
lowNicCleanlowNicClean
A data frame with 5 columns: id, condition, x, y, commodity.
# data(lowNicClean)# data(lowNicClean)
ETM data across price points with product quantities.
ongoingETMongoingETM
A data frame with 6 columns: id, x, AdjCig, FixCig, ECig, flavor.
# data(ongoingETM)# data(ongoingETM)
beezdemand Color Palette
palette_beezdemand()palette_beezdemand()
Named vector of brand colors.
palette_beezdemand()palette_beezdemand()
Converts demand data between wide format (one row per subject,
prices as columns) and long format (one row per observation with id, x,
y columns). This is a convenience wrapper around tidyr::pivot_longer()
and tidyr::pivot_wider() tailored for behavioral economic purchase task
data.
pivot_demand_data( data, format = c("long", "wide"), id_var = "id", x_var = "x", y_var = "y", price_cols = NULL, x_values = NULL, drop_na = TRUE )pivot_demand_data( data, format = c("long", "wide"), id_var = "id", x_var = "x", y_var = "y", price_cols = NULL, x_values = NULL, drop_na = TRUE )
data |
A data frame or tibble to reshape. |
format |
Character. Direction of reshaping: |
id_var |
Character. Name of the subject/series identifier column.
Default |
x_var |
Character. Name of the price column in long-format data. Used
when |
y_var |
Character. Name of the consumption column in long-format data.
Used when |
price_cols |
Character vector of column names in wide-format data that
represent prices. Used when |
x_values |
Numeric vector of actual price values corresponding to each
price column in wide-format data. Used when |
drop_na |
Logical. When |
format = "long")The function determines which columns are price columns by:
If price_cols is provided, those columns are used directly.
If price_cols is NULL, column names are tested with as.numeric().
Columns whose names successfully parse as numbers (e.g., "0", "0.5",
"10") are treated as price columns. Remaining non-id_var columns are
preserved as extra identifiers.
If no column names parse as numeric, all non-id_var columns become price
columns and x_values must be supplied.
Actual numeric price values come from x_values if supplied, or from parsing
column names. If column names cannot be parsed and x_values is not supplied,
an error is raised.
format = "wide")Pivots long data so that each unique value in x_var becomes a column, with
values from y_var. All columns except x_var and y_var are used as
identifiers.
A tibble. When format = "long": columns id, any extra identifier
columns, x (numeric price), and y (numeric consumption). When
format = "wide": one row per subject with prices as column names.
# --- Wide to long --- # Columns named as prices (auto-parsed) wide_num <- data.frame( id = 1:3, "0" = c(10, 8, 12), "0.5" = c(9, 7, 11), "1" = c(8, 6, 9), check.names = FALSE ) pivot_demand_data(wide_num, format = "long") # Columns with non-numeric names require x_values wide_named <- data.frame(id = 1:2, price_1 = c(10, 8), price_2 = c(5, 4)) pivot_demand_data(wide_named, format = "long", x_values = c(0, 0.5)) # --- Long to wide --- data(apt, package = "beezdemand") wide_apt <- pivot_demand_data(apt, format = "wide") head(wide_apt)# --- Wide to long --- # Columns named as prices (auto-parsed) wide_num <- data.frame( id = 1:3, "0" = c(10, 8, 12), "0.5" = c(9, 7, 11), "1" = c(8, 6, 9), check.names = FALSE ) pivot_demand_data(wide_num, format = "long") # Columns with non-numeric names require x_values wide_named <- data.frame(id = 1:2, price_1 = c(10, 8), price_2 = c(5, 4)) pivot_demand_data(wide_named, format = "long", x_values = c(0, 0.5)) # --- Long to wide --- data(apt, package = "beezdemand") wide_apt <- pivot_demand_data(apt, format = "wide") head(wide_apt)
Creates Q-Q plots for random effects to assess normality assumptions.
plot_qq(object, which = NULL, ...) ## S3 method for class 'beezdemand_hurdle' plot_qq(object, which = NULL, ...) ## S3 method for class 'beezdemand_nlme' plot_qq(object, which = NULL, ...)plot_qq(object, which = NULL, ...) ## S3 method for class 'beezdemand_hurdle' plot_qq(object, which = NULL, ...) ## S3 method for class 'beezdemand_nlme' plot_qq(object, which = NULL, ...)
object |
A fitted model object with random effects ( |
which |
Character vector; which random effects to plot. Default is all. |
... |
Additional arguments (ignored). |
A ggplot2 object.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") plot_qq(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") plot_qq(fit)
Creates diagnostic plots for model residuals including residuals vs fitted, scale-location, and histogram of residuals.
plot_residuals(object, type = c("all", "fitted", "histogram", "qq"), ...)plot_residuals(object, type = c("all", "fitted", "histogram", "qq"), ...)
object |
A fitted model object. |
type |
Character; type of residual plot. One of:
|
... |
Additional arguments passed to plotting functions. |
A ggplot2 object or list of ggplot2 objects.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") plot_residuals(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") plot_residuals(fit)
Creates a demand curve plot for a single subject with optional observed data and population reference curve.
plot_subject( object, subject_id, prices = NULL, show_data = TRUE, show_population = TRUE, style = c("modern", "apa") )plot_subject( object, subject_id, prices = NULL, show_data = TRUE, show_population = TRUE, style = c("modern", "apa") )
object |
An object of class |
subject_id |
The ID of the subject to plot. |
prices |
Numeric vector of prices for plotting. If |
show_data |
Logical; if |
show_population |
Logical; if |
style |
Plot styling, passed to |
A ggplot2 object.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") plot_subject(fit, subject_id = "19")data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") plot_subject(fit, subject_id = "19")
Central plotting style API for beezdemand, with a modern default based on the codedbx "Refined Contemporary" brand and an APA alternative.
Plot Method for beezdemand_fixed
## S3 method for class 'beezdemand_fixed' plot( x, type = c("demand", "population", "individual", "both"), ids = NULL, style = c("modern", "apa"), show_observed = TRUE, show_pred = NULL, x_trans = c("log10", "log", "linear", "pseudo_log"), y_trans = NULL, free_trans = 0.01, x_limits = NULL, y_limits = NULL, n_points = 200, x_lab = NULL, y_lab = NULL, xlab = NULL, ylab = NULL, facet = NULL, observed_point_alpha = 0.5, observed_point_size = 1.8, pop_line_alpha = 0.9, pop_line_size = 1, ind_line_alpha = 0.35, ind_line_size = 0.7, subtitle = NULL, ... )## S3 method for class 'beezdemand_fixed' plot( x, type = c("demand", "population", "individual", "both"), ids = NULL, style = c("modern", "apa"), show_observed = TRUE, show_pred = NULL, x_trans = c("log10", "log", "linear", "pseudo_log"), y_trans = NULL, free_trans = 0.01, x_limits = NULL, y_limits = NULL, n_points = 200, x_lab = NULL, y_lab = NULL, xlab = NULL, ylab = NULL, facet = NULL, observed_point_alpha = 0.5, observed_point_size = 1.8, pop_line_alpha = 0.9, pop_line_size = 1, ind_line_alpha = 0.35, ind_line_size = 0.7, subtitle = NULL, ... )
x |
A beezdemand_fixed object. |
type |
Plot type: "demand", "population", "individual", or "both". |
ids |
Optional vector of subject IDs to plot. Defaults to all subjects. |
style |
Plot styling, passed to |
show_observed |
Logical; if TRUE, overlay observed data points where possible. |
show_pred |
Which prediction layers to plot: "population", "individual", or "both". |
x_trans |
X-axis transform: "log", "log10", "linear", or "pseudo_log". |
y_trans |
Y-axis transform: "log", "log10", "linear", or "pseudo_log". |
free_trans |
Value used to display free (x = 0) on log scales. Use NULL to drop x <= 0 values instead. |
x_limits |
Optional numeric vector of length 2 for x-axis limits. |
y_limits |
Optional numeric vector of length 2 for y-axis limits. |
n_points |
Number of points to use for prediction curves when thinning. |
x_lab |
Optional x-axis label. |
y_lab |
Optional y-axis label. |
xlab |
Deprecated alias for |
ylab |
Deprecated alias for |
facet |
Faceting specification (TRUE for |
observed_point_alpha |
Alpha for observed points. |
observed_point_size |
Size for observed points. |
pop_line_alpha |
Alpha for population curve. |
pop_line_size |
Line size for population curve. |
ind_line_alpha |
Alpha for individual curves. |
ind_line_size |
Line size for individual curves. |
subtitle |
Optional subtitle for the plot. |
... |
Additional arguments (currently unused). |
A ggplot2 object.
Creates visualizations of fitted demand curves from a hurdle demand model.
## S3 method for class 'beezdemand_hurdle' plot( x, type = c("demand", "population", "probability", "parameters", "individual", "both"), ids = NULL, subjects = NULL, parameters = c("Q0", "alpha", "breakpoint", "Pmax", "Omax"), prices = NULL, show_population = TRUE, show_pred = NULL, show_observed = TRUE, x_trans = c("log10", "log", "linear", "pseudo_log"), y_trans = NULL, free_trans = 0.01, facet = NULL, x_limits = NULL, y_limits = NULL, x_lab = NULL, y_lab = NULL, xlab = NULL, ylab = NULL, style = c("modern", "apa"), observed_point_alpha = 0.5, observed_point_size = 1.8, pop_line_alpha = 0.9, pop_line_size = 1, ind_line_alpha = 0.35, ind_line_size = 0.7, ... )## S3 method for class 'beezdemand_hurdle' plot( x, type = c("demand", "population", "probability", "parameters", "individual", "both"), ids = NULL, subjects = NULL, parameters = c("Q0", "alpha", "breakpoint", "Pmax", "Omax"), prices = NULL, show_population = TRUE, show_pred = NULL, show_observed = TRUE, x_trans = c("log10", "log", "linear", "pseudo_log"), y_trans = NULL, free_trans = 0.01, facet = NULL, x_limits = NULL, y_limits = NULL, x_lab = NULL, y_lab = NULL, xlab = NULL, ylab = NULL, style = c("modern", "apa"), observed_point_alpha = 0.5, observed_point_size = 1.8, pop_line_alpha = 0.9, pop_line_size = 1, ind_line_alpha = 0.35, ind_line_size = 0.7, ... )
x |
An object of class |
type |
Character string specifying the plot type:
|
ids |
Optional vector of subject IDs to plot (alias of |
subjects |
Character or numeric vector of subject IDs to plot for
|
parameters |
Character vector specifying which parameters to plot when
|
prices |
Numeric vector of prices for plotting. If |
show_population |
Logical; if |
show_pred |
Which prediction layers to plot: "population", "individual", or "both". |
show_observed |
Logical; if |
x_trans |
Character. Transformation for x-axis. Default "log". |
y_trans |
Character. Transformation for y-axis. Default "log". |
free_trans |
Value used to display free (x = 0) on log scales. Use NULL to drop x <= 0 values instead. |
facet |
Faceting specification (TRUE for |
x_limits |
Optional numeric vector of length 2 for x-axis limits. |
y_limits |
Optional numeric vector of length 2 for y-axis limits. |
x_lab |
Optional x-axis label. |
y_lab |
Optional y-axis label. |
xlab |
Deprecated alias for |
ylab |
Deprecated alias for |
style |
Plot styling, passed to |
observed_point_alpha |
Alpha for observed points. |
observed_point_size |
Size for observed points. |
pop_line_alpha |
Alpha for population curve. |
pop_line_size |
Line size for population curve. |
ind_line_alpha |
Alpha for individual curves. |
ind_line_size |
Line size for individual curves. |
... |
Additional arguments (currently unused). |
A ggplot2 object.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") # Plot mean demand curve plot(fit) # Plot parameter distributions plot(fit, type = "parameters")data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") # Plot mean demand curve plot(fit) # Plot parameter distributions plot(fit, type = "parameters")
Creates a ggplot2 visualization of a fitted beezdemand_nlme model,
showing observed data points and/or model prediction lines.
## S3 method for class 'beezdemand_nlme' plot( x, type = c("demand", "population", "individual", "both"), ids = NULL, show_observed = TRUE, observed_point_alpha = 0.6, show_pred = "population", n_points = 200, inv_fun = identity, facet = NULL, at = NULL, color_by = NULL, linetype_by = NULL, shape_by = NULL, x_trans = c("log10", "log", "linear", "pseudo_log"), y_trans = NULL, free_trans = 0.01, x_limits = NULL, y_limits = NULL, style = c("modern", "apa"), title = NULL, subtitle = NULL, x_lab = NULL, y_lab = NULL, xlab = NULL, ylab = NULL, observed_point_size = 2, pop_line_size = 1, ind_line_size = 0.6, pop_line_alpha = 0.9, ind_line_alpha = 0.3, ... )## S3 method for class 'beezdemand_nlme' plot( x, type = c("demand", "population", "individual", "both"), ids = NULL, show_observed = TRUE, observed_point_alpha = 0.6, show_pred = "population", n_points = 200, inv_fun = identity, facet = NULL, at = NULL, color_by = NULL, linetype_by = NULL, shape_by = NULL, x_trans = c("log10", "log", "linear", "pseudo_log"), y_trans = NULL, free_trans = 0.01, x_limits = NULL, y_limits = NULL, style = c("modern", "apa"), title = NULL, subtitle = NULL, x_lab = NULL, y_lab = NULL, xlab = NULL, ylab = NULL, observed_point_size = 2, pop_line_size = 1, ind_line_size = 0.6, pop_line_alpha = 0.9, ind_line_alpha = 0.3, ... )
x |
A |
type |
Plot type: "demand", "population", "individual", or "both". |
ids |
Optional vector of subject IDs to plot. |
show_observed |
Logical. If TRUE, plots the original data points. Default |
observed_point_alpha |
Alpha for observed points. Default |
show_pred |
Which prediction layers to plot: "population", "individual", or "both". |
n_points |
Integer. Number of points for prediction lines. Default |
inv_fun |
Optional function to inverse-transform y-axis and predictions. Default |
facet |
Optional faceting formula (e.g., |
at |
Optional named list giving values for continuous covariates used in the fixed-effects RHS. When building prediction grids for population- or individual- level lines, these values will be used. If not provided, the function will default to the median of each continuous covariate found in the original model data. Factor variables are always handled as grids (population) or observed combinations (individual) as before. |
color_by |
Optional character string: name of a factor to color lines and/or points by.
Must be a column in |
linetype_by |
Optional character string: name of a factor for linetypes of population prediction lines
if individual lines are also shown (otherwise applies to the shown lines).
Must be a model factor in |
shape_by |
Optional character string: name of a factor for shapes of observed points.
Must be a column in |
x_trans |
Character. Transformation for x-axis. Default "log". |
y_trans |
Character. Transformation for y-axis. Default "log". |
free_trans |
Value used to display free (x = 0) on log scales. Use NULL to drop x <= 0 values instead. |
x_limits |
Optional numeric vector of length 2 for x-axis limits. |
y_limits |
Optional numeric vector of length 2 for y-axis limits. |
style |
Plot styling, passed to |
title |
Optional plot title. |
subtitle |
Optional subtitle for the plot. |
x_lab |
Optional x-axis label. |
y_lab |
Optional y-axis label. |
xlab |
Deprecated alias for |
ylab |
Deprecated alias for |
observed_point_size |
Size for observed points. Default |
pop_line_size |
Size for population prediction lines. Default |
ind_line_size |
Size for individual prediction lines. Default |
pop_line_alpha |
Alpha for population prediction lines. Default |
ind_line_alpha |
Alpha for individual prediction lines. Default |
... |
Additional arguments (currently unused). |
A ggplot2 object.
Creates a ggplot2 visualization of a fitted linear cross-price demand model
(of class cp_model_lm). The plot overlays a prediction line over the
observed data points. Axis transformations (e.g., "log10") can be applied.
If the model includes group effects, separate lines will be drawn for each group.
## S3 method for class 'cp_model_lm' plot( x, data = NULL, inv_fun = identity, n_points = 100, title = NULL, xlab = "Price", ylab = "Consumption", x_trans = "identity", y_trans = "identity", point_size = 3, ... )## S3 method for class 'cp_model_lm' plot( x, data = NULL, inv_fun = identity, n_points = 100, title = NULL, xlab = "Price", ylab = "Consumption", x_trans = "identity", y_trans = "identity", point_size = 3, ... )
x |
A |
data |
Optional data frame containing columns |
inv_fun |
Optional function to inverse-transform predictions. Default is |
n_points |
Number of points to create in the prediction grid. Default is |
title |
Optional title for the plot; default is |
xlab |
Label for the x-axis. Default is |
ylab |
Label for the y-axis. Default is |
x_trans |
Transformation for the x-axis; one of |
y_trans |
Transformation for the y-axis; one of |
point_size |
Size of the data points in the plot. Default is |
... |
Additional arguments passed to the generic |
A ggplot2 object displaying the fitted model predictions and observed data.
Creates a ggplot2 visualization of a fitted mixed-effects cross-price demand model
(of class cp_model_lmer). This function allows you to plot:
## S3 method for class 'cp_model_lmer' plot( x, data = NULL, inv_fun = identity, n_points = 100, title = NULL, xlab = "Price", ylab = "Consumption", x_trans = "identity", y_trans = "identity", point_size = 3, pred_type = c("fixed", "random", "all"), ... )## S3 method for class 'cp_model_lmer' plot( x, data = NULL, inv_fun = identity, n_points = 100, title = NULL, xlab = "Price", ylab = "Consumption", x_trans = "identity", y_trans = "identity", point_size = 3, pred_type = c("fixed", "random", "all"), ... )
x |
A |
data |
Optional data frame containing columns |
inv_fun |
Optional function to inverse-transform predictions. Default is |
n_points |
Number of points to use in creating the prediction grid. Default is |
title |
Optional title for the plot; default is |
xlab |
Label for the x-axis. Default is |
ylab |
Label for the y-axis. Default is |
x_trans |
Transformation for the x-axis; one of |
y_trans |
Transformation for the y-axis; one of |
point_size |
Size of the observed data points. Default is |
pred_type |
Character string specifying which prediction components to plot:
The default is |
... |
Additional arguments passed to |
"fixed"Only the population-level (fixed-effects) prediction.
"random"Only the subject-specific predictions.
"all"Both: the fixed-effects and the subject-specific predictions.
If the model includes group effects, separate lines will be drawn for each group.
A ggplot2 object displaying the observed data points along with the prediction curves.
Plot a Cross-Price Demand Model (Nonlinear)
## S3 method for class 'cp_model_nls' plot( x, data = NULL, inv_fun = identity, n_points = 100, title = NULL, xlab = "Price", ylab = "Consumption", x_trans = "identity", y_trans = "identity", point_size = 3, inverse_fun = deprecated(), ... )## S3 method for class 'cp_model_nls' plot( x, data = NULL, inv_fun = identity, n_points = 100, title = NULL, xlab = "Price", ylab = "Consumption", x_trans = "identity", y_trans = "identity", point_size = 3, inverse_fun = deprecated(), ... )
x |
A cross-price model object from fit_cp_nls with return_all=TRUE. |
data |
Optional data frame with x and y; if NULL, uses object$data. |
inv_fun |
Optional function to inverse-transform predictions. Default is |
n_points |
Number of points used for prediction curve. |
title |
Optional plot title. |
xlab |
X-axis label. |
ylab |
Y-axis label. |
x_trans |
Transformation for x-axis: "identity", "log10", or "pseudo_log". |
y_trans |
Transformation for y-axis: "identity", "log10", or "pseudo_log". |
point_size |
Size of data points. |
inverse_fun |
|
... |
Additional arguments (passed to predict). |
A ggplot2 object.
Creates a single plot object
PlotCurve(adf, dfrow, newdats, yscale = "log", style = c("modern", "apa"))PlotCurve(adf, dfrow, newdats, yscale = "log", style = c("modern", "apa"))
adf |
Data frame (long form) of purchase task data. |
dfrow |
A row of results from FitCurves |
newdats |
A newdat dataframe from FitCurves |
yscale |
Scaling of y axis. Default is "log". Can also take "linear" |
style |
Plot styling, passed to |
Creates individual demand curves
ggplot2 graphical object
Shawn Gilroy [email protected]
## Creates a single plot from elements of an object created by FitCurves if (interactive()) { fc <- FitCurves(apt, "hs", k = 2, detailed = TRUE) PlotCurve(fc$adfs[[1]], fc$dfres[1, ], fc$newdats[[1]]) }## Creates a single plot from elements of an object created by FitCurves if (interactive()) { fc <- FitCurves(apt, "hs", k = 2, detailed = TRUE) PlotCurve(fc$adfs[[1]], fc$dfres[1, ], fc$newdats[[1]]) }
Creates plots
PlotCurves(dat, outdir = NULL, device = "png", ending = NULL, ask = TRUE, ...)PlotCurves(dat, outdir = NULL, device = "png", ending = NULL, ask = TRUE, ...)
dat |
FitCurves object with 4 elements (dfres, newdats, adfs, fits) |
outdir |
Directory where plots are saved |
device |
Type of file. Default is "png". Can be "pdf" |
ending |
Optional. Can specify to only plot through a certain number of datasets |
ask |
Can view plots one by one. If TRUE, plots will not save |
... |
Pass arguments to PlotCurve (for example yscale = c("log", "linear")) |
Creates and saves plots of individual demand curves
Nothing
Brent Kaplan [email protected], Shawn Gilroy [email protected]
## Interactively view plots from output from FitCurves if (interactive()) { fc <- FitCurves(apt, "hs", k = 2, detailed = TRUE) PlotCurves(fc, ask = TRUE) }## Interactively view plots from output from FitCurves if (interactive()) { fc <- FitCurves(apt, "hs", k = 2, detailed = TRUE) PlotCurves(fc, ask = TRUE) }
Predict Method for beezdemand_fixed
## S3 method for class 'beezdemand_fixed' predict( object, newdata = NULL, type = c("response", "link"), se.fit = FALSE, interval = c("none", "confidence"), level = 0.95, ... )## S3 method for class 'beezdemand_fixed' predict( object, newdata = NULL, type = c("response", "link"), se.fit = FALSE, interval = c("none", "confidence"), level = 0.95, ... )
object |
A |
newdata |
A data frame containing a price column matching the fitted
object's |
type |
One of |
se.fit |
Logical; if |
interval |
One of |
level |
Confidence level when |
... |
Unused. |
A tibble containing the original newdata columns, plus .fitted
and, when requested, .se.fit and .lower/.upper. If newdata does not
include an id column, predictions are returned for all subjects (cross
product of newdata × subjects) unless k is subject-specific (k = "ind").
Returns predictions from a fitted hurdle demand model.
## S3 method for class 'beezdemand_hurdle' predict( object, newdata = NULL, type = c("response", "link", "parameters", "probability", "demand"), prices = NULL, se.fit = FALSE, interval = c("none", "confidence"), level = 0.95, ... )## S3 method for class 'beezdemand_hurdle' predict( object, newdata = NULL, type = c("response", "link", "parameters", "probability", "demand"), prices = NULL, se.fit = FALSE, interval = c("none", "confidence"), level = 0.95, ... )
object |
An object of class |
newdata |
Optional data frame containing a price column matching the fitted
object's |
type |
One of:
|
prices |
Optional numeric vector of prices used only when |
se.fit |
Logical; if |
interval |
One of |
level |
Confidence level when |
... |
Unused. |
For type = "parameters", a tibble of subject-level parameters.
Otherwise, a tibble containing the newdata columns plus .fitted and
helper columns predicted_log_consumption, predicted_consumption,
prob_zero, and expected_consumption. When requested, .se.fit and
.lower/.upper are included.
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") # Get subject-specific parameters pars <- predict(fit, type = "parameters") # Predict demand at specific prices demand <- predict(fit, type = "demand", prices = c(0, 0.5, 1, 2, 5))data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") # Get subject-specific parameters pars <- predict(fit, type = "parameters") # Predict demand at specific prices demand <- predict(fit, type = "demand", prices = c(0, 0.5, 1, 2, 5))
Generates point predictions from a fitted beezdemand_nlme model.
Predictions can be made at the population level (fixed effects only) or
group/subject level (fixed + random effects). The output scale depends
on the equation_form used during model fitting and whether inv_fun is applied.
## S3 method for class 'beezdemand_nlme' predict( object, newdata = NULL, type = c("response", "link", "population", "individual"), level = 0, inv_fun = identity, se.fit = FALSE, interval = c("none", "confidence"), interval_level = 0.95, ... )## S3 method for class 'beezdemand_nlme' predict( object, newdata = NULL, type = c("response", "link", "population", "individual"), level = 0, inv_fun = identity, se.fit = FALSE, interval = c("none", "confidence"), interval_level = 0.95, ... )
object |
A |
newdata |
Optional data frame for which to make predictions.
Must contain |
type |
One of |
level |
Integer, prediction level for
Default is |
inv_fun |
Optional function to inverse-transform the predictions.
Example: If |
se.fit |
Logical; if |
interval |
One of |
interval_level |
Confidence level when |
... |
Additional arguments passed to |
A tibble containing the original newdata columns plus .fitted.
When requested, .se.fit and .lower/.upper are included (currently NA).
data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") # Population-level predictions preds <- predict(fit, level = 0) # Subject-level predictions preds_subj <- predict(fit, level = 1)data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") # Population-level predictions preds <- predict(fit, level = 0) # Subject-level predictions preds_subj <- predict(fit, level = 1)
Predict method for cp_model_lm objects.
## S3 method for class 'cp_model_lm' predict(object, newdata = NULL, ...)## S3 method for class 'cp_model_lm' predict(object, newdata = NULL, ...)
object |
A cp_model_lm object. |
newdata |
Data frame containing new x values. |
... |
Additional arguments. |
Data frame with predictions.
Generates predictions from a mixed-effects cross-price demand model (of class
cp_model_lmer). The function supports two modes:
## S3 method for class 'cp_model_lmer' predict(object, newdata = NULL, pred_type = c("fixed", "random"), ...)## S3 method for class 'cp_model_lmer' predict(object, newdata = NULL, pred_type = c("fixed", "random"), ...)
object |
A |
newdata |
A data frame containing at least an |
pred_type |
Character string specifying the type of prediction: either |
... |
Additional arguments passed to the underlying |
"fixed"Returns predictions based solely on the fixed-effects component
(using re.form = NA).
"random"Returns subject-specific predictions (fixed plus random effects)
(using re.form = NULL).
A data frame containing all columns of newdata plus a column y_pred
with the corresponding predictions.
data(etm) fit <- fit_cp_linear(etm, type = "mixed") new_prices <- data.frame(x = c(2, 4, 8, 16, 32, 64)) predict(fit, newdata = new_prices, pred_type = "fixed")data(etm) fit <- fit_cp_linear(etm, type = "mixed") new_prices <- data.frame(x = c(2, 4, 8, 16, 32, 64)) predict(fit, newdata = new_prices, pred_type = "fixed")
Predict from a Cross-Price Demand Model (Nonlinear)
## S3 method for class 'cp_model_nls' predict( object, newdata = NULL, inv_fun = identity, inverse_fun = deprecated(), ... )## S3 method for class 'cp_model_nls' predict( object, newdata = NULL, inv_fun = identity, inverse_fun = deprecated(), ... )
object |
A cross-price model object from fit_cp_nls with return_all=TRUE. |
newdata |
A data frame containing an 'x' column. |
inv_fun |
Optional inverse transformation function. Default is |
inverse_fun |
|
... |
Additional arguments. |
A data frame with x values and predicted y values.
Prints a formatted summary of Monte Carlo simulation results.
print_mc_summary(mc_results, digits = 3)print_mc_summary(mc_results, digits = 3)
mc_results |
Output from |
digits |
Number of digits to display. Default is 3. |
Invisibly returns the input mc_results object.
mc_results <- run_hurdle_monte_carlo(n_sim = 50, n_subjects = 100, seed = 123) print_mc_summary(mc_results)mc_results <- run_hurdle_monte_carlo(n_sim = 50, n_subjects = 100, seed = 123) print_mc_summary(mc_results)
Print Method for ANOVA Comparisons
## S3 method for class 'anova.beezdemand_hurdle' print(x, digits = 4, ...)## S3 method for class 'anova.beezdemand_hurdle' print(x, digits = 4, ...)
x |
An |
digits |
Number of significant digits to print. |
... |
Additional arguments (ignored). |
Invisibly returns the input object x.
Print method for beezdemand_comparison objects
## S3 method for class 'beezdemand_comparison' print(x, digits = 3, ...)## S3 method for class 'beezdemand_comparison' print(x, digits = 3, ...)
x |
A |
digits |
Number of significant digits to display for estimates. |
... |
Additional arguments (unused). |
Invisibly returns the input object x.
Print Method for Model Diagnostics
## S3 method for class 'beezdemand_diagnostics' print(x, ...)## S3 method for class 'beezdemand_diagnostics' print(x, ...)
x |
A |
... |
Additional arguments (ignored). |
Invisibly returns the input object x.
Print Method for beezdemand_fixed
## S3 method for class 'beezdemand_fixed' print(x, ...)## S3 method for class 'beezdemand_fixed' print(x, ...)
x |
A beezdemand_fixed object |
... |
Additional arguments (ignored) |
Invisibly returns the input object x.
Print Method for Hurdle Demand Model
## S3 method for class 'beezdemand_hurdle' print(x, ...)## S3 method for class 'beezdemand_hurdle' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
Invisibly returns the input object x.
Print Method for Model Comparison
## S3 method for class 'beezdemand_model_comparison' print(x, digits = 4, ...)## S3 method for class 'beezdemand_model_comparison' print(x, digits = 4, ...)
x |
A |
digits |
Number of significant digits to print. |
... |
Additional arguments (ignored). |
Invisibly returns the input object x.
Provides a concise summary of a beezdemand_nlme object, typically
displaying the call, model specifications, and key results from the
nlme fit if successful.
## S3 method for class 'beezdemand_nlme' print(x, digits = max(3L, getOption("digits") - 3L), ...)## S3 method for class 'beezdemand_nlme' print(x, digits = max(3L, getOption("digits") - 3L), ...)
x |
An object of class |
digits |
Minimal number of significant digits, see |
... |
Additional arguments passed to |
Invisibly returns the original object x.
data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") print(fit)data(ko) fit <- fit_demand_mixed(ko, y_var = "y_ll4", x_var = "x", id_var = "monkey", equation_form = "zben") print(fit)
Fallback print method for summary objects inheriting from beezdemand_summary.
Specific summary classes should implement their own print.summary.* methods
for detailed output; this provides a minimal fallback.
## S3 method for class 'beezdemand_summary' print(x, ...)## S3 method for class 'beezdemand_summary' print(x, ...)
x |
A summary object with class including |
... |
Additional arguments (unused). |
Invisibly returns x.
Print Method for beezdemand_systematicity
## S3 method for class 'beezdemand_systematicity' print(x, ...)## S3 method for class 'beezdemand_systematicity' print(x, ...)
x |
A beezdemand_systematicity object |
... |
Additional arguments (ignored) |
Invisibly returns the input object x.
Print method for cp_posthoc objects
## S3 method for class 'cp_posthoc' print(x, ...)## S3 method for class 'cp_posthoc' print(x, ...)
x |
A cp_posthoc object |
... |
Additional arguments passed to print |
Invisibly returns the input object x.
Print Method for summary.beezdemand_fixed
## S3 method for class 'summary.beezdemand_fixed' print(x, digits = 4, n = 20, ...)## S3 method for class 'summary.beezdemand_fixed' print(x, digits = 4, n = 20, ...)
x |
A summary.beezdemand_fixed object |
digits |
Number of significant digits to print |
n |
Number of subjects (ids) to print (default 20) |
... |
Additional arguments (ignored) |
Invisibly returns the input object x.
Print Summary of Hurdle Demand Model
## S3 method for class 'summary.beezdemand_hurdle' print(x, digits = 4, n = Inf, ...)## S3 method for class 'summary.beezdemand_hurdle' print(x, digits = 4, n = Inf, ...)
x |
An object of class |
digits |
Number of significant digits to print. Default is 4. |
n |
Number of rows to print for any tables (unused for this class). |
... |
Additional arguments passed to |
Invisibly returns the input object x.
Print method for summary.beezdemand_nlme
## S3 method for class 'summary.beezdemand_nlme' print(x, digits = 4, n = Inf, ...)## S3 method for class 'summary.beezdemand_nlme' print(x, digits = 4, n = Inf, ...)
x |
A summary.beezdemand_nlme object |
digits |
Number of significant digits to print |
n |
Number of rows to print for any tables (unused for this class). |
... |
Additional arguments (ignored) |
Invisibly returns the input object x.
Print Method for summary.beezdemand_systematicity
## S3 method for class 'summary.beezdemand_systematicity' print(x, n = 20, ...)## S3 method for class 'summary.beezdemand_systematicity' print(x, n = 20, ...)
x |
A summary.beezdemand_systematicity object |
n |
Number of IDs to display (default 20) |
... |
Additional arguments (ignored) |
Invisibly returns the input object x.
Print method for summary.cp_model_lm objects.
## S3 method for class 'summary.cp_model_lm' print(x, ...)## S3 method for class 'summary.cp_model_lm' print(x, ...)
x |
A |
... |
Unused |
Invisibly returns the input object x.
Print method for summary.cp_model_lmer objects.
## S3 method for class 'summary.cp_model_lmer' print(x, ...)## S3 method for class 'summary.cp_model_lmer' print(x, ...)
x |
A |
... |
Unused |
Invisibly returns the input object x.
Print method for summary.cp_model_nls objects
## S3 method for class 'summary.cp_model_nls' print(x, ...)## S3 method for class 'summary.cp_model_nls' print(x, ...)
x |
A |
... |
Unused |
Invisibly returns the input object x.
Print Method for summary.cp_unsystematic
## S3 method for class 'summary.cp_unsystematic' print(x, ...)## S3 method for class 'summary.cp_unsystematic' print(x, ...)
x |
A |
... |
Additional arguments (ignored). |
Invisibly returns the input object x.
Generates a scales::trans object using the ll4 transformation.
This transformation object can be passed to the trans argument of
ggplot2::scale_x_continuous or ggplot2::scale_y_continuous.
It's designed for non-negative data and handles zero values gracefully.
The "pseudo" aspect is conceptual, similar to pseudo_log_trans in that it
handles a range including zero, but the transformation is ll4.
pseudo_ll4_trans(lambda = 4)pseudo_ll4_trans(lambda = 4)
lambda |
A positive numeric scalar, the lambda parameter for the |
A trans object (from the scales package).
if (require(ggplot2) && require(scales)) { set.seed(123) df <- data.frame( x_vals = c(0, 0.01, 0.1, 1, 10, 100, 1000, NA), # Include 0 and NA y_vals = c(0, 10, 50, 100, 500, 1000, 2000, 50) ) # Using pseudo_ll4_trans for the y-axis ggplot(df, aes(x = x_vals, y = y_vals)) + geom_point() + scale_y_continuous(trans = pseudo_ll4_trans(lambda = 4), name = "Y-Values (Pseudo-LL4 Scale)") + ggtitle("Y-Axis with Pseudo-LL4 Transformation") # Using pseudo_ll4_trans for the x-axis ggplot(df, aes(x = x_vals, y = y_vals)) + geom_point() + scale_x_continuous(trans = pseudo_ll4_trans(lambda = 2), # Different lambda name = "X-Values (Pseudo-LL4 Scale)") + ggtitle("X-Axis with Pseudo-LL4 Transformation") }if (require(ggplot2) && require(scales)) { set.seed(123) df <- data.frame( x_vals = c(0, 0.01, 0.1, 1, 10, 100, 1000, NA), # Include 0 and NA y_vals = c(0, 10, 50, 100, 500, 1000, 2000, 50) ) # Using pseudo_ll4_trans for the y-axis ggplot(df, aes(x = x_vals, y = y_vals)) + geom_point() + scale_y_continuous(trans = pseudo_ll4_trans(lambda = 4), name = "Y-Values (Pseudo-LL4 Scale)") + ggtitle("Y-Axis with Pseudo-LL4 Transformation") # Using pseudo_ll4_trans for the x-axis ggplot(df, aes(x = x_vals, y = y_vals)) + geom_point() + scale_x_continuous(trans = pseudo_ll4_trans(lambda = 2), # Different lambda name = "X-Values (Pseudo-LL4 Scale)") + ggtitle("X-Axis with Pseudo-LL4 Transformation") }
S3 method for ranef for objects of class beezdemand_nlme.
Extracts the random effects from the fitted nlme model.
## S3 method for class 'beezdemand_nlme' ranef(object, ...)## S3 method for class 'beezdemand_nlme' ranef(object, ...)
object |
A |
... |
Additional arguments passed to |
A data frame (or list of data frames if multiple levels of grouping)
of random effects, as returned by ranef.nlme().
coef.beezdemand_nlme, fixef.beezdemand_nlme
Extract Random Effects from Mixed-Effects Cross-Price Model
## S3 method for class 'cp_model_lmer' ranef(object, ...)## S3 method for class 'cp_model_lmer' ranef(object, ...)
object |
A cp_model_lmer object |
... |
Additional arguments passed to ranef |
List of random effects
Recodes outliers
RecodeOutliers(df, outval = 3.29, unitshigher = 0)RecodeOutliers(df, outval = 3.29, unitshigher = 0)
df |
A dataframe of consumption values |
outval |
Values greater/less than or equal to this number (specified in standard deviations) will be recoded. Default is 3.29SD as specified by Tabachnick and Fidell (2013) |
unitshigher |
Outliers identified by outval will be coded to a certain number of units higher/lower than the greatest nonoutlier value. Default is 0 units. |
Recodes outliers using Tabachnick and Fidell's (2013) criteria. A variable is standardized and values that are greater/less than or equal to a specified outlier value (specified in standard deviations; default 3.29SD) are recoded to a certain number of units (default 0) higher/lower than the greatest nonoutlier value. Disregards 'NA' values.
Invisibly, a dataframe with original and recoded (if any) values
Brent Kaplan [email protected]
## If any outliers are detected, they would be coded as 1 unit higher emp <- GetEmpirical(apt) RecodeOutliers(emp[, c(2:6)], unitshigher = 1)## If any outliers are detected, they would be coded as 1 unit higher emp <- GetEmpirical(apt) RecodeOutliers(emp[, c(2:6)], unitshigher = 1)
Replaces 0 values
ReplaceZeros(dat, nrepl = 1, replnum = 0.01)ReplaceZeros(dat, nrepl = 1, replnum = 0.01)
dat |
Dataframe (long form) |
nrepl |
Number of zeros to replace with replacement value (replnum). Can accept either a number or "all" if all zeros should be replaced. Default is to replace the first zero only. |
replnum |
Value to replace zeros. Default is .01 |
Replaces specified number of 0s with replacement value.
Dataframe (long form)
Brent Kaplan [email protected]
## Replace all zeros with .01 ReplaceZeros(apt, nrepl = "all", replnum = .01)## Replace all zeros with .01 ReplaceZeros(apt, nrepl = "all", replnum = .01)
Runs a Monte Carlo simulation study to assess model performance, including bias, standard error estimates, and confidence interval coverage.
run_hurdle_monte_carlo( n_sim = 100, n_subjects = 100, true_params = NULL, n_random_effects = 2, prices = seq(0, 11, by = 0.5), stop_at_zero = TRUE, verbose = TRUE, seed = NULL )run_hurdle_monte_carlo( n_sim = 100, n_subjects = 100, true_params = NULL, n_random_effects = 2, prices = seq(0, 11, by = 0.5), stop_at_zero = TRUE, verbose = TRUE, seed = NULL )
n_sim |
Number of simulated datasets. Default is 100. |
n_subjects |
Number of subjects per dataset. Default is 100. |
true_params |
Named list of true parameter values. If NULL, defaults
are used from |
n_random_effects |
Number of random effects (2 or 3). Default is 2. |
prices |
Numeric vector of prices. Default is seq(0, 11, by = 0.5). |
stop_at_zero |
Logical; if TRUE in simulation, subjects stop after first zero. Default is TRUE. |
verbose |
Logical; print progress. Default is TRUE. |
seed |
Random seed for reproducibility. |
A list with:
Data frame of parameter estimates from each simulation
True parameter values used
Summary statistics including bias, SE ratio, and coverage
Number of simulations that converged
Total number of simulations attempted
simulate_hurdle_data, fit_demand_hurdle
# Run small simulation study (for demonstration) mc_results <- run_hurdle_monte_carlo(n_sim = 10, n_subjects = 50, seed = 123) # View summary print(mc_results$summary) # Check convergence rate cat("Convergence rate:", mc_results$n_converged / mc_results$n_sim, "\n")# Run small simulation study (for demonstration) mc_results <- run_hurdle_monte_carlo(n_sim = 10, n_subjects = 50, seed = 123) # View summary print(mc_results$summary) # Check convergence rate cat("Convergence rate:", mc_results$n_converged / mc_results$n_sim, "\n")
beezdemand Color Scale (Discrete)
scale_color_beezdemand(...)scale_color_beezdemand(...)
... |
Additional arguments passed to |
A ggplot2 discrete color scale.
library(ggplot2) ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + geom_point() + scale_color_beezdemand()library(ggplot2) ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + geom_point() + scale_color_beezdemand()
beezdemand Fill Scale (Discrete)
scale_fill_beezdemand(...)scale_fill_beezdemand(...)
... |
Additional arguments passed to |
A ggplot2 discrete fill scale.
library(ggplot2) ggplot(iris, aes(Species, Sepal.Length, fill = Species)) + geom_boxplot() + scale_fill_beezdemand()library(ggplot2) ggplot(iris, aes(Species, Sepal.Length, fill = Species)) + geom_boxplot() + scale_fill_beezdemand()
This function generates a ggplot2 continuous scale that applies the ll4
transformation (and its inverse ll4_inv) to an axis. This is useful for
visualizing data spanning multiple orders of magnitude while handling zeros.
scale_ll4(..., lambda = 4)scale_ll4(..., lambda = 4)
... |
Arguments passed on to |
lambda |
A positive numeric scalar, the lambda parameter for the |
A ggplot2 scale object.
if (require(ggplot2) && require(scales)) { set.seed(123) df <- data.frame( x = 1:100, y_raw = c(0, 0.1, 0.5, 1, 5, 10, 50, 100, 500, 1000, sample(1:2000, 90, replace = TRUE)) ) # Plot with y-axis on LL4 scale ggplot(df, aes(x = x, y = y_raw)) + geom_point() + scale_ll4(name = "Y-axis (LL4 Scale)", lambda = 4) + ggtitle("Data with LL4 Transformed Y-Axis") # Can also be used for x-axis by replacing scale_y_continuous in its definition # Or by creating a scale_x_ll4 variant. }if (require(ggplot2) && require(scales)) { set.seed(123) df <- data.frame( x = 1:100, y_raw = c(0, 0.1, 0.5, 1, 5, 10, 50, 100, 500, 1000, sample(1:2000, 90, replace = TRUE)) ) # Plot with y-axis on LL4 scale ggplot(df, aes(x = x, y = y_raw)) + geom_point() + scale_ll4(name = "Y-axis (LL4 Scale)", lambda = 4) + ggtitle("Data with LL4 Transformed Y-Axis") # Can also be used for x-axis by replacing scale_y_continuous in its definition # Or by creating a scale_x_ll4 variant. }
Generates simulated demand data from the two-part hurdle model. Useful for Monte Carlo simulation studies, power analyses, and model validation.
simulate_hurdle_data( n_subjects = 100, prices = seq(0, 11, by = 0.5), beta0 = -2, beta1 = 1, log_q0 = log(10), logQ0 = deprecated(), k = 2, alpha = 0.5, sigma_a = 1, sigma_b = 0.5, sigma_c = 0.1, rho_ab = 0.3, rho_ac = 0, rho_bc = 0, sigma_e = 0.3, epsilon = 0.001, n_random_effects = 2, stop_at_zero = TRUE, seed = NULL )simulate_hurdle_data( n_subjects = 100, prices = seq(0, 11, by = 0.5), beta0 = -2, beta1 = 1, log_q0 = log(10), logQ0 = deprecated(), k = 2, alpha = 0.5, sigma_a = 1, sigma_b = 0.5, sigma_c = 0.1, rho_ab = 0.3, rho_ac = 0, rho_bc = 0, sigma_e = 0.3, epsilon = 0.001, n_random_effects = 2, stop_at_zero = TRUE, seed = NULL )
n_subjects |
Number of subjects to simulate. Default is 100. |
prices |
Numeric vector of prices at which to simulate consumption.
Default is |
beta0 |
Intercept for Part I (logistic). Default is -2. |
beta1 |
Slope for Part I (on log(price + epsilon)). Default is 1. |
log_q0 |
Log of intensity parameter (Q0). Default is log(10), meaning
Q0 = 10. To specify Q0 directly, use |
logQ0 |
|
k |
Scaling parameter for demand decay. Default is 2. |
alpha |
Elasticity parameter controlling rate of demand decay. Default is 0.5. |
sigma_a |
Standard deviation of random intercept for Part I. Default is 1. |
sigma_b |
Standard deviation of random intercept for Part II. Default is 0.5. |
sigma_c |
Standard deviation of random slope for alpha (only used if
|
rho_ab |
Correlation between a_i and b_i. Default is 0.3. |
rho_ac |
Correlation between a_i and c_i. Default is 0. |
rho_bc |
Correlation between b_i and c_i. Default is 0. |
sigma_e |
Residual standard deviation. Default is 0.3. |
epsilon |
Small constant for log(price + epsilon). Default is 0.001. |
n_random_effects |
Number of random effects (2 or 3). Default is 2. |
stop_at_zero |
Logical; if TRUE, stop generating observations for a subject once zero consumption is observed. This means subjects will have varying numbers of observations. Set to FALSE to generate all prices for all subjects. Default is TRUE. |
seed |
Optional random seed for reproducibility. |
The simulation follows Zhao et al. (2016):
Part I (Zero vs Positive):
Part II (Positive Consumption):
Random effects or are drawn from a
multivariate normal distribution with the specified variances and correlations.
A data frame with columns:
Subject identifier
Price value
Simulated consumption (may include zeros)
Indicator for zero consumption (1 = zero, 0 = positive)
Subject-specific random effect for Part I
Subject-specific random effect for Part II
Subject-specific random effect for alpha (if n_random_effects = 3)
fit_demand_hurdle, run_hurdle_monte_carlo
# Simulate with default parameters (2 RE model) sim_data <- simulate_hurdle_data(n_subjects = 100, seed = 123) head(sim_data) # Simulate with custom prices apt_prices <- c(0, 0.25, 0.5, 1, 1.5, 2, 2.5, 3, 4, 5, 6, 7, 8, 9, 10) sim_apt <- simulate_hurdle_data(n_subjects = 100, prices = apt_prices, seed = 123) # Simulate with custom parameters (Q0 = 15, alpha = 0.1) sim_custom <- simulate_hurdle_data( n_subjects = 100, log_q0 = log(15), alpha = 0.1, seed = 123 ) # Simulate 3 RE model sim_3re <- simulate_hurdle_data( n_subjects = 100, n_random_effects = 3, sigma_c = 0.1, seed = 456 )# Simulate with default parameters (2 RE model) sim_data <- simulate_hurdle_data(n_subjects = 100, seed = 123) head(sim_data) # Simulate with custom prices apt_prices <- c(0, 0.25, 0.5, 1, 1.5, 2, 2.5, 3, 4, 5, 6, 7, 8, 9, 10) sim_apt <- simulate_hurdle_data(n_subjects = 100, prices = apt_prices, seed = 123) # Simulate with custom parameters (Q0 = 15, alpha = 0.1) sim_custom <- simulate_hurdle_data( n_subjects = 100, log_q0 = log(15), alpha = 0.1, seed = 123 ) # Simulate 3 RE model sim_3re <- simulate_hurdle_data( n_subjects = 100, n_random_effects = 3, sigma_c = 0.1, seed = 456 )
Simulate demand data
SimulateDemand(nruns = 10, setparams, sdindex, x, outdir = NULL, fn = NULL)SimulateDemand(nruns = 10, setparams, sdindex, x, outdir = NULL, fn = NULL)
nruns |
Number of runs. Default value is 10 |
setparams |
A 6x1 matrix (or 6 element vector) containing (in order) mean log10alpha, sd log10alpha, mean log10q0, sd log10q0, k, sd of consumption values across all prices |
sdindex |
A vector of n length of sd consumption values for n prices |
x |
A vector of n prices |
outdir |
Optional. Directory to save results. Must end with a "/" |
fn |
Optional. Filename of saved RData object |
Generates and saves simulated datasets in the manner specified in Koffarnus, Franck, Stein, & Bickel (2015).
Invisibly a list consisting of: rounded consumption values, unrounded consumption values, simulation parameters, and inState and outState of seeds.
Brent Kaplan [email protected]
## set values setparams <- vector(length = 4) setparams <- c(-2.5547, .702521, 1.239893, .320221, 3.096, 1.438231) names(setparams) <- c("alphalm", "alphalsd", "q0lm", "q0lsd", "k", "yvalssd") sdindex <- c(2.1978, 1.9243, 1.5804, 1.2465, 0.8104, 0.1751, 0.0380, 0.0270) x <- c(.1, 1, 3, 10, 30, 100, 300, 1000) set.seed(1234) sim <- SimulateDemand(nruns = 1, setparams = setparams, sdindex = sdindex, x = x) sim## set values setparams <- vector(length = 4) setparams <- c(-2.5547, .702521, 1.239893, .320221, 3.096, 1.438231) names(setparams) <- c("alphalm", "alphalsd", "q0lm", "q0lsd", "k", "yvalssd") sdindex <- c(2.1978, 1.9243, 1.5804, 1.2465, 0.8104, 0.1751, 0.0380, 0.0270) x <- c(.1, 1, 3, 10, 30, 100, 300, 1000) set.seed(1234) sim <- SimulateDemand(nruns = 1, setparams = setparams, sdindex = sdindex, x = x) sim
Summary Method for beezdemand_fixed
## S3 method for class 'beezdemand_fixed' summary(object, report_space = c("natural", "log10"), ...)## S3 method for class 'beezdemand_fixed' summary(object, report_space = c("natural", "log10"), ...)
object |
A beezdemand_fixed object |
report_space |
Character. Reporting space for core parameters. One of:
|
... |
Additional arguments (ignored) |
A summary.beezdemand_fixed object (inherits from beezdemand_summary)
Provides a summary of a fitted hurdle demand model, including fixed effects, variance components, correlations, and fit statistics.
## S3 method for class 'beezdemand_hurdle' summary(object, report_space = c("natural", "log10", "internal"), ...)## S3 method for class 'beezdemand_hurdle' summary(object, report_space = c("natural", "log10", "internal"), ...)
object |
An object of class |
report_space |
Character. Reporting space for core demand parameters. One of:
|
... |
Additional arguments (currently unused). |
An object of class summary.beezdemand_hurdle (also inherits
from beezdemand_summary) containing:
The original function call
"beezdemand_hurdle"
"TMB"
Tibble of fixed effects with estimates, SEs, z-values, p-values
Matrix form for printing (legacy compatibility)
Matrix of variance/covariance estimates
Matrix of correlation estimates
Number of subjects
Number of observations
Logical indicating convergence
Log-likelihood at convergence
Akaike Information Criterion
Bayesian Information Criterion
Group-level Pmax and Omax
Summary of individual-level parameters
Character vector of warnings/notes
data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") summary(fit)data(apt) fit <- fit_demand_hurdle(apt, y_var = "y", x_var = "x", id_var = "id") summary(fit)
Returns a structured summary object containing model coefficients, fit statistics, and random effects information.
## S3 method for class 'beezdemand_nlme' summary(object, report_space = c("natural", "log10"), ...)## S3 method for class 'beezdemand_nlme' summary(object, report_space = c("natural", "log10"), ...)
object |
A beezdemand_nlme object |
report_space |
Character. Reporting space for core parameters. One of
|
... |
Additional arguments (passed to summary.nlme) |
A summary.beezdemand_nlme object (inherits from
beezdemand_summary) with fields including:
call: The original function call
model_class: "beezdemand_nlme"
backend: "nlme"
equation_form: The equation form used ("zben" or "simplified")
coefficients: Tibble of fixed effects with std.error, statistic, p.value
random_effects: VarCorr output for random effects
logLik, AIC, BIC: Model fit statistics
Summary Method for beezdemand_systematicity
## S3 method for class 'beezdemand_systematicity' summary(object, ...)## S3 method for class 'beezdemand_systematicity' summary(object, ...)
object |
A beezdemand_systematicity object |
... |
Additional arguments (ignored) |
A summary.beezdemand_systematicity object
Summary method for cp_model_lm objects.
## S3 method for class 'cp_model_lm' summary(object, ...)## S3 method for class 'cp_model_lm' summary(object, ...)
object |
A cp_model_lm object. |
... |
Additional arguments. |
A list summarizing the linear model.
Summary method for cp_model_lmer objects.
## S3 method for class 'cp_model_lmer' summary(object, ...)## S3 method for class 'cp_model_lmer' summary(object, ...)
object |
A cp_model_lmer object. |
... |
Additional arguments. |
A list summarizing the mixed-effects model.
Summarize a Cross-Price Demand Model (Nonlinear)
## S3 method for class 'cp_model_nls' summary(object, inv_fun = identity, inverse_fun = deprecated(), ...)## S3 method for class 'cp_model_nls' summary(object, inv_fun = identity, inverse_fun = deprecated(), ...)
object |
A cross-price model object from fit_cp_nls with return_all=TRUE. |
inv_fun |
Optional function to inverse-transform predictions (e.g., ll4_inv).
Default is |
inverse_fun |
|
... |
Additional arguments (unused). |
A list containing model summary information.
Summarizes systematic and unsystematic patterns from multiple calls to
check_unsystematic_cp(). This includes overall proportions, trend and bounce
direction counts, and optionally summaries by subject or group.
## S3 method for class 'cp_unsystematic' summary(object, ...)## S3 method for class 'cp_unsystematic' summary(object, ...)
object |
A data frame containing results from multiple |
... |
Additional arguments (currently unused) |
A list of class summary.cp_unsystematic with the following elements:
Number of total patterns examined.
Count of systematic patterns (no bounce).
Count of unsystematic patterns (bounce detected).
Proportion of systematic patterns.
Proportion of unsystematic patterns.
Breakdown of trend directions.
Breakdown of bounce directions.
(Optional) Summary of zero-reversal patterns, if present in input.
(Optional) Summary of zero-return patterns, if present in input.
(Optional) Summary stats by 'group'.
(Optional) Top IDs with unsystematic patterns.
Modern wrappers for systematicity checks with unified output vocabulary.
APA theme for ggplot
theme_apa(plot.box = FALSE)theme_apa(plot.box = FALSE)
plot.box |
Boolean for a box around the plot |
Theme for ggplot graphics that closely align with APA formatting
ggplot theme
Brent Kaplan [email protected]
p <- ggplot2::ggplot(apt, ggplot2::aes(x = x, y = y)) + ggplot2::geom_point() p + theme_apa()p <- ggplot2::ggplot(apt, ggplot2::aes(x = x, y = y)) + ggplot2::geom_point() p + theme_apa()
beezdemand Plot Theme
theme_beezdemand( style = c("modern", "apa"), base_size = 11, base_family = "sans" )theme_beezdemand( style = c("modern", "apa"), base_size = 11, base_family = "sans" )
style |
Character. One of |
base_size |
Base font size (default: 11). |
base_family |
Base font family (default: "sans"). |
A ggplot2 theme object.
library(ggplot2) ggplot(iris, aes(Sepal.Length, Sepal.Width)) + geom_point() + theme_beezdemand()library(ggplot2) ggplot(iris, aes(Sepal.Length, Sepal.Width)) + geom_point() + theme_beezdemand()
Tidy Method for beezdemand_fixed
## S3 method for class 'beezdemand_fixed' tidy(x, report_space = c("natural", "log10"), ...)## S3 method for class 'beezdemand_fixed' tidy(x, report_space = c("natural", "log10"), ...)
x |
A beezdemand_fixed object |
report_space |
Character. Reporting space for core parameters. One of
|
... |
Additional arguments (ignored) |
A tibble of model coefficients with columns: id, term, estimate, std.error, statistic, p.value, component
Returns a tibble of model coefficients in tidy format.
## S3 method for class 'beezdemand_hurdle' tidy(x, report_space = c("natural", "log10", "internal"), ...)## S3 method for class 'beezdemand_hurdle' tidy(x, report_space = c("natural", "log10", "internal"), ...)
x |
An object of class |
report_space |
Character. Reporting space for core demand parameters.
One of |
... |
Additional arguments (currently unused). |
A tibble with columns:
Parameter name
Point estimate
Standard error
z-value
P-value
One of "zero_probability", "consumption", "variance", or "fixed"
Tidy method for beezdemand_nlme
## S3 method for class 'beezdemand_nlme' tidy( x, effects = c("fixed", "ran_pars"), report_space = c("natural", "log10"), ... )## S3 method for class 'beezdemand_nlme' tidy( x, effects = c("fixed", "ran_pars"), report_space = c("natural", "log10"), ... )
x |
A beezdemand_nlme object |
effects |
Which effects to include: "fixed" (default), "ran_pars", or both |
report_space |
Character. Reporting space for core parameters. One of
|
... |
Additional arguments (ignored) |
A tibble of model coefficients with columns:
term: Parameter name
estimate: Point estimate
std.error: Standard error
statistic: t-value
p.value: P-value
component: "fixed" or "variance"
Tidy Method for beezdemand_systematicity
## S3 method for class 'beezdemand_systematicity' tidy(x, ...)## S3 method for class 'beezdemand_systematicity' tidy(x, ...)
x |
A beezdemand_systematicity object |
... |
Additional arguments (ignored) |
The per-subject results tibble
Extract coefficients from a linear cross-price model in tidy format
## S3 method for class 'cp_model_lm' tidy(x, ...)## S3 method for class 'cp_model_lm' tidy(x, ...)
x |
A cp_model_lm object. |
... |
Additional arguments (unused). |
A tibble with columns: term, estimate, std.error, statistic, p.value.
Extract coefficients from a mixed-effects cross-price model in tidy format
## S3 method for class 'cp_model_lmer' tidy(x, effects = c("fixed", "random", "ran_pars"), ...)## S3 method for class 'cp_model_lmer' tidy(x, effects = c("fixed", "random", "ran_pars"), ...)
x |
A cp_model_lmer object. |
effects |
Which effects to return: "fixed" (default), "random", or "ran_pars". |
... |
Additional arguments passed to broom.mixed::tidy. |
A tibble with tidy coefficient information.
This function extracts model coefficients from a cross-price demand model into a tidy data frame format, following the conventions of the broom package. It handles cases where model fitting failed gracefully, returning an empty data frame with the expected structure.
## S3 method for class 'cp_model_nls' tidy(x, ...)## S3 method for class 'cp_model_nls' tidy(x, ...)
x |
A model object from fit_cp_nls or fit_cp_linear |
... |
Additional arguments (unused) |
A data frame with one row per coefficient, containing columns:
term |
The name of the model parameter |
estimate |
The estimated coefficient value |
std.error |
The standard error of the coefficient |
statistic |
The t-statistic for the coefficient |
p.value |
The p-value for the coefficient |
data(etm) fit <- fit_cp_nls(etm, equation = "exponentiated") tidy(fit)data(etm) fit <- fit_cp_nls(etm, equation = "exponentiated") tidy(fit)