# mtest: a nonparametric bootstrap to assess multicollinearity via two rules:
- **Klein's rule**: compares global R² vs auxiliary R² for each predictor.
- **VIF rule**: flags when the auxiliary R² of a predictor exceeds a threshold.
## Install (local)
```bash
pip install -e .
```
## Quickstart
```python
import numpy as np
from mtest import mtest
rng = np.random.default_rng(0)
n, p = 500, 4
X = rng.normal(size=(n, p))
beta = np.array([1, 0.5, 0.0, 0.0])
y = X @ beta + rng.normal(scale=1.0, size=n)
res = mtest(X, y, n_boot=500, r2_threshold=0.9, seed=2025)
print(res["p_vif"]) # dict per predictor
print(res["p_klein"]) # dict per predictor
```
## API
```python
mtest(X, y, n_boot=1000, nsam=None, r2_threshold=0.9, seed=None, return_distributions=True)
```
- `X`: array-like `(n, p)` predictors. Intercept is **not** added automatically.
- `y`: array-like `(n,)` response.
- `n_boot`: bootstrap replicates.
- `nsam`: bootstrap sample size (default: `n`).
- `r2_threshold`: threshold **on auxiliary R²** used for VIF rule.
- `seed`: RNG seed.
- `return_distributions`: if `True`, returns bootstrap arrays.
**Return**: dict with keys
- `R2_global`, `R2_aux` (original sample),
- `VIF` (original sample),
- `B_R2_global` `(n_boot,)`,
- `B_R2_aux` `(n_boot, p)`, columns aligned with predictors,
- `p_vif` (dict), `p_klein` (dict).
## Notes
- For the VIF rule we use `Pr(R²_j > r2_threshold)` — pass `r2_threshold` accordingly.
- Klein's rule p-value is `Pr(R²_global < R²_j)` across bootstrap replicates.
- Numerical stability: we use least squares and guard divisions-by-zero.
MIT License.
Raw data
{
"_id": null,
"home_page": null,
"name": "mtest-py",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "multicollinearity, bootstrap, VIF, Klein, regression, statistics",
"author": "V\u00edctor Morales-O\u00f1ate",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/9f/ea/c0d3bde107834fb5eb500621b0f8ba1d01073e27dc9c7ab69eed9f81c411/mtest_py-0.1.1.tar.gz",
"platform": null,
"description": "# mtest: a nonparametric bootstrap to assess multicollinearity via two rules:\n\n- **Klein's rule**: compares global R\u00b2 vs auxiliary R\u00b2 for each predictor.\n- **VIF rule**: flags when the auxiliary R\u00b2 of a predictor exceeds a threshold.\n\n## Install (local)\n\n```bash\npip install -e .\n```\n\n## Quickstart\n\n```python\nimport numpy as np\nfrom mtest import mtest\n\nrng = np.random.default_rng(0)\nn, p = 500, 4\nX = rng.normal(size=(n, p))\nbeta = np.array([1, 0.5, 0.0, 0.0])\ny = X @ beta + rng.normal(scale=1.0, size=n)\n\nres = mtest(X, y, n_boot=500, r2_threshold=0.9, seed=2025)\nprint(res[\"p_vif\"]) # dict per predictor\nprint(res[\"p_klein\"]) # dict per predictor\n```\n\n## API\n\n```python\nmtest(X, y, n_boot=1000, nsam=None, r2_threshold=0.9, seed=None, return_distributions=True)\n```\n- `X`: array-like `(n, p)` predictors. Intercept is **not** added automatically.\n- `y`: array-like `(n,)` response.\n- `n_boot`: bootstrap replicates.\n- `nsam`: bootstrap sample size (default: `n`).\n- `r2_threshold`: threshold **on auxiliary R\u00b2** used for VIF rule.\n- `seed`: RNG seed.\n- `return_distributions`: if `True`, returns bootstrap arrays.\n\n**Return**: dict with keys\n- `R2_global`, `R2_aux` (original sample),\n- `VIF` (original sample),\n- `B_R2_global` `(n_boot,)`,\n- `B_R2_aux` `(n_boot, p)`, columns aligned with predictors,\n- `p_vif` (dict), `p_klein` (dict).\n\n## Notes\n\n- For the VIF rule we use `Pr(R\u00b2_j > r2_threshold)` \u2014 pass `r2_threshold` accordingly.\n- Klein's rule p-value is `Pr(R\u00b2_global < R\u00b2_j)` across bootstrap replicates.\n- Numerical stability: we use least squares and guard divisions-by-zero.\n\nMIT License.\n",
"bugtrack_url": null,
"license": null,
"summary": "A Procedure for Multicollinearity Testing using Bootstrap",
"version": "0.1.1",
"project_urls": {
"Homepage": "https://github.com/vmoprojs/mtest-py",
"Issues": "https://github.com/vmoprojs/mtest-py/issues"
},
"split_keywords": [
"multicollinearity",
" bootstrap",
" vif",
" klein",
" regression",
" statistics"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "5caa24b2cdf43c0f75fe903138a1ac38122c9a18988f4a5706804c8ff5414320",
"md5": "b2be2a90c67caaeddd3c5e9e2662f15b",
"sha256": "8a8e4c557c4b6cc513212beef6a60555f945e26adb421d6164af041b105febb9"
},
"downloads": -1,
"filename": "mtest_py-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b2be2a90c67caaeddd3c5e9e2662f15b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 8512,
"upload_time": "2025-09-12T05:31:35",
"upload_time_iso_8601": "2025-09-12T05:31:35.200727Z",
"url": "https://files.pythonhosted.org/packages/5c/aa/24b2cdf43c0f75fe903138a1ac38122c9a18988f4a5706804c8ff5414320/mtest_py-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "9feac0d3bde107834fb5eb500621b0f8ba1d01073e27dc9c7ab69eed9f81c411",
"md5": "73841e53367d11be526967e95fb64c15",
"sha256": "8768065dafc16b6f439e353a2d99b9d99d1a1f179bed0507c566cf3a55298a40"
},
"downloads": -1,
"filename": "mtest_py-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "73841e53367d11be526967e95fb64c15",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 10663,
"upload_time": "2025-09-12T05:31:36",
"upload_time_iso_8601": "2025-09-12T05:31:36.515445Z",
"url": "https://files.pythonhosted.org/packages/9f/ea/c0d3bde107834fb5eb500621b0f8ba1d01073e27dc9c7ab69eed9f81c411/mtest_py-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-12 05:31:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "vmoprojs",
"github_project": "mtest-py",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "mtest-py"
}