Skip to content

Qrilc

fyt.imputations.qrilc

QRILCImputer

Bases: BaseEstimator, TransformerMixin

QRILC imputer (Quantile Regression Imputation of Left-Censored data).

Implemented as a scikit-learn transformer.

This implementation mimics the logic of the R function impute.QRILC from the imputeLCMD package. It estimates the distribution of the complete data (CDD) by fitting a linear model between the empirical quantiles of the observed data and the theoretical quantiles of a standard normal distribution. Missing values are then imputed by sampling from a truncated normal distribution based on the estimated parameters.

After fitting, the estimator exposes means_, sds_ and pnas_ — the per-feature estimated means, standard deviations, and fractions of missing values of the complete data distribution, each of shape (n_features,) — as well as n_features_in_ (number of features seen during fit) and feature_names_in_ (feature names, only defined when the input is a DataFrame).

Parameters:

Name Type Description Default
tune_sigma float

Coefficient that controls the standard deviation of the Missing Not At Random (MNAR) distribution. - tune_sigma = 1.0: The complete-data distribution is assumed to be Gaussian. - 0 < tune_sigma < 1: The complete-data distribution is assumed to be left-censored. Default is 1.0.

1.0
upper_q float

The upper quantile used for the quantile regression. This corresponds to the upper.q parameter in the R implementation. Default is 0.99.

0.99
random_state int | None

Controls the randomness of the imputation. Pass an int for reproducible results. Default is None.

None
apply_log_transform bool

If True, apply log transformation before imputation. Default is False.

False
apply_inverse_log_transform bool

If True, apply inverse log transformation (exp) after imputation, returning data in the original space with observed values preserved exactly. If False while apply_log_transform is True, the OUTPUT IS IN LOG SPACE (observed values included). Default is False.

False
axis int

Axis along which to impute. - 0: Impute within features (across samples) - default behavior. Each feature's distribution is estimated from all samples during fit(). The same distributions are applied to new samples in transform(). - 1: Impute within samples (across features). Each sample's distribution is estimated independently from its features. NOTE: When axis=1, transform() will refit on the provided data since each sample has its own unique distribution and training sample distributions don't apply to new samples. Default is 0.

0

fit(X, y=None)

Fit the QRILC model on X.

Parameters:

Name Type Description Default
X array - like or DataFrame

Input data with missing values encoded as np.nan. Shape (n_samples, n_features).

required
y Ignored

Not used, present for API consistency by convention.

None

Returns:

Name Type Description
self QRILCImputer

Fitted estimator.

Note

When axis=0 (default): Fits distribution parameters for each feature across samples. When axis=1: Fits distribution parameters for each sample across features. For axis=1, transform() computes per-sample parameters from the incoming data locally (sample distributions don't transfer between datasets) but never overwrites the fitted state.

transform(X)

Impute missing values in X using the fitted QRILC model.

Parameters:

Name Type Description Default
X array - like or DataFrame

Data to transform. Must have the same number of features as the data passed to fit. Shape (n_samples, n_features).

required

Returns:

Name Type Description
X_imputed ndarray or DataFrame

Data with imputed values. Shape (n_samples, n_features). Returns pl.DataFrame if input is pl.DataFrame.

Raises:

Type Description
ValueError

If axis=0 and X has a different number of features than the data the imputer was fitted with.

Note

When axis=1 (sample-level imputation), the censored-normal parameters are computed from the provided data itself (each sample has its own distribution across features), WITHOUT touching the fitted state — transform never mutates the estimator.

Each call uses a fresh RNG seeded from random_state, so transform is deterministic and idempotent regardless of call order.