Starting with beezdemand version 0.2.0, FitCurves() has
been superseded by fit_demand_fixed(). This guide helps you
migrate existing code to use the modern API.
For related workflows, see:
vignette("beezdemand") for getting startedvignette("model-selection") for choosing a model
classvignette("mixed-demand") and
vignette("mixed-demand-advanced") for mixed-effects
modelsvignette("hurdle-demand-models") for hurdle modelsThe new fit_demand_fixed() function provides:
summary(), tidy(), glance(),
predict(), plot(), confint(),
augment())tidy() and glance()FitCurves() will continue to work but is no longer
actively developed. New features will only be added to
fit_demand_fixed().
| FitCurves() | fit_demand_fixed() | Notes |
|---|---|---|
dat |
data |
Renamed for consistency |
xcol |
x_var |
Renamed for consistency |
ycol |
y_var |
Renamed for consistency |
idcol |
id_var |
Renamed for consistency |
detailed = TRUE |
Always detailed | fit_demand_fixed always returns full results |
groupcol |
Not supported | Use factor models instead |
| Returns data.frame | Returns S3 object | Use tidy() for data frame output |
# New approach
fit <- fit_demand_fixed(
data = apt,
equation = "hs",
k = 2,
x_var = "x",
y_var = "y",
id_var = "id"
)
# fit is a structured S3 object
print(fit)
#>
#> Fixed-Effect Demand Model
#> ==========================
#>
#> Call:
#> fit_demand_fixed(data = apt, equation = "hs", k = 2, x_var = "x",
#> y_var = "y", id_var = "id")
#>
#> Equation: hs
#> k: fixed (2)
#> Subjects: 10 ( 10 converged, 0 failed)
#>
#> Use summary() for parameter summaries, tidy() for tidy output.# Use tidy() for a tibble of coefficients
fit <- fit_demand_fixed(apt, equation = "hs", k = 2)
coefs <- tidy(fit)
head(coefs)
#> # A tibble: 6 × 10
#> id term estimate std.error statistic p.value component estimate_scale
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 19 Q0 10.2 0.269 NA NA fixed natural
#> 2 30 Q0 2.81 0.226 NA NA fixed natural
#> 3 38 Q0 4.50 0.215 NA NA fixed natural
#> 4 60 Q0 9.92 0.459 NA NA fixed natural
#> 5 68 Q0 10.4 0.329 NA NA fixed natural
#> 6 106 Q0 5.68 0.300 NA NA fixed natural
#> # ℹ 2 more variables: term_display <chr>, estimate_internal <dbl>
# Or access the results data frame directly
head(fit$results)
#> id Intensity BP0 BP1 Omaxe Pmaxe Equation Q0d K Alpha R2
#> 1 19 10 NA 20 45 15 hs 10.158664 2 0.002047574 0.9804182
#> 2 30 3 NA 20 20 20 hs 2.807366 2 0.005865523 0.7723159
#> 3 38 4 NA 10 21 7 hs 4.497456 2 0.004203441 0.8767531
#> 4 60 10 NA 10 24 8 hs 9.924274 2 0.004299344 0.9714808
#> 5 68 10 NA 10 36 9 hs 10.390384 2 0.002765273 0.9723669
#> 6 106 5 NA 7 15 5 hs 5.683566 2 0.006281201 0.9283457
#> Q0se Alphase alpha_star alpha_star_se N AbsSS SdRes
#> 1 0.2685323 6.090445e-05 0.00836391 0.0002487819 16 0.01113625 0.02820366
#> 2 0.2257764 6.760007e-04 0.02395943 0.0027613206 16 0.10721624 0.08751173
#> 3 0.2146862 3.571177e-04 0.01717017 0.0014587507 14 0.02387617 0.04460584
#> 4 0.4591683 1.449834e-04 0.01756192 0.0005922269 14 0.02013543 0.04096282
#> 5 0.3290277 9.636582e-05 0.01129556 0.0003936341 14 0.01006059 0.02895483
#> 6 0.3002817 4.315615e-04 0.02565739 0.0017628381 11 0.01651102 0.04283174
#> Q0Low Q0High AlphaLow AlphaHigh EV Omaxd Pmaxd
#> 1 9.582720 10.734609 0.001916947 0.002178201 1.7266939 44.43035 13.869758
#> 2 2.323124 3.291609 0.004415646 0.007315401 0.6027653 15.51003 17.520210
#> 3 4.029695 4.965217 0.003425349 0.004981534 0.8411046 21.64285 15.260658
#> 4 8.923832 10.924716 0.003983452 0.004615236 0.8223426 21.16008 6.761518
#> 5 9.673495 11.107274 0.002555310 0.002975236 1.2785478 32.89890 10.040966
#> 6 5.004282 6.362850 0.005304941 0.007257462 0.5628754 14.48361 8.081306
#> Omaxa Pmaxa Notes converged
#> 1 44.43095 13.955544 converged TRUE
#> 2 15.51024 17.628574 converged TRUE
#> 3 21.64314 15.355046 converged TRUE
#> 4 21.16036 6.803339 converged TRUE
#> 5 32.89934 10.103070 converged TRUE
#> 6 14.48380 8.131289 converged TRUE# Use glance() for model-level statistics
fit <- fit_demand_fixed(apt, equation = "hs", k = 2)
glance(fit)
#> # A tibble: 1 × 12
#> model_class backend equation k_spec nobs n_subjects n_success n_fail
#> <chr> <chr> <chr> <chr> <int> <int> <int> <int>
#> 1 beezdemand_fixed legacy hs fixed (2) 146 10 10 0
#> # ℹ 4 more variables: converged <lgl>, logLik <dbl>, AIC <dbl>, BIC <dbl>
# Or use summary() for comprehensive output
summary(fit)
#>
#> Fixed-Effect Demand Model Summary
#> ==================================================
#>
#> Equation: hs
#> k: fixed (2)
#>
#> Fit Summary:
#> Total subjects: 10
#> Converged: 10
#> Failed: 0
#> Total observations: 146
#>
#> Parameter Summary (across subjects):
#> Q0:
#> Median: 6.2498
#> Range: [ 2.8074 , 10.3904 ]
#> alpha:
#> Median: 0.004251
#> Range: [ 0.001987 , 0.00785 ]
#>
#> Per-subject coefficients:
#> -------------------------
#> # A tibble: 40 × 10
#> id term estimate std.error statistic p.value component estimate_scale
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 106 Q0 5.68 0.300 NA NA fixed natural
#> 2 106 alpha 0.00628 0.000432 NA NA fixed natural
#> 3 106 alpha_st… 0.0257 0.00176 NA NA fixed natural
#> 4 106 k 2 NA NA NA fixed natural
#> 5 113 Q0 6.20 0.174 NA NA fixed natural
#> 6 113 alpha 0.00199 0.000109 NA NA fixed natural
#> 7 113 alpha_st… 0.00812 0.000447 NA NA fixed natural
#> 8 113 k 2 NA NA NA fixed natural
#> 9 142 Q0 6.17 0.641 NA NA fixed natural
#> 10 142 alpha 0.00237 0.000400 NA NA fixed natural
#> # ℹ 30 more rows
#> # ℹ 2 more variables: term_display <chr>, estimate_internal <dbl># Use predict() method
fit <- fit_demand_fixed(apt, equation = "hs", k = 2)
# Predict at new prices
new_prices <- data.frame(x = c(0, 0.5, 1, 2, 5, 10))
preds <- predict(fit, newdata = new_prices)
head(preds)
#> # A tibble: 6 × 3
#> x id .fitted
#> <dbl> <chr> <dbl>
#> 1 0 19 10.2
#> 2 0 30 2.81
#> 3 0 38 4.50
#> 4 0 60 9.92
#> 5 0 68 10.4
#> 6 0 106 5.68# Use plot() method directly on the fit object
fit <- fit_demand_fixed(apt, equation = "hs", k = 2)
# Plot first 5 subjects
plot(fit, ids = unique(apt$id)[1:5], facet = TRUE)Once you migrate to the modern API, you can use standardized post-fit helpers:
augment() to get fitted values + residuals in a tidy
formatcheck_demand_model() for a structured diagnostic
summaryplot_residuals() for common residual diagnostics (via
augment())fit <- fit_demand_fixed(apt, equation = "hs", k = 2)
augment(fit) |> head()
#> # A tibble: 6 × 7
#> id x y group k .fitted .resid
#> <chr> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
#> 1 19 0 10 a 2 10.2 -0.159
#> 2 19 0.5 10 a 2 9.69 0.314
#> 3 19 1 10 a 2 9.24 0.760
#> 4 19 1.5 8 a 2 8.82 -0.819
#> 5 19 2 8 a 2 8.42 -0.421
#> 6 19 2.5 8 a 2 8.04 -0.0444
check_demand_model(fit)
#>
#> Model Diagnostics
#> ==================================================
#> Model class: beezdemand_fixed
#>
#> Convergence:
#> Status: Converged
#>
#> Residuals:
#> Mean: 0.0284
#> SD: 0.5306
#> Range: [-1.458, 2.228]
#> Outliers: 3 observations
#>
#> --------------------------------------------------
#> Issues Detected (1):
#> 1. Detected 3 potential outliers across subjects
plot_residuals(fit)$fittedFor user-facing workflows, prefer:
check_systematic_demand() (purchase task)check_systematic_cp() (cross-price)These wrap legacy helpers (e.g., CheckUnsystematic())
but return a standardized beezdemand_systematicity
object.
Both functions support aggregation, with identical syntax:
# Fit to mean data
fit_mean <- fit_demand_fixed(apt, equation = "hs", k = 2, agg = "Mean")
tidy(fit_mean)
#> # A tibble: 4 × 10
#> id term estimate std.error statistic p.value component estimate_scale
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 mean Q0 7.44 2.03e-1 NA NA fixed natural
#> 2 mean alpha 0.00435 8.89e-5 NA NA fixed natural
#> 3 mean alpha_star 0.0178 3.63e-4 NA NA fixed natural
#> 4 mean k 2 NA NA NA fixed natural
#> # ℹ 2 more variables: term_display <chr>, estimate_internal <dbl>Both functions support log10 parameterization:
# Fit in log10 space
fit_log <- fit_demand_fixed(
apt,
equation = "hs",
k = 2,
param_space = "log10"
)
# tidy() can report in either scale
tidy(fit_log, report_space = "log10") |> head()
#> # A tibble: 6 × 10
#> id term estimate std.error statistic p.value component estimate_scale
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 19 Q0 1.01 0.0115 NA NA fixed log10
#> 2 30 Q0 0.448 0.0349 NA NA fixed log10
#> 3 38 Q0 0.653 0.0207 NA NA fixed log10
#> 4 60 Q0 0.997 0.0201 NA NA fixed log10
#> 5 68 Q0 1.02 0.0138 NA NA fixed log10
#> 6 106 Q0 0.755 0.0229 NA NA fixed log10
#> # ℹ 2 more variables: term_display <chr>, estimate_internal <dbl>
tidy(fit_log, report_space = "natural") |> head()
#> # A tibble: 6 × 10
#> id term estimate std.error statistic p.value component estimate_scale
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 19 Q0 10.2 0.269 NA NA fixed natural
#> 2 30 Q0 2.81 0.226 NA NA fixed natural
#> 3 38 Q0 4.50 0.215 NA NA fixed natural
#> 4 60 Q0 9.92 0.459 NA NA fixed natural
#> 5 68 Q0 10.4 0.329 NA NA fixed natural
#> 6 106 Q0 5.68 0.300 NA NA fixed natural
#> # ℹ 2 more variables: term_display <chr>, estimate_internal <dbl>| Feature | FitCurves() | fit_demand_fixed() |
|---|---|---|
| Equations | hs, koff, linear | hs, koff, linear |
| k options | numeric, “ind”, “fit”, “share” | numeric, “ind”, “fit”, “share” |
| Aggregation | “Mean”, “Pooled” | “Mean”, “Pooled” |
| Parameter space | natural, log10 | natural, log10 |
summary() method |
No | Yes |
tidy() method |
No | Yes |
glance() method |
No | Yes |
predict() method |
No | Yes |
plot() method |
No | Yes |
coef() method |
No | Yes |
augment() method |
No | Yes |
confint() method |
No | Yes |
If you need to continue using FitCurves() without
warnings (e.g., in legacy code or during a gradual migration), you can
suppress the deprecation message:
# Suppress deprecation warning temporarily
rlang::with_options(
lifecycle_verbosity = "quiet",
FitCurves(apt, "hs", k = 2)
)However, we strongly recommend migrating to
fit_demand_fixed() for new code.
If you encounter issues during migration:
?fit_demand_fixedvignette("beezdemand") – Getting started with
beezdemandvignette("model-selection") – Choosing the right model
classvignette("fixed-demand") – Fixed-effect demand
modelingvignette("mixed-demand") – Mixed-effects nonlinear
demand modelsvignette("mixed-demand-advanced") – Advanced
mixed-effects topicsvignette("hurdle-demand-models") – Two-part hurdle
demand modelsvignette("cross-price-models") – Cross-price demand
analysisvignette("group-comparisons") – Group comparisonssessionInfo()
#> R version 4.5.2 (2025-10-31)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Tahoe 26.3
#>
#> Matrix products: default
#> BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/New_York
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] purrr_1.2.0 beezdemand_0.2.0 ggplot2_4.0.1 tidyr_1.3.2
#> [5] dplyr_1.1.4
#>
#> loaded via a namespace (and not attached):
#> [1] nls.multstart_2.0.0 gtable_0.3.6 TMB_1.9.19
#> [4] xfun_0.55 bslib_0.9.0 insight_1.4.4
#> [7] lattice_0.22-6 vctrs_0.6.5 tools_4.5.2
#> [10] Rdpack_2.6.4 generics_0.1.4 pbkrtest_0.5.5
#> [13] parallel_4.5.2 tibble_3.3.0 pkgconfig_2.0.3
#> [16] Matrix_1.7-4 RColorBrewer_1.1-3 S7_0.2.1
#> [19] lifecycle_1.0.4 compiler_4.5.2 farver_2.1.2
#> [22] minpack.lm_1.2-4 codetools_0.2-20 nlstools_2.1-0
#> [25] htmltools_0.5.9 sass_0.4.10 yaml_2.3.12
#> [28] pillar_1.11.1 nloptr_2.2.1 jquerylib_0.1.4
#> [31] MASS_7.3-60.2 cachem_1.1.0 reformulas_0.4.2
#> [34] boot_1.3-32 nlme_3.1-168 tidyselect_1.2.1
#> [37] digest_0.6.39 performance_0.15.2 mvtnorm_1.3-3
#> [40] labeling_0.4.3 splines_4.5.2 fastmap_1.2.0
#> [43] grid_4.5.2 cli_3.6.5 magrittr_2.0.4
#> [46] utf8_1.2.6 broom_1.0.11 withr_3.0.2
#> [49] scales_1.4.0 backports_1.5.0 estimability_1.5.1
#> [52] rmarkdown_2.30 emmeans_2.0.1 otel_0.2.0
#> [55] lme4_1.1-38 coda_0.19-4.1 evaluate_1.0.5
#> [58] knitr_1.51 rbibutils_2.4 mgcv_1.9-3
#> [61] rlang_1.1.6 Rcpp_1.1.0 xtable_1.8-4
#> [64] glue_1.8.0 nlsr_2023.8.31 minqa_1.2.8
#> [67] jsonlite_2.0.0 R6_2.6.1