Skip to content

Tobit

Tobit estimates a censored normal (Tobit) regression model by maximum likelihood. The observed dependent variable y is a continuous latent regression y* = x'β + ε (ε ~ N(0, σ²)) censored at a lower bound, an upper bound, or both. It shares the general maximum-likelihood API shape with Logit (data/y/x/options constructor, .fit(), z-tests, cov_type, marginal_effects(), predict()), but y is continuous rather than 0/1, σ is reported as an estimated parameter, and the results add censoring_fit_check() in place of pred_table().

Censoring bounds

TobitOptions.lower (default 0.0) and TobitOptions.upper (default None) set the censoring bounds; None means that side is not censored. The default is the standard left-censored-at-zero Tobit. For a right-censored-only model, pass lower=None explicitly. fit() raises ValidationError if both bounds are None, if lower >= upper, or if any y value falls outside the given bounds, and also if no observation lies strictly inside the bounds (the model is then unidentified).

TobitResults.lower / .upper echo back the bounds actually used.

Standard error types

TobitOptions.cov_type supports "classical" (observed-information / Hessian-based), "opg" (outer product of gradients), "hc0", "hc1", and "cluster" (requires cluster). As with Logit, HC2/HC3 and HAC are not available. Internally the optimizer works in (β, log σ) space; the reported covariance is transformed to (β, σ) space so that TobitResults.std_errors includes a standard error for sigma alongside the coefficients. param_names is ["const", <x…>, "sigma"].

Overall significance test

TobitResults.wald_statistic / wald_p_value report a Wald test of the joint hypothesis that all non-intercept coefficients are zero (chi-square distributed, matching AER::tobit). Tobit does not provide a likelihood-ratio statistic or a pseudo-R², because the intercept-only Tobit model has no closed-form log-likelihood.

Solver options

TobitOptions.solver selects the optimization algorithm: "newton" (default, Newton-Raphson with a Levenberg-Marquardt damped step for the indefinite-Hessian regions specific to the (β, log σ) likelihood), "bfgs", or "lbfgs". All three converge to the same maximum-likelihood estimate. max_iter and tol control the iteration limit and the gradient-norm convergence threshold. When the solver does not converge within max_iter iterations, a ComputationError is raised unless raise_on_non_convergence=False, in which case TobitResults.converged is False instead.

Marginal effects and predictions

TobitResults.marginal_effects() and predict() both take a target:

target Quantity
"expected_latent" E[y*\|x] = x'β (the linear predictor)
"expected_observed" (default) E[y\|x], the censoring-adjusted conditional mean (McDonald–Moffitt)
"prob_uncensored" P(uncensored\|x)

marginal_effects() computes dy/dx with delta-method standard errors, evaluated at "overall" (average marginal effects, the default), "mean", or "median"; the constant term is excluded. predict() returns row-oriented fitted values for the training data (in-sample only). See Getting Started for an example.

Censoring fit check

TobitResults.censoring_fit_check() replaces pred_table(). For each censored direction it compares the observed censoring rate (fraction of y exactly at the boundary) against the model-implied rate (mean fitted boundary probability), returned as a per-direction breakdown ("lower" / "uncensored" / "upper").

econometricsmodels.Tobit(data, y, x, options=None)

Censored regression (Tobit) estimator.

Parameters:

Name Type Description Default
data DataFrame

A polars DataFrame containing the dependent and independent variables.

required
y str

Column name of the dependent variable. May be censored at options.lower/options.upper.

required
x list[str]

List of column names of the independent variables.

required
options TobitOptions | None

Estimation options. Defaults to TobitOptions() (classical, with intercept, Newton-Raphson, confidence_level=0.95, left-censored at 0.0) when omitted.

None

Examples:

>>> import polars as pl
>>> from econometricsmodels import Tobit
>>> df = pl.DataFrame({"y": [0.0, 1.0], "x1": [1.0, 2.0]})
>>> result = Tobit(df, y="y", x=["x1"]).fit()
>>> result.params["x1"]

fit()

Estimate the Tobit model by maximum likelihood.

Returns:

Type Description
TobitResults

The estimation results.

Raises:

Type Description
TypeError

An argument has the wrong type (for example x is a string instead of a list of column names). A builtin exception, not a ValidationError.

ValidationError

The input or options are invalid (a column is missing, contains missing values or NaN/infinity, y is outside the censoring bounds, the censoring bounds themselves are invalid, insufficient observations, no uncensored observations, confidence_level out of range, an unknown cov_type/solver string, an x column named "const"/"sigma", etc.). A subclass of ValueError.

ComputationError

A problem was detected during computation (e.g. non-convergence, a singular Hessian/OPG/design matrix). A subclass of RuntimeError.

econometricsmodels.TobitOptions

Estimation options for Tobit.

See docs/spec/tobit-spec.md for the rationale behind each field's meaning and default value.

cluster property

Column name to use as the cluster group key when cov_type="cluster". Refers to a column in data rather than being passed as a separate array. Specifying it with any other cov_type raises ValidationError.

confidence_level property

Confidence level for confidence intervals, in the range (0, 1). Defaults to 0.95 (a 95% confidence interval).

cov_type property

Standard error type: one of "classical", "opg", "hc0", "hc1", "cluster". Case-insensitive.

include_intercept property

Whether the engine should automatically add an intercept column. When true, a column of all 1.0 is prepended to the design matrix. If the user's x already contains a constant column while this is true, the resulting perfect collinearity raises ComputationError (singular design matrix).

lower property

Lower censoring bound. None means "no censoring from below". Defaults to 0.0 (the standard left-censored-at-zero Tobit model). At least one of lower/upper must be set (both None raises ValidationError).

max_iter property

Maximum number of solver iterations, an integer from 1 to 10,000 (anything else raises ValidationError).

raise_on_non_convergence property

If true (default), raise ComputationError when the solver fails to converge within max_iter iterations. If false, return the result at the final iterate instead (with converged=False).

solver property

Optimization solver: one of "newton" (default), "bfgs", "lbfgs". Case-insensitive.

tol property

Convergence tolerance. For solver="newton", an absolute threshold on the total gradient norm (default 1e-6). For solver="bfgs"/"lbfgs", a per-observation-average gradient threshold (the total gradient norm divided by the number of observations must fall below tol, default 1e-8), matching how statsmodels/scipy normalize convergence checks by nobs. The two defaults are not interchangeable: Newton's absolute semantics with a 1e-8 threshold (or bfgs/lbfgs's normalized semantics with a 1e-6 threshold) measurably degrades either speed or precision. Passing tol explicitly always uses the semantics of the chosen solver. For bfgs/lbfgs, the solver also reports convergence when the gradient norm is within 100 * tol of the target and the line search can no longer make progress because the log-likelihood has reached floating-point precision (common with very large samples); this window scales with tol, so it widens if you loosen tol. Note: the solver-dependent default is resolved once, at construction time. Changing solver afterwards via the setter does not re-resolve tol — set both together (or set tol explicitly) if you change solver after construction.

upper property

Upper censoring bound. None (default) means "no censoring from above".

econometricsmodels.TobitResults(raw)

Tobit estimation results.

Array-valued properties (params, std_errors, etc.) are exposed as dictionaries keyed by coefficient name (for O(1) lookup of a single parameter). They include an entry for "sigma" (the error term's standard deviation) in addition to the regression coefficients, since _lib.TobitResult reports sigma alongside beta in a unified (k+1)-length representation (see engine_pybind/src/nonlinear/tobit.rs, TobitResult). Use coef_table() for a row-oriented listing (docs/spec/nonlinear-common.md section 5).

marginal_effects(), predict(), and censoring_fit_check() are provided as separate methods rather than fields on this class (they depend on a representative point / prediction target not fixed at fit() time; see docs/spec/nonlinear-common.md section 6).

Parameters:

Name Type Description Default
raw TobitResult

The estimation result object returned by _lib.fit_tobit (_lib.TobitResult).

required
Note

Users normally do not construct this directly; it is returned by Tobit.fit().

aic property

Akaike Information Criterion (AIC).

bic property

Bayesian Information Criterion (BIC).

conf_int property

Coefficient name to confidence interval (lower, upper) (includes "sigma").

converged property

Whether the solver converged within max_iter iterations.

cov_type property

Standard error type actually used (normalized to lowercase).

dep_var_name property

Column name of the dependent variable.

df_model property

Model degrees of freedom (number of slope coefficients, excluding the intercept and sigma).

df_resid property

Residual degrees of freedom (n - (k + 1), where k + 1 includes sigma as an estimated parameter).

log_likelihood property

Log-likelihood at the fitted parameters.

lower property

Lower censoring bound actually used (echoes TobitOptions.lower). None means no censoring from below.

n_iter property

Actual number of solver iterations.

n_obs property

Number of observations.

p_values property

Coefficient name to two-sided p-value (includes "sigma").

param_names property

List of coefficient names ("const" first when include_intercept=True; "sigma" last).

params property

Coefficient name to coefficient value (includes "sigma").

sigma property

Point estimate of the error term's standard deviation.

Equal to params["sigma"]; provided as a convenience shortcut.

solver property

Optimization solver actually used (normalized to lowercase).

stat_df property

Degrees of freedom of the t distribution behind test_stats, or None when stat_dist is "normal". May differ from df_resid (e.g. cluster-robust inference uses G - 1), so use this to recompute p-values from test_stats.

stat_dist property

Distribution of test_stats: "t" (t-statistics) or "normal" (z-statistics).

std_errors property

Coefficient name to standard error (includes "sigma").

test_stats property

Coefficient name to z-statistic (includes "sigma").

Tobit uses a z-test (standard normal), not a t-test (see docs/spec/nonlinear-common.md section 4).

upper property

Upper censoring bound actually used (echoes TobitOptions.upper). None means no censoring from above.

wald_df property

Degrees of freedom of the chi-squared Wald test (wald_statistic). None when there are no slope coefficients.

wald_dist property

Distribution of wald_statistic: always "chi2" (chi-squared).

wald_p_value property

P-value of the Wald test (chi-squared distribution with df_model degrees of freedom). NaN when df_model == 0.

wald_statistic property

Wald test statistic for overall model significance (all slope coefficients jointly zero; the Tobit analogue of OLS's F-statistic and Logit/Probit's likelihood-ratio statistic).

NaN when df_model == 0 (no slope coefficients to test).

augment(new_data=None, target='expected_observed')

Source data with the predicted values appended as a column.

Same target/new_data semantics as predict(), but returns a polars DataFrame (the training data, or new_data when given, plus a new predicted-value column) instead of a row-oriented list. See OLSResults.augment() for the project's general policy on this DataFrame-returning exception.

Like Logit/Probit's fixed "predicted_probability" column, the appended column here has a predicted_ prefix and is named "predicted_{target}", using the lowercased target (e.g. target="expected_observed" or target="Expected_Observed" both produce "predicted_expected_observed"), since predict()'s meaning depends on target. This also lets augment() be called once per target on the same DataFrame without a name collision.

Parameters:

Name Type Description Default
new_data DataFrame | None

Same as predict(). If None (default), returns the training data used in fit() with the predicted values appended.

None
target str

Same as predict().

'expected_observed'

Returns:

Type Description
DataFrame

A polars DataFrame: the source data's columns plus

DataFrame

"predicted_{target}", in the same row order as the

DataFrame

source.

Raises:

Type Description
ValidationError

Same as predict(), or the source data already has a column named "predicted_{target}" (which would otherwise be silently overwritten).

censoring_fit_check()

Censoring goodness-of-fit check.

For each direction ("lower"/"uncensored"/"upper") that applies to this model, compares the observed rate (fraction of training observations exactly at that boundary) against the model-implied average probability. Replaces Logit/Probit's pred_table(), which is not meaningful for Tobit's continuous y (docs/spec/nonlinear-common.md section 6). A direction is omitted from the result when the corresponding TobitOptions.lower/upper was None (that direction has no censoring).

Returns:

Type Description
list[dict[str, float | str]]

A list of dictionaries, one per applicable category (at

list[dict[str, float | str]]

most 3: "lower", "uncensored", "upper"). Keys are

list[dict[str, float | str]]

category, observed_rate, model_implied_rate.

coef_table()

Row-oriented summary table of the coefficients.

Shaped to be usable almost as-is in a REST API response. Same shape as LogitResults.coef_table(). Includes a row for "sigma" in addition to the regression coefficients (see params).

Returns:

Type Description
list[dict[str, float | str]]

A list of dictionaries, one per coefficient (including

list[dict[str, float | str]]

"sigma"). Keys are param, coef, std_err, test_stat,

list[dict[str, float | str]]

p_value, conf_lower, conf_upper.

marginal_effects(at='overall', target='expected_observed', confidence_level=0.95)

Marginal effects (dy/dx) with delta-method standard errors.

Unlike Logit/Probit, this is Tobit's own implementation (not the shared dydx_and_jacobian pattern) because the formula differs per target (see docs/spec/nonlinear-common.md section 6). Independent of the confidence_level used in fit() (may differ from it). The constant term (intercept) is excluded from the output.

Parameters:

Name Type Description Default
at str

The representative point at which to evaluate the marginal effects. One of "overall" (default, average marginal effects), "mean", or "median". Case-insensitive.

'overall'
target str

Which quantity's marginal effect to compute. Same three values as predict(). Case-insensitive.

'expected_observed'
confidence_level float

Confidence level for the confidence interval, in the range (0, 1). Defaults to 0.95.

0.95

Returns:

Type Description
list[dict[str, float | str]]

A list of dictionaries, one per explanatory variable

list[dict[str, float | str]]

(excluding the intercept). Keys are param, effect,

list[dict[str, float | str]]

std_err, test_stat, p_value, conf_lower, conf_upper (see

list[dict[str, float | str]]

docs/spec/nonlinear-common.md section 6). test_stat is

list[dict[str, float | str]]

always a z-statistic (normal distribution). effect is

list[dict[str, float | str]]

the marginal effect estimate (corresponds to dy/dx in

list[dict[str, float | str]]

Stata's margins, dydx(*) and statsmodels).

Raises:

Type Description
ValidationError

at is not one of "overall", "mean", "median", target is not one of the three known values, or confidence_level is out of range. A subclass of ValueError.

predict(new_data=None, target='expected_observed')

Predicted values for target, on the training data or new_data.

Parameters:

Name Type Description Default
new_data DataFrame | None

New data to predict on. Must contain columns with the same names as the x columns passed at fit time (matched by name; column order does not matter). If include_intercept=True was used at fit time, the constant column is added automatically and must not be included here. If None (default), returns the predicted values for the training data used in fit().

None
target str

Which quantity to predict. One of "expected_latent" (E[y*|x] = x'β), "expected_observed" (default; E[y|x], the censoring-adjusted conditional expectation, directly comparable to the observed y), or "prob_uncensored" (P(uncensored|x)). Case-insensitive. Independent of new_data: the same three targets are available whether predicting on the training data or new data.

'expected_observed'

Returns:

Type Description
list[dict[str, float]]

Row-oriented predictions, one dict per observation. Each

list[dict[str, float]]

dict has a single key, "predicted".

Raises:

Type Description
ValidationError

target is not one of the three known values, or new_data is missing a required x column, or a column contains missing/NaN/infinite values. A subclass of ValueError.