fit_synthesizer: Fit a synthetic-data model

View source: R/synthesizer.R

fit_synthesizerR Documentation

Fit a synthetic-data model

Description

fit_synthesizer() learns a generative model from a data set. The model combines

  • a marginal model per column: an interpolated empirical quantile function for continuous variables (linear or monotone-spline interpolation between order statistics), and an empirical probability table for discrete, categorical, ordinal and logical variables. Interpolation means that synthetic values of a continuous variable lie between, rather than on, the observed values, always within the observed range. With small samples this slightly reduces the spread in the tails compared with the data;

  • a copula (Gaussian, Student-t or independence) that couples the columns. Discrete and categorical variables take part in the dependence structure: their pseudo-observations use the distributional transform, and their latent correlations are estimated by maximum likelihood (polyserial / polychoric), see Estimation details;

  • an optional missing-data model: for each column with missing values a missingness indicator is added to the copula, so that the rate of missingness and its (monotone) association with other variables are reproduced;

  • optional stratification (by), fitting separate models within groups, with a pooled fallback for small groups.

Use generate() to draw synthetic data from the fitted model, or synthesize() to fit and generate in one step.

Usage

fit_synthesizer(data, ...)

## S3 method for class 'data.frame'
fit_synthesizer(
  data,
  copula = c("gaussian", "t", "independence"),
  by = NULL,
  min_stratum_size = 20L,
  missing = c("joint", "independent", "drop"),
  interpolation = c("linear", "spline"),
  discrete_threshold = 20L,
  knots = NULL,
  id_cols = NULL,
  pd_method = c("auto", "higham", "eigen", "none"),
  seed = NULL,
  ...
)

## S3 method for class 'matrix'
fit_synthesizer(data, ...)

## Default S3 method:
fit_synthesizer(data, ...)

Arguments

data

A data frame, matrix, atomic vector (numeric, integer, logical, character, factor, Date, POSIXct) or ts object. Time series are handled by fit_synthesizer.ts().

...

Further arguments passed to methods.

copula

Dependence model: "gaussian" (default), "t" (heavier joint tails) or "independence". See Estimation details.

by

Optional character vector of column names used to stratify the model. Each stratum gets its own marginals and copula; strata are sampled in proportion to their training size.

min_stratum_size

Strata with fewer rows than this use a pooled model fitted on all rows.

missing

How missing values are treated: "joint" (default; model missingness inside the copula), "independent" (reproduce the missing rate of each column independently) or "drop" (do not reproduce missingness: partially observed columns are generated without missing values; a column with no observed training value has no distribution to draw from and necessarily stays entirely missing). Under "joint", missingness may depend on the other variables (missing at random); it cannot depend on the unobserved value itself, which the data do not identify (see Estimation details).

interpolation

Interpolation of the empirical quantile function for continuous variables: "linear" (default) or "spline" (monotone Hyman spline, smoother densities).

discrete_threshold

Numeric columns with at most this many distinct values are treated as discrete (sampled from their observed support), provided their values are whole numbers or actually repeat (fewer distinct values than half the observations). A small sample of a continuous variable is therefore still modelled as continuous.

knots

Optional maximum number of quantile knots stored per continuous column. NULL (default) keeps every observation; a smaller value shrinks the model and avoids storing the original values.

id_cols

Optional character vector of identifier columns. They are not modelled; synthetic data get fresh sequential identifiers.

pd_method

How to repair a correlation matrix that is not positive definite: "auto"/"higham" (nearest correlation matrix), "eigen" (eigenvalue flooring) or "none" (fail if not positive definite).

seed

Optional random seed for the fit. Fitting is stochastic (random tie-breaking and the randomised distributional transform used for the pseudo-observations, row subsampling for the t copula), so a seed makes the fitted model reproducible when fitting and generation are separate steps. The global random number generator state is restored afterwards. (synthesize() has its own seed, covering both steps.)

Value

An object of class sp_synthesizer.

Estimation details

Latent correlations. For a pair of continuous variables the Gaussian copula uses the normal scores \Phi^{-1}(U) and the t copula inverts Kendall's tau, \rho = \sin(\pi\tau/2). As Kendall's tau is quadratic in the sample size, it is computed on a random subsample of 2000 rows; a pair that the subsample leaves with fewer than \min(n_{ij}, 500) jointly observed rows is re-estimated from up to 2000 of its own n_{ij} joint rows, so every pair with n_{ij} \ge 3 is estimated whatever the subsample.

Discrete and categorical variables. The pseudo-observations of a discrete margin fill each category's probability interval with independent uniform noise (the distributional transform). Correlating these jittered scores would bias every dependence involving a discrete variable towards zero, most strongly for binary variables. Pairs with at least one discrete margin are therefore estimated by maximum likelihood under the Gaussian copula, with the thresholds fixed at the normal quantiles of the marginal cumulative probabilities: the polyserial correlation for a discrete-continuous pair (Olsson, Drasgow and Dorans, 1982) and the polychoric correlation for a discrete-discrete pair (Olsson, 1979), using the bivariate normal distribution function of Genz (2004). The t copula uses the same estimates for these pairs. Unordered categories enter in the order of their levels, which is also the order used when generating, so the estimate is the maximum likelihood estimate of the model actually fitted.

Missing data. All estimates use pairwise complete observations. The rows in which two variables are both observed may be a selected subset (e.g. y is observed mainly for low x), with a restricted range. For continuous pairs the estimate is therefore the pairwise covariance of the normal scores, scaled by each variable's standard deviation over all of its observed values (for the t copula, the tau-based correlation rescaled in the same way). This reproduces the relation among the observed rows under such selection; with complete data it equals the ordinary correlation. With missing = "joint", the missingness indicators are binary variables of the copula, so missingness can depend on the other variables (missing at random). The latent correlation between a variable and its own indicator is fixed at 0: the data do not identify it (the value is never seen when missing), and this choice keeps the distribution of the observed values of each variable as in the training data. Pairwise estimates based on different subsets of rows need not form a coherent joint estimate, and the resulting matrix need not be positive definite; it is then projected onto the set of valid correlation matrices according to pd_method (Higham's nearest correlation matrix by default). The projection guarantees a valid model, not an optimal joint estimator.

Unidentified pairs. If two variables are observed together in fewer than 3 rows (e.g. questions from different survey modules), their correlation cannot be estimated (with 2 rows it is trivially \pm 1); the same applies when the pairwise estimate is not finite. Such entries are not set to zero, which would assert independence and, through the projection, distort the identified entries. They are filled by the maximum-determinant positive-definite completion of the identified entries (Dempster, 1972), which keeps every identified correlation and makes the pair conditionally independent given the other variables. If the identified entries cannot be completed, the unknown entries fall back to 0. In either case the matrix may then still be modified by the positive-definiteness repair. A warning reports how many pairs were affected and how they were filled; copula_correlation(fit, what = "n_pair") gives the pairwise counts, and the fitted copula records the method (completion: "none", "maxdet" or "zero_fallback") and the largest change made by the repair (pd_adjustment), both shown by summary(). Pair counts and identification always refer to the full data.

t-copula degrees of freedom. With the correlation matrix held fixed, df is chosen by profile likelihood over the grid 2, 3, 4, 5, 6, 8, 10, 15, 20, 30, 50, 100 using the complete rows (at most 5000), so it is a discrete grid estimate rather than a continuous maximum likelihood estimate. If fewer than 10 complete rows are available, df is not estimated and is fixed at 10; a warning is issued and the fitted copula stores df_estimated = FALSE (see summary()).

References

Sklar, A. (1959). Fonctions de répartition à n dimensions et leurs marges. Publications de l'Institut de Statistique de l'Université de Paris, 8, 229–231.

Dempster, A. P. (1972). Covariance selection. Biometrics, 28(1), 157–175. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.2307/2528966")}

Genz, A. (2004). Numerical computation of rectangular bivariate and trivariate normal and t probabilities. Statistics and Computing, 14(3), 251–260. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1023/B:STCO.0000035304.20635.31")}

Olsson, U. (1979). Maximum likelihood estimation of the polychoric correlation coefficient. Psychometrika, 44(4), 443–460. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02296207")}

Olsson, U., Drasgow, F. and Dorans, N. J. (1982). The polyserial correlation coefficient. Psychometrika, 47(3), 337–347. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02294164")}

Rüschendorf, L. (2009). On the distributional transform, Sklar's theorem, and the empirical copula process. Journal of Statistical Planning and Inference, 139(11), 3921–3927. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1016/j.jspi.2009.05.030")}

Higham, N. J. (2002). Computing the nearest correlation matrix – a problem from finance. IMA Journal of Numerical Analysis, 22(3), 329–343. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/imanum/22.3.329")}

See Also

generate(), synthesize(), compare_synthetic()

Examples

fit <- fit_synthesizer(iris)
fit
syn <- generate(fit, n = 300, seed = 1)
head(syn)

# Stratified model and missing-data model
fit_aq <- fit_synthesizer(airquality, by = "Month")
colSums(is.na(generate(fit_aq, seed = 2)))

SynthesizerPlus documentation built on Oct. 16, 2026, 5:10 p.m.