ACD Transformations with mfp2

Package version 1.1.0

Edwin Kipruto, Michael Kammer, Patrick Royston, and Willi Sauerbrei

November 02, 2026

1 Overview

The approximate cumulative distribution (ACD) transformation provides a smooth way to model sigmoid-shaped relationships, including curves that level off at one or both ends (Royston, 2014). It approximates the empirical cumulative distribution function of a continuous predictor.

The MFPA extension combines this transformation with multivariable fractional polynomial (MFP) modelling (Royston and Sauerbrei, 2016). For a predictor selected for ACD assessment, mfp2() considers functions of both the original predictor and its ACD transformation. The usual function-selection procedure is replaced by the function-selection procedure with ACD transformation (FSPA). Other predictors continue through standard MFP selection during backfitting.

Request ACD assessment using:

Requesting ACD assessment allows the transformation to be considered; selection may still retain an ordinary FP1 or linear effect, or omit the predictor.

2 Definition of the ACD transformation

For observed predictor values \(x_1,\ldots,x_n\), the transformation has three steps. The description below assumes ordinary continuous data, without structural-zero handling.

2.1 Inverse normal transformation of ranks

First, convert the ranks to normal scores:

\[ z_i = \Phi^{-1}\left\{\frac{\operatorname{rank}(x_i)-0.5}{n}\right\}, \]

where \(\Phi^{-1}\) is the inverse standard normal cumulative distribution function. The package assigns average ranks to tied values. When all values are distinct, these scores approximate expected standard normal order statistics.

2.2 Power-linear approximation

Next, approximate the normal scores using a one-term FP regression. To include the logarithmic case explicitly, define

\[ h_p(u) = \begin{cases} \log(u), & p=0,\\ u^p, & p\ne 0. \end{cases} \]

The fitted approximation is

\[ \hat z_i = \hat a_0 + \hat a_1 h_q(x_i+s), \]

where \(s\) is the fitted shift and \(q\) is the best-fitting FP1 power. The default candidate set is

\[ S = \{-2,-1,-0.5,0,0.5,1,2,3\}. \]

The coefficients are estimated by ordinary least squares, and the power giving the best fit is selected. This preliminary regression uses the predictor values, not the outcome. User-supplied candidate powers for the predictor also apply to this step.

With automatic shifting, \(s=0\) when all values are positive; otherwise, a shift is chosen so that \(x_i+s>0\). Active ACD predictors are not scaled by the ordinary MFP scale factor in version 1.1.0.

2.3 Back-transformation to the interval (0, 1)

Finally, apply the standard normal cumulative distribution function:

\[ A(x_i) = \Phi(\hat z_i) = \Phi\{\hat a_0+\hat a_1 h_q(x_i+s)\}. \]

This gives a smooth approximation to the predictor’s empirical cumulative distribution. Once its parameters have been estimated, \(A(x)\) can be evaluated at new predictor values without recalculating their ranks. The fitted transformation is estimated once and reused during backfitting and prediction.

3 Interpretation

ACD values are approximately uniformly distributed between zero and one. They need not be exactly uniform, and the smallest and largest observed values need not map exactly to zero and one.

For illustration, consider an uncentred model with an identity link:

\[ \mu(x)=E(Y\mid X=x)=\beta_0+\beta_1 A(x). \]

At ACD values near zero, the fitted mean is near \(\beta_0\); at values near one, it is near \(\beta_0+\beta_1\). Thus, \(\beta_1\) is the signed change in the fitted mean for a one-unit increase in \(A(x)\). Across the actual observed predictor range, the fitted difference is

\[ \mu(x_{\max})-\mu(x_{\min}) =\beta_1\{A(x_{\max})-A(x_{\min})\}. \]

This difference is approximately \(\beta_1\) only when the observed ACD values cover nearly the whole interval. With other links, the same interpretation applies on the linear-predictor scale.

A linear effect of \(A(x)\) typically produces a sigmoid-shaped relationship with the original predictor. The transformation compresses the tails of its distribution, which can reduce the influence of extreme predictor values. It does not guarantee a particular response shape for every distribution or selected function.

4 ACD in the fractional polynomial family

The largest ACD-extended function combines one FP1 term in the shifted original predictor and one FP1 term in its ACD transformation:

\[ \beta_1 h_{p_1}(x+s)+\beta_2 h_{p_2}\{A(x)\}. \]

Following Royston and Sauerbrei (2016), this is denoted \(FP1(p_1,p_2)\). Here the notation represents two components, each containing one FP term. It differs from ordinary FP1 notation, which represents a single power term in one predictor.

The powers \(p_1\) and \(p_2\) are selected for the outcome model. They are separate from the power \(q\) used to construct \(A(x)\). The default power set gives \(8\times8=64\) candidate pairs. A power of zero denotes a logarithm through the definition of \(h_p\) above.

This family also permits simpler functions that omit either component. When both components are retained, the original-predictor term can add a trend, so the complete function need not level off at both ends.

5 Function-selection procedure for ACD (FSPA)

For each predictor requested for ACD assessment, the FSPA considers the following six candidate families. The notation omits the intercept, other predictors, and centring constants.

Six candidate model families considered by the FSPA.
Model Notation Function Interpretation
M1 \(FP1(p_1, p_2)\) \(\beta_1 h_{p_1}(x+s) + \beta_2 h_{p_2}(A_x)\) Most complex allowed ACD-extended function
M2 \(FP1(p_1, \cdot)\) \(\beta_1 h_{p_1}(x+s)\) Standard FP1 function of x
M3 \(FP1(\cdot, p_2)\) \(\beta_2 h_{p_2}(A_x)\) FP1 function of ACD(x)
M4 \(FP1(1, \cdot)\) \(\beta_1(x+s)\) Linear function of x
M5 \(FP1(\cdot, 1)\) \(\beta_2 A_x\) Linear function of ACD(x)
M6 \(FP1(\cdot, \cdot)\) Null model x omitted

Here \(A_x=A(x)\), and a dot indicates that the corresponding component is omitted. The families do not form a single nested sequence; for example, M2 and M3 use different components.

5.1 P-value selection

With criterion = "pvalue", the first comparison uses select and the remaining comparisons use alpha. For the Gaussian models used below, the sequence is:

  1. Compare M1 with M6 using 4 selection degrees of freedom. If the comparison is not significant, omit the predictor unless it is retained through keep or select = 1. Otherwise, continue.
  2. Compare M1 with M4 using 3 degrees of freedom. If the comparison is not significant, select the linear effect of the original predictor (M4) and stop.
  3. Compare M1 with M2 using 2 degrees of freedom. If the comparison is not significant, select the ordinary FP1 function (M2) and stop.
  4. Compare M1 with M3 using 2 degrees of freedom. If the comparison is significant, retain both components (M1) and stop. Otherwise, continue to the final comparison.
  5. Compare M3 with M5 using 1 degree of freedom. Select an FP1 function of ACD (M3) if the comparison is significant; otherwise, select a linear effect of ACD (M5).

The ordering favours a linear or ordinary FP1 function when it gives an adequate fit relative to the two-component function. ACD components are retained when those simpler forms do not adequately represent the relationship. The degrees of freedom include an allowance for selecting the outcome-model FP powers; model comparisons also account for family-specific coefficient counts where applicable.

Gaussian models use chi-square comparisons by default. Set ftest = TRUE to use F-tests. GEE models use Wald-based comparisons under p-value selection.

5.2 Information criteria

With criterion = "aic" or criterion = "bic", the six candidate families are compared directly, and the permitted model with the smallest criterion value is selected. The select and alpha significance levels do not control these comparisons. For GEE models, the corresponding scores are QICu and QBIC.

6 Simulation example

The following simulation creates a sigmoid relationship between x and a continuous outcome y, with random noise added to the mean.

set.seed(54)

n <- 500
x <- matrix(rnorm(n), ncol = 1, dimnames = list(NULL, "x"))

sigmoid <- function(x) {
  1 / (1 + exp(-1.7 * x))
}

y <- as.numeric(20 * sigmoid(x) + rnorm(n, mean = 0, sd = 0.5))

7 Fitting an ACD model

7.1 Matrix interface

Name the predictor in acd_vars to request ACD assessment. In this example, the response family defaults to Gaussian.

fit_acd_matrix <- mfp2(
  x, y,
  acd_vars = "x",
  verbose = FALSE
)

fit_acd_matrix$fp_terms
#>   df_setting df_initial select alpha  acd  zero catzero spike prop_zero spike_dec selected
#> x          4          4   0.05  0.05 TRUE FALSE   FALSE FALSE        NA         2     TRUE
#>   searched_fp df_final power1 power2
#> x        TRUE        4      1      1

7.2 Formula interface

Set acd = TRUE inside fp() to request the same assessment through the formula interface.

dat <- data.frame(y = y, x = as.numeric(x))

fit_acd_formula <- mfp2(
  y ~ fp(x, acd = TRUE),
  data = dat,
  verbose = FALSE
)

fit_acd_formula$fp_terms
#>   df_setting df_initial select alpha  acd  zero catzero spike prop_zero spike_dec selected
#> x          4          4   0.05  0.05 TRUE FALSE   FALSE FALSE        NA         2     TRUE
#>   searched_fp df_final power1 power2
#> x        TRUE        4      1      1

8 Comparison with standard MFP

For comparison, fit an ordinary MFP model to the same data without ACD assessment. Its default maximum complexity is FP2.

fit_standard <- mfp2(
  y ~ fp(x, acd = FALSE),
  data = dat,
  verbose = FALSE
)

fit_standard$fp_terms
#>   df_setting df_initial select alpha   acd  zero catzero spike prop_zero spike_dec selected
#> x          4          4   0.05  0.05 FALSE FALSE   FALSE FALSE        NA         2     TRUE
#>   searched_fp df_final power1 power2
#> x        TRUE        4      3      3

9 Plotting the fitted functions

Use plot() to compare the selected functions. Each panel shows the fitted contribution, pointwise 95% confidence intervals, and component-plus-residual points. Because each Gaussian model has only one predictor and an identity link, the fitted curve includes the intercept and the points correspond to the observed outcomes.

p1 <- plot(fit_acd_matrix, terms = "x")[[1]] +
  ggplot2::ylab("Partial predictor + residuals") +
  ggplot2::ggtitle("ACD model")

p2 <- plot(fit_standard, terms = "x")[[1]] +
  ggplot2::ylab("Partial predictor + residuals") +
  ggplot2::ggtitle("Standard MFP model")

patchwork::wrap_plots(p1, p2, ncol = 2)
ACD model compared with a standard MFP model.

ACD model compared with a standard MFP model.

Both models use the same simulated observations. Inspect the curves to see how each represents the central transition and the tails, rather than assuming that requesting ACD guarantees a better fit. The intervals are conditional on the selected model and do not account for uncertainty from variable or function selection.

10 Practical remarks

11 References

Royston, P. (2014). A smooth covariate rank transformation for use in regression models with a sigmoid dose-response function. Stata Journal, 14(2), 329–341.

Royston, P. and Sauerbrei, W. (2016). mfpa: Extension of mfp using the ACD covariate transformation for enhanced parametric multivariable modeling. Stata Journal, 16(1), 72–87.

Royston, P. and Sauerbrei, W. (2008). Multivariable Model-Building: A Pragmatic Approach to Regression Analysis Based on Fractional Polynomials for Modelling Continuous Variables. John Wiley & Sons.