--- title: "Migration Guide: FitCurves to fit_demand_fixed" author: "beezdemand Developers" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Migration Guide: FitCurves to fit_demand_fixed} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( echo = TRUE, collapse = TRUE, comment = "#>", dev = "png", dpi = 144, fig.width = 7, fig.height = 5, warning = FALSE, message = FALSE ) library(beezdemand) library(dplyr) ``` # Overview 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 started - `vignette("model-selection")` for choosing a model class - `vignette("mixed-demand")` and `vignette("mixed-demand-advanced")` for mixed-effects models - `vignette("hurdle-demand-models")` for hurdle models ## Why Migrate? The new `fit_demand_fixed()` function provides: - **Structured S3 objects** with consistent methods (`summary()`, `tidy()`, `glance()`, `predict()`, `plot()`, `confint()`, `augment()`) - **Tidyverse integration** via tibble outputs from `tidy()` and `glance()` - **Standardized API** consistent with other beezdemand model classes - **Better reproducibility** with stored call and parameter information `FitCurves()` will continue to work but is no longer actively developed. New features will only be added to `fit_demand_fixed()`. # Quick Migration Reference | 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 | # Basic Migration ## Before (FitCurves) ```{r fitcurves-example, eval = FALSE} # Old approach results <- FitCurves( dat = apt, equation = "hs", k = 2, xcol = "x", ycol = "y", idcol = "id" ) # results is a data.frame with all parameters head(results) ``` ## After (fit_demand_fixed) ```{r fit-demand-fixed-example} # 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) ``` # Extracting Results ## Getting Parameter Estimates ### Before (FitCurves) ```{r extract-old, eval = FALSE} # FitCurves returns a data frame directly results <- FitCurves(apt, "hs", k = 2) q0_values <- results$Q0d alpha_values <- results$Alpha ``` ### After (fit_demand_fixed) ```{r extract-new} # Use tidy() for a tibble of coefficients fit <- fit_demand_fixed(apt, equation = "hs", k = 2) coefs <- tidy(fit) head(coefs) # Or access the results data frame directly head(fit$results) ``` ## Getting Model-Level Statistics ### Before (FitCurves) ```{r stats-old, eval = FALSE} # Manual calculation required results <- FitCurves(apt, "hs", k = 2) n_converged <- sum(!is.na(results$Alpha)) mean_r2 <- mean(results$R2, na.rm = TRUE) ``` ### After (fit_demand_fixed) ```{r stats-new} # Use glance() for model-level statistics fit <- fit_demand_fixed(apt, equation = "hs", k = 2) glance(fit) # Or use summary() for comprehensive output summary(fit) ``` # Working with Predictions ## Before (FitCurves) ```{r pred-old, eval = FALSE} # Required detailed = TRUE and manual extraction results <- FitCurves(apt, "hs", k = 2, detailed = TRUE) # Predictions stored in list element predictions <- results$newdats # List of data frames ``` ## After (fit_demand_fixed) ```{r pred-new} # 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) ``` # Plotting ## Before (FitCurves) ```{r plot-old, eval = FALSE} # Used separate PlotCurves() function results <- FitCurves(apt, "hs", k = 2, detailed = TRUE) PlotCurves(results) ``` ## After (fit_demand_fixed) ```{r plot-new, fig.width = 6, fig.height = 4} # 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) ``` ## New in 0.2.0: Diagnostics + Residual Workflows Once you migrate to the modern API, you can use standardized post-fit helpers: - `augment()` to get fitted values + residuals in a tidy format - `check_demand_model()` for a structured diagnostic summary - `plot_residuals()` for common residual diagnostics (via `augment()`) ```{r post-fit-workflow} fit <- fit_demand_fixed(apt, equation = "hs", k = 2) augment(fit) |> head() check_demand_model(fit) plot_residuals(fit)$fitted ``` ## New in 0.2.0: Unified Systematicity Wrappers For 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. ```{r systematicity-wrapper, eval = FALSE} sys <- check_systematic_demand(apt) head(sys$results) ``` # Advanced Features ## Aggregated Data (Mean/Pooled) Both functions support aggregation, with identical syntax: ```{r agg-example} # Fit to mean data fit_mean <- fit_demand_fixed(apt, equation = "hs", k = 2, agg = "Mean") tidy(fit_mean) ``` ## Parameter Space Both functions support log10 parameterization: ```{r param-space} # 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() tidy(fit_log, report_space = "natural") |> head() ``` # Feature Comparison | 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 | # Suppressing Deprecation Warnings 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: ```{r suppress-warning, eval = FALSE} # 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. # Need Help? If you encounter issues during migration: 1. Check the function documentation: `?fit_demand_fixed` 2. Review the [beezdemand GitHub repository](https://github.com/brentkaplan/beezdemand) 3. Open an issue if you find bugs or have feature requests # See Also - `vignette("beezdemand")` -- Getting started with beezdemand - `vignette("model-selection")` -- Choosing the right model class - `vignette("fixed-demand")` -- Fixed-effect demand modeling - `vignette("mixed-demand")` -- Mixed-effects nonlinear demand models - `vignette("mixed-demand-advanced")` -- Advanced mixed-effects topics - `vignette("hurdle-demand-models")` -- Two-part hurdle demand models - `vignette("cross-price-models")` -- Cross-price demand analysis - `vignette("group-comparisons")` -- Group comparisons # Session Information ```{r session-info} sessionInfo() ```