marginaleffects

repository·main·Indexed 20 days ago

https://github.com/vincentarelbundock/marginaleffects

A cross-language (R and Python) package for interpreting statistical and machine learning models. It provides a unified interface to compute predictions, comparisons (contrasts, risk ratios), slopes (partial derivatives), and hypothesis tests, supporting over 100 different model classes.

Tokens
66.1K
Snippets
167
Records
242
Agent score
70%

What's inside marginaleffects

  1. Overview of marginaleffects

    main

    marginaleffects is a package available for both R and Python designed to simplify the interpretation of statistical and machine learning models. It provides a unified interface to compute:

    • Predictions: Estimating outcomes based on model parameters.
    • Comparisons: Calculating contrasts, risk ratios, and other comparative metrics.
    • Slopes: Computing partial derivatives and marginal effects.
    • Hypothesis Tests: Performing statistical tests on model components.

    The package supports over 100 different classes of statistical and machine learning models.

  2. License information for marginaleffects-r

    main

    The marginaleffects-r package is licensed under the GNU General Public License v3 (GPLv3).

    Key takeaways for users:

    • Permissions: You are explicitly permitted to run the unmodified program. You may make, run, and propagate covered works.
    • Modifications: You may modify the work, but you must carry prominent notices stating that you modified it and providing a relevant date. Modified versions must be released under the same GPLv3 license.
    • Distribution: You may convey verbatim copies or modified versions. If conveying in object code form, you must also provide the machine-readable Corresponding Source.
    • No Warranty: The program is provided "AS IS" without warranty of any kind. The entire risk as to the quality and performance of the program is with you.
  3. How predictions and average predictions work

    main

    The marginaleffects package provides two primary ways to evaluate outcomes predicted by a fitted model:

    1. predictions(): Computes unit-level (conditional) estimates. This evaluates the model at specific combinations of predictor values (a "reference grid"). Use this when you want to know the predicted outcome for specific observations or specific points in the predictor space.

    2. avg_predictions(): Computes average (marginal) estimates. This marginalizes the unit-level predictions over the distribution of the predictors. Use this when you want to know the expected outcome across a population or specific subgroups.

    Key distinction: If you need "conditional" predictions (e.g., what is the predicted outcome for a specific person?), use predictions() with the newdata argument. If you need "average" predictions (e.g., what is the average predicted outcome for all people in group X?), use avg_predictions() or predictions() with the by argument.

    # Unit-level predictions
    predictions(model, newdata = datagrid(x = 10))
    
    # Average predictions
    avg_predictions(model, newdata = "mean")
  4. Manage memory and internal attributes

    main

    The data frames produced by marginaleffects contain internal attributes (accessible via components()) that store the original model and data. These are useful for post-processing but can consume significant memory.

    Best Practices:

    1. Avoid relying on internal attributes: The names and contents of attributes returned by components() are not part of the public API and may change without notice.
    2. Clear memory: If memory usage becomes an issue, use the prune() function to remove these attributes, or set the global option options(marginaleffects_lean = TRUE) to prevent them from being stored.
  5. How autodiff expansion and guardrails work

    main

    The marginaleffects autodiff pipeline (using JAX) is designed to be a performance optimization that prioritizes correctness. It uses a 'lowering' mechanism to move recorded plans into a shared JAX pipeline.

    Safety Guardrail: Every autodiff operation is protected by autodiff_try() (available in both Python and R). This function compares JAX estimates against the standard pipeline using a 1e-8 tolerance. If a mismatch is detected (e.g., due to a lowering bug), the system automatically reverts to finite differences and issues a warning. This ensures that autodiff provides a speedup when possible but never produces incorrect numbers.

  6. Understand the `type` argument and `invlink(link)`

    main

    The type argument determines the scale of predictions used for computations. Valid values depend on the model object; if an invalid value is provided, marginaleffects will return an error listing valid types (the first being the default).

    This is a special type available for some models, primarily in the predictions() function. It computes predictions on the link scale and then applies the inverse link function to backtransform them to the response scale.

    Use cases:

    • Ensuring confidence intervals stay within valid bounds (e.g., 0 to 1 for logit models).
    • It is the default for predictions().
    • It is available (but not default) for avg_predictions() or predictions() when using the by argument.

    Note: An average of estimates with type="invlink(link)" is not always equivalent to an average of estimates with type="response".

  7. Perform hypothesis tests with the hypothesis argument

    main

    The hypothesis argument allows you to perform linear or non-linear hypothesis tests and custom contrasts on the estimated slopes.

    Supported Formats:

    • Numeric/Float: Specifies the null hypothesis used in Z and p-value computation.
    • String Equations: Use variable names or b0, b1, etc., to identify parameter positions. The b* wildcard can be used for all estimates.
      • Examples: "b0 = b1", "hp + drat = 12", "b* / b0 = 1".
    • Comparison Strings:
      • "pairwise" / "revpairwise": Pairwise differences between estimates in each row.
      • "reference" / "revreference": Differences between estimates and the first row.
      • "sequential" / "revsequential": Differences between an estimate and the next row.
    • List of Strings: Multiple hypotheses evaluated in sequence (results are stacked).
    • Numpy Array: A vector of weights where the output is the dot product of the weights and the estimates.
  8. Compare predictions with comparisons() and avg_comparisons()

    main

    The comparisons() and avg_comparisons() functions allow you to predict an outcome variable at different regressor values and compare those predictions using differences, ratios, or other functions (e.g., risk ratios, log odds, lift, slopes, elasticities).

    • comparisons(): Computes unit-level (conditional) estimates. It returns a comparison for every observation or grid point specified.
    • avg_comparisons(): Computes average (marginal) estimates. It aggregates unit-level estimates to provide a single summary statistic per term or group.

    Key parameters to control these comparisons:

    • variables: Identifies the focal regressors of interest.
    • comparison: Determines the mathematical method used to compare predictions (e.g., "difference", "ratio").
    • newdata: Controls where statistics are evaluated (e.g., at observed values, at the mean, or on a custom grid).
    # Unit-level comparisons
    comparisons(model, variables = c("x1", "x2"), comparison = "difference")
    
    # Average (marginal) comparisons
    avg_comparisons(model, variables = c("x1", "x2"), comparison = "difference")
  9. Compare predictions with different regressor values

    main

    The comparisons() and avg_comparisons() functions allow you to calculate the difference in predicted outcomes between different values of regressors. You can specify how these values are chosen using the newdata argument or by providing specific values via datagrid().

    Common ways to specify newdata include:

    • "mean": Contrasts at the mean of the predictors.
    • "balanced": Contrasts between marginal means.
    • datagrid(...): User-specified values for regressors.
    • "unique" or "max": Special values used within datagrid() to represent unique values or maximum values of a variable.
    # Contrasts at the mean
    comparisons(mod, newdata = "mean")
    
    # Contrasts between marginal means
    comparisons(mod, newdata = "balanced")
    
    # Contrasts at user-specified values
    comparisons(mod, newdata = datagrid(am = 0, gear = tmp$gear))
  10. Perform Equivalence, Inferiority, and Superiority tests

    main

    The equivalence argument allows for hypothesis testing regarding the bounds $[a, b]$ of an estimate $\theta$ with standard error $\sigma_\theta$.

    • Non-inferiority: Tests $H_0: \theta \leq a$ against $H_1: \theta > a$. The p-value is the upper-tail probability of $t = (\theta - a)/\sigma_\theta$.
    • Non-superiority: Tests $H_0: \theta \geq b$ against $H_1: \theta < b$. The p-value is the lower-tail probability of $t = (\theta - b)/\sigma_\theta$.
    • Equivalence (TOST): Uses Two One-Sided Tests. The p-value is the maximum of the non-inferiority and non-superiority p-values.
  11. Perform Equivalence, Non-Inferiority, and Non-Superiority tests

    main

    These tests use the equivalence argument to perform Two One-Sided Tests (TOST) or directional tests.

    Arguments

    • equivalence: A numeric vector of length 2 representing the bounds $[a, b]$.

    Test Logic

    • Non-inferiority: Tests if $\theta > a$. Null hypothesis $H_0: \theta \leq a$.
    • Non-superiority: Tests if $\theta < b$. Null hypothesis $H_0: \theta \geq b$.
    • Equivalence (TOST): The p-value is the maximum of the non-inferiority and non-superiority p-values.

    Note: For Bayesian models, this reports the proportion of posterior draws in the interval and the ROPE (Region of Practical Equivalence).

    # Equivalence test with bounds 17 and 18
    p <- predictions(mod, newdata = "median")
    hypotheses(p, equivalence = c(17, 18))
    
    # Equivalence test on average slopes
    mfx <- avg_slopes(mod, variables = "hp")
    hypotheses(mfx, equivalence = c(-.1, .1))