Skip to content

R Python differences

Ivan Svetunkov edited this page Oct 22, 2026 · 8 revisions

R vs Python differences

The Python port is a numerical port: on the same data, the two implementations are expected to return the same estimates, not merely similar ones. Both optimise with NLopt (R through nloptr, Python through nlopt) from the same starting values, and the Python densities reproduce R's.

This page records where that holds and where it does not, as measured on the versions below. Re-run the scripts after upgrading either side. What exists in only one language is on Roadmap.

Versions measured

R side Version Python side Version
R 4.6.1 CPython 3.14.4
greybox 2.0.12 greybox 1.0.11
nloptr 2.2.1 nlopt 2.10.0
statmod 1.5.2 numpy 2.5.0
scipy 1.18.0
pandas 3.0.3
rpy2 3.6.9

Platform: Linux x86-64, glibc 2.43.

1. Where the two agree

Every example on the wiki pages is run in both languages, on identical data (written by R and read by Python where random numbers are involved). On those examples:

Quantity Measured on Agreement
ALM estimates, standard errors, information criteria, prediction intervals ALM: mpg ~ . with dlnorm, mpg ~ wt + hp with dnorm, dlaplace, LASSO, ROLE, a custom loss; AR(1) Same to the printed digits (4 decimals in the summaries, 6 in the intervals)
Selection path and selected model stepwise: mtcars IC path 209.1693, 166.8866, 158.2020, 156.4271, 157.9231 in both
Combined parameters, importance, intervals CALM Same to the printed digits
Information criteria of the candidate models AID 10 decimals (e.g. 307.70083267522057 in both)
Demand types, stockouts, new, obsolete AID, aidCat() Identical
Error measures measures, measures() All 16 identical to 4 decimals
Rolling-origin forecasts and holdouts rolling_origin Same to the printed digits
dgamma, dnorm, dlnorm log-densities distributions: 2000 random arguments each Bit-identical
supsmu(), lowess(), with and without tied x Smoothers Bit-identical
STI strengths EDA: AirPassengers 0.1061, 0.8613, 0.0326 in both
RMCB means, intervals, p-values RMCB: tukey, dnorm, dlnorm, dlaplace Same to 6 decimals

2. Where they differ

Item Difference See
RMCB with a general alm() The means and p-value match, but the interval widths can differ: R bootstraps the covariance matrix when the Hessian is inaccurate, Python always uses the Hessian. RMCB
Random draws r*() functions use NumPy's / SciPy's generators, so a seed does not reproduce R's draws. Examples that need random data generate it in R. distributions
Column names of lags Python names a lag B(x,1), R B(x, 1). manipulations

3. The parity test suite

The Python repository has tests that run R through rpy2 on the same inputs and compare the results. They need rpy2 and R with greybox; they are skipped otherwise.

Test file Covers
tests/test_r_python_compare.py Distribution functions.
tests/test_distributions_compare.py Distribution functions against the R sources of the repository.
tests/test_alm_distributions_compare.py ALM across the distributions.
tests/test_alm_parity_compare.py ALM estimates, counts, information criteria, losses, checks of the regressors, occurrence models.
tests/test_residuals_compare.py Standardised and studentised residuals, hat values, outliers.
tests/test_scale_compare.py Scale model: ALM(scale_formula=), sm(), implant().
tests/test_pointlik_compare.py point_lik().
tests/test_diagnostics_compare.py outlier_dummy().
tests/test_selection_compare.py stepwise(), CALM(), rolling_origin().
tests/test_measures_compare.py Point, interval and half-moment measures.
tests/test_association_compare.py association(), pcor(), mcor(), cramer(), determination(), determ().
tests/test_formula_compare.py formula() against model.frame() / model.matrix().
tests/test_xreg_compare.py xreg_expander(), xreg_transformer(), xreg_multiplier(), temporal_dummy().
tests/test_stick_compare.py stick() and rmcb().
tests/test_aid_compare.py aid(), aid_cat().
tests/test_bootstrap.py coefbootstrap().

On the versions above, these files give 2093 passed:

cd python
OMP_NUM_THREADS=1 .venv/bin/python -m pytest tests/test_*compare*.py tests/test_bootstrap.py -q

4. Interface differences

Topic R Python
Model fitting Formula interface: alm(y ~ x, data) scikit-learn style: ALM().fit(X, y), with formula() building (y, X)
Names camelCase (xregExpander) snake_case functions, PascalCase classes (xreg_expander, ALM); map on Home
Results lists read with $ objects read with .
Parameters of a model coef() includes the intercept coefficients includes it; coef excludes it (scikit-learn's coef_ convention)
Forecasting an AR model without regressors forecast(model, h) model.predict(np.ones((h, 1)))
Time series input ts objects carry the frequency arrays carry none: stick() requires lags, and xreg_expander() defaults to lags [-1, 0, 1]
rmcb() plot drawn unless outplot="none" never drawn by rmcb(); call result.plot()
Positions 1-based 0-based, except where a result reproduces R's positions (the stockouts of aid())
rolling_origin() call a string evaluated with data, h, counti, … a function of data, h and optionally counti, …

5. Reading a difference

Both languages run the same optimiser from the same starting values on the same likelihood, so a materially different optimum is not "optimiser noise". Evaluate the loss in both languages at identical parameter values: equal there means the starting values differ; different there means the two are not fitting the same model (data, regressors, distribution parameters).

Clone this wiki locally