Generated: 2026-08-17 14:51:03 UTC
Python analog of benchmark_model_fits_R.html —
same three tables (point-estimate, Wald/full-inference, utility math kernels), same table shape,
same three-color row coding. Produced by R/benchmark/benchmark_model_fits_python.py.
EDI's C++ model-fitting kernels are bound to Python in the edi_kernels
package under python/ (released on PyPI — see
R/package_metadata/python_bindings_package_spec.md). This script does not
own or edit that package; at the top of every run it configures and builds its
_core pybind11 module (via CMake, into an isolated /tmp directory)
and imports whatever compiles, so the EDI Time column reflects the real
state of the bindings at run time rather than a stale snapshot — different runs of this
script can show different EDI coverage as the bindings evolve, and a build failure there
simply leaves every EDI column NA (not a crash of this script). Point-estimate
rows with a working, wired binding call it directly; rows where the Wald table needs
standard errors the bindings don't yet expose stay NA. Same-input,
same-process discipline: for every wired row, both the EDI and canonical closures are built
from the exact same generated arrays (never redrawn separately). Each side is timed at its
own fastest available point-estimate-only entry point — the same convention the R report
already uses (R's canonical glm.fit() point-estimate row likewise never forms
the explicit variance-covariance matrix; that only happens in the separate Wald table). EDI
rows therefore use estimate_only=True where that argument exists. Where
statsmodels' public API has no equivalent cheaper mode — .fit() is the only
entry point it exposes, full stop — the canonical column still reflects .fit()'s
real, honest cost: that is genuinely the fastest a Python user can get this model fit today,
not a handicap imposed on canonical Python. (Checked directly: statsmodels' .fit()
doesn't secretly race ahead by skipping something EDI bothers to compute — accessing
.bse after .fit() costs no measurable additional time, since IRLS's
per-iteration weighted-least-squares solve already forms the same (X'WX)⁻¹ a
covariance estimate would need; the two APIs just draw the "point estimate vs. full inference"
line in different places.)
scale = 0.5); 5,000 elements for the utility-function vectors.benchmark_model_fits.R (logistic/log-binomial/identity-binomial links, Poisson mean model, Beta(mu*phi, (1-mu)*phi) proportions, exponential survival times with ~20% censoring, 3-level ordinal construction)..fit()/equivalent directly on pre-built NumPy arrays (or, where the package requires it — lifelines, statsmodels.OrderedModel internals — a pre-built pandas.DataFrame), inside the timed region only; data generation happens once, outside the timed closure.lstsq instead of OLS().fit() where that's a real, distinct fast path); the Wald table times a full fit that also produces the treatment coefficient's standard error and two-sided p-value (.bse/.pvalues off the same fitted result for most statsmodels families; a package switch to lifelines.CoxPHFitter for the unstratified-Cox row specifically, since scikit-survival's bare-metal CoxPHSurvivalAnalysis doesn't expose a variance; a finite-difference delta-method SE for the four G-computation rows, off .cov_params()). The Wald table's row set follows R's wald_specs rather than reusing the point-estimate table's — it adds several nonparametric-test-only classes with no point-estimate-table row at all (Lin's estimator, Miettinen-Nurminen/Newcombe risk-difference CIs, Jonckheere-Terpstra, Ridit, Gehan-Wilcoxon, KM median difference) and omits several point-estimate-table rows that R's own Wald table never covers (identity-binomial, modified Poisson, fractional logit, ordered probit, cauchit, cloglog). Classes with no EDI C++ kernel at all — the EDI R class delegates to base R or a CRAN package (quantile regression via quantreg::rq, the pooled-variance t-test, the Wilcoxon rank-sum test itself, Fisher exact) — are omitted from both tables entirely: with no EDI side to time, a permanently-NA row carries no information. One row, restricted-mean-survival-time difference, is excluded from the Wald table for the same reason R's own Wald table excludes it — see below.benchmark/fast_math_utils_bench.cpp's apples-to-apples vectorized-vs-vectorized discipline (the EDI side likewise calls the vectorized elementwise wrappers exposed by python/cpp/bindings_fast_math.cpp, never a Python-level scalar loop).time.perf_counter harness (mirrors the R harness's adaptive system.time split, target 200ms/batch).scipy.stats.ttest_ind(..., equal_var=False)) between the EDI and canonical timing replicate distributions — real for any row with a wired, working EDI binding; NA for rows where no binding is wired or available.Speedup > 1 and Timing Pval < 0.05; light grey = NA timing comparison (EDI not bound yet, or a fit failed); light blue = no canonical Python implementation exists at all for this model family/function.EDI faster, significant NA timing comparison no canonical Python implementation
Families with no clean, actively-maintained Python canonical equivalent — an absent/NA comparison here is more honest than a mismatched substitute baseline (same discipline python_bindings_package_spec.md and the R report apply):
InferenceContinKKGLMM (future kernel fast_gaussian_lmm): Gaussian LMM with a random intercept, fit via MLE: statsmodels' MixedLM uses REML/a different estimation path by default and isn't a direct like-for-like timing comparison -- see python_bindings_package_spec.md Baseline Gaps.InferenceCountKKCondPoissonOneLik (future kernel fast_cpoisson_combined): KK combined (matched-pair + reservoir) joint-likelihood estimator: no canonical analog in either R or Python.InferenceCountKKGLMM (future kernel fast_poisson_glmm): Poisson GLMM with a random intercept, fit via adaptive Gauss-Hermite quadrature + MLE: no pure-Python package offers a comparable ML (not variational/Bayesian) GLMM fitter -- see python_bindings_package_spec.md Baseline Gaps.InferenceCountKKHurdlePoissonOneLik (future kernel fast_hurdle_poisson_glmm): Hurdle-Poisson GLMM with a random intercept: no pure-Python package combines a hurdle count model with adaptive-quadrature GLMM fitting.InferenceIncidKKCondLogitGLMMOneLik (future kernel fast_clogit_plus_glmm): KK combined (matched-pair + reservoir) joint-likelihood estimator: no canonical analog in either R or Python (see python_bindings_package_spec.md Baseline Gaps).InferenceOrdinalAdjCatLogitRegr (future kernel fast_adjacent_category_logit): No identified Python package implements the adjacent-category logit link (R uses VGAM::vglm(acat())).InferenceOrdinalCauchitRegr (future kernel fast_ordinal_cauchit_regression): Same as cloglog: OrderedModel's distr= only documents 'probit'/'logit'.InferenceOrdinalCloglogRegr (future kernel fast_ordinal_cloglog_regression): statsmodels.miscmodels.ordinal_model.OrderedModel's distr= argument only officially supports 'probit'/'logit' strings; cloglog is not a documented/tested option, so this is treated as a gap rather than an unverified custom-distribution hack.InferenceOrdinalContRatioRegr (future kernel fast_continuation_ratio_regression): No identified Python package implements the continuation-ratio link (R uses VGAM::vglm(cratio())).InferenceOrdinalKKCLMM (future kernel fast_ordinal_clmm): Same as InferenceOrdinalKKGLMM, generalized to logit/probit/cauchit/cloglog links.InferenceOrdinalKKGLMM (future kernel fast_ordinal_glmm): Proportional-odds ordinal GLMM with a random intercept: no pure-Python package offers ML ordinal-GLMM fitting with adaptive quadrature.InferenceOrdinalStereotypeLogitRegr (future kernel fast_stereotype_logit): Stereotype logit ordinal regression: R uses VGAM::vglm(multinomial(...)) style fitting; no identified Python package implements the stereotype-logit link specifically.InferencePropZeroOneInflatedBetaRegr (future kernel fast_zero_one_inflated_beta): Zero-one-inflated beta regression: no canonical package in either R or Python.InferenceSurvivalKKWeibullFrailtyOneLik (future kernel fast_weibull_frailty): Weibull AFT with shared log-normal frailty: no clean Python package (R side notes only a partial/PH-parameterized frailtypack analog).| Class | Response | EDI Time (ms) | Canonical Pkg | Canonical Func | Canonical Time (ms) | Speedup | Timing Pval | |
|---|---|---|---|---|---|---|---|---|
| InferenceAllSimpleWilcox | continuous | 0.15 | numpy | median(HL pairwise diff) | 0.61 | 4.00x | 5.61e-31 | *** |
| InferenceContinKKGLMM | continuous | NA | None | NA | NA | NA | ||
| InferenceContinOLS | continuous | 0.02 | numpy | linalg.lstsq | 0.08 | 4.44x | 4.02e-27 | *** |
| InferenceContinRobustRegr | continuous | 0.10 | statsmodels | RLM | 8.13 | 77.85x | 2.21e-28 | *** |
| InferenceCountHurdleNegBin | count | 1.59 | statsmodels | HurdleCountModel(negbin) | 89.63 | 56.33x | 4.72e-29 | *** |
| InferenceCountHurdlePoisson | count | 0.98 | statsmodels | HurdleCountModel(poisson) | 27.71 | 28.21x | 3.18e-27 | *** |
| InferenceCountKKCondPoissonOneLik | count | NA | None | NA | NA | NA | ||
| InferenceCountKKGLMM | count | NA | None | NA | NA | NA | ||
| InferenceCountKKHurdlePoissonOneLik | count | NA | None | NA | NA | NA | ||
| InferenceCountNegBin | count | 0.64 | statsmodels | NegativeBinomial | 12.05 | 18.90x | 1.18e-29 | *** |
| InferenceCountPoisson | count | 0.11 | statsmodels | GLM(Poisson) | 2.67 | 24.70x | 4.45e-30 | *** |
| InferenceCountQuasiPoisson | count | 0.10 | statsmodels | GLM(Poisson) | 2.64 | 27.16x | 1.55e-31 | *** |
| InferenceCountRobustPoisson | count | 0.08 | statsmodels | GLM(Poisson) | 2.40 | 29.38x | 4.13e-29 | *** |
| InferenceCountZeroInflatedNegBin | count | 9.45 | statsmodels | ZeroInflatedNegativeBinomialP | 218.39 | 23.11x | 1.74e-30 | *** |
| InferenceCountZeroInflatedPoisson | count | 7.93 | statsmodels | ZeroInflatedPoisson | 39.63 | 5.00x | 5.63e-25 | *** |
| InferenceIncidBinomialIdentityRiskDiff | incidence | 0.12 | statsmodels | GLM(Binomial, identity link) | 5.83 | 48.07x | 9.04e-30 | *** |
| InferenceIncidGCompRiskDiff | incidence | 0.24 | statsmodels | GLM(Binomial)+gcomp(RD) | 2.63 | 11.16x | 7.72e-27 | *** |
| InferenceIncidGCompRiskRatio | incidence | 0.22 | statsmodels | GLM(Binomial)+gcomp(RR) | 2.71 | 12.15x | 2.85e-28 | *** |
| InferenceIncidKKCondLogitGLMMOneLik | incidence | NA | None | NA | NA | NA | ||
| InferenceIncidLogBinomial | incidence | 0.89 | statsmodels | GLM(Binomial, log link) | 10.48 | 11.76x | 2.5e-16 | *** |
| InferenceIncidLogRegr | incidence | 0.18 | statsmodels | GLM(Binomial) | 2.52 | 13.71x | 5e-33 | *** |
| InferenceIncidModifiedPoisson | incidence | 0.11 | statsmodels | GLM(Poisson) | 2.45 | 22.42x | 9.31e-30 | *** |
| InferenceIncidProbitRegr | incidence | 0.36 | statsmodels | GLM(Binomial, probit link) | 5.23 | 14.35x | 1.07e-25 | *** |
| InferenceIncidRiskDiff | incidence | 0.02 | numpy | linalg.lstsq (LPM) | 0.07 | 4.42x | 8.75e-21 | *** |
| InferenceOrdinalAdjCatLogitRegr | ordinal | 0.55 | None | NA | NA | NA | ||
| InferenceOrdinalCauchitRegr | ordinal | 0.68 | None | NA | NA | NA | ||
| InferenceOrdinalCloglogRegr | ordinal | 0.58 | None | NA | NA | NA | ||
| InferenceOrdinalContRatioRegr | ordinal | 0.19 | None | NA | NA | NA | ||
| InferenceOrdinalGCompMeanDiff | ordinal | 0.76 | statsmodels | OrderedModel(logit)+gcomp | 69.71 | 91.47x | 1.29e-31 | *** |
| InferenceOrdinalKKCLMM | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalKKGLMM | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalOrderedProbitRegr | ordinal | 0.57 | statsmodels | OrderedModel(probit) | 62.28 | 109.22x | 1.15e-24 | *** |
| InferenceOrdinalPropOddsRegr | ordinal | 0.70 | statsmodels | OrderedModel(logit) | 77.94 | 111.19x | 2.49e-28 | *** |
| InferenceOrdinalStereotypeLogitRegr | ordinal | NA | None | NA | NA | NA | ||
| InferencePropBetaRegr | proportion | 1.06 | statsmodels | BetaModel | 11.39 | 10.72x | 5.64e-31 | *** |
| InferencePropFractionalLogit | proportion | 0.11 | statsmodels | GLM(Binomial, fractional y) | 2.09 | 18.21x | 2.41e-27 | *** |
| InferencePropGCompMeanDiff | proportion | 0.17 | statsmodels | GLM(Binomial)+gcomp | 1.93 | 11.06x | 4.07e-32 | *** |
| InferencePropZeroOneInflatedBetaRegr | proportion | 4.66 | None | NA | NA | NA | ||
| InferenceSurvivalCoxPHRegr | survival | 0.38 | scikit-survival | CoxPHSurvivalAnalysis | 34.75 | 90.41x | 1.38e-22 | *** |
| InferenceSurvivalKKWeibullFrailtyOneLik | survival | NA | None | NA | NA | NA | ||
| InferenceSurvivalKMDiff | survival | 0.01 | lifelines | KaplanMeierFitter(median) | 14.82 | 1365.87x | 2.57e-29 | *** |
| InferenceSurvivalLogRank | survival | 0.08 | lifelines | statistics.logrank_test | 16.24 | 209.33x | 3.63e-27 | *** |
| InferenceSurvivalRestrictedMeanDiff | survival | 0.01 | lifelines | utils.restricted_mean_survival_time | 17.56 | 1603.59x | 2.49e-35 | *** |
| InferenceSurvivalStratCoxPHRegr | survival | 0.35 | lifelines | CoxPHFitter(strata=) | 152.53 | 432.83x | 5.82e-27 | *** |
| InferenceSurvivalWeibullRegr | survival | 0.12 | lifelines | WeibullAFTFitter.fit() (right-censored only) | 136.18 | 1169.57x | 2.29e-31 | *** |
| InferenceSurvivalWeibullRegr | survival | 0.37 | lifelines | WeibullAFTFitter.fit_interval_censoring() | 192.87 | 518.83x | 4.32e-31 | *** |
32 of 46 rows have a working canonical Python timing; 0 canonical fit(s) failed on this run (see console log); 14 are documented Baseline Gaps.
EDI faster, significant NA timing comparison no canonical Python implementation
Same Baseline Gap families as the point-estimate table above, plus 1 row(s) excluded outright (no variance computation, not a Baseline Gap in the usual sense):
InferenceSurvivalRestrictedMeanDiff: Not in R's own Wald table either: lifelines' restricted_mean_survival_time (like R's survival:::survmean) returns only a point value; a variance requires a separate bootstrap-based computation, a different computational profile than every other Wald row here.InferenceContinKKGLMM (future kernel fast_gaussian_lmm): Gaussian LMM with a random intercept, fit via MLE: statsmodels' MixedLM uses REML/a different estimation path by default and isn't a direct like-for-like timing comparison -- see python_bindings_package_spec.md Baseline Gaps.InferenceCountKKCondPoissonOneLik (future kernel fast_cpoisson_combined_with_var): KK combined (matched-pair + reservoir) joint-likelihood estimator: no canonical analog in either R or Python.InferenceCountKKGLMM (future kernel fast_poisson_glmm): Poisson GLMM with a random intercept, fit via adaptive Gauss-Hermite quadrature + MLE: no pure-Python package offers a comparable ML (not variational/Bayesian) GLMM fitter -- see python_bindings_package_spec.md Baseline Gaps.InferenceCountKKHurdlePoissonOneLik (future kernel fast_hurdle_poisson_glmm): Hurdle-Poisson GLMM with a random intercept: no pure-Python package combines a hurdle count model with adaptive-quadrature GLMM fitting.InferenceIncidKKCondLogitGLMMOneLik (future kernel fast_clogit_plus_glmm): KK combined (matched-pair + reservoir) joint-likelihood estimator: no canonical analog in either R or Python (see python_bindings_package_spec.md Baseline Gaps).InferenceOrdinalAdjCatLogitRegr (future kernel fast_adjacent_category_logit_with_var): No identified Python package implements the adjacent-category logit link (R uses VGAM::vglm(acat())).InferenceOrdinalContRatioRegr (future kernel fast_continuation_ratio_regression_with_var): No identified Python package implements the continuation-ratio link (R uses VGAM::vglm(cratio())).InferenceOrdinalJonckheereTerpstraTest (future kernel out of python-bindings scope (nonparametric-test kernel, EDI:::fast_jonckheere_terpstra_cpp)): No identified Python package implements the Jonckheere-Terpstra trend test (checked scipy, statsmodels, scikit-posthocs; R itself needs the specialty clinfun package, not base R either — no equally-specialized Python package was found).InferenceOrdinalKKCLMM (future kernel fast_ordinal_clmm): Same as InferenceOrdinalKKGLMM, generalized to logit/probit/cauchit/cloglog links.InferenceOrdinalKKGLMM (future kernel fast_ordinal_glmm): Proportional-odds ordinal GLMM with a random intercept: no pure-Python package offers ML ordinal-GLMM fitting with adaptive quadrature.InferenceOrdinalStereotypeLogitRegr (future kernel fast_stereotype_logit_with_var): Stereotype logit ordinal regression: R uses VGAM::vglm(multinomial(...)) style fitting; no identified Python package implements the stereotype-logit link specifically.InferencePropZeroOneInflatedBetaRegr (future kernel fast_zero_one_inflated_beta): Zero-one-inflated beta regression: no canonical package in either R or Python.InferenceSurvivalKKWeibullFrailtyOneLik (future kernel fast_weibull_frailty): Weibull AFT with shared log-normal frailty: no clean Python package (R side notes only a partial/PH-parameterized frailtypack analog).| Class | Response | EDI Time (ms) | Canonical Pkg | Canonical Func | Canonical Time (ms) | Speedup | Timing Pval | |
|---|---|---|---|---|---|---|---|---|
| InferenceContinKKGLMM | continuous | NA | None | NA | NA | NA | ||
| InferenceContinLin | continuous | 0.25 | statsmodels | OLS(interaction)+summary | 1.15 | 4.54x | 8.45e-22 | *** |
| InferenceContinOLS | continuous | 0.17 | statsmodels | OLS+summary | 0.59 | 3.42x | 4.84e-25 | *** |
| InferenceContinRobustRegr | continuous | 0.29 | statsmodels | RLM+summary | 5.83 | 20.20x | 3.24e-29 | *** |
| InferenceCountHurdleNegBin | count | 1.37 | statsmodels | HurdleCountModel(negbin)+summary | 86.02 | 62.90x | 6.37e-30 | *** |
| InferenceCountHurdlePoisson | count | 1.28 | statsmodels | HurdleCountModel(poisson)+summary | 26.91 | 21.02x | 1.08e-29 | *** |
| InferenceCountKKCondPoissonOneLik | count | NA | None | NA | NA | NA | ||
| InferenceCountKKGLMM | count | NA | None | NA | NA | NA | ||
| InferenceCountKKHurdlePoissonOneLik | count | NA | None | NA | NA | NA | ||
| InferenceCountNegBin | count | 0.78 | statsmodels | NegativeBinomial+summary | 13.28 | 17.09x | 2.39e-26 | *** |
| InferenceCountPoisson | count | 0.20 | statsmodels | GLM(Poisson)+summary | 2.68 | 13.40x | 6.18e-29 | *** |
| InferenceCountQuasiPoisson | count | 0.21 | statsmodels | GLM(Poisson)+summary | 2.78 | 13.27x | 3.5e-31 | *** |
| InferenceCountRobustPoisson | count | 0.22 | statsmodels | GLM(Poisson)+summary | 2.85 | 12.85x | 1.07e-31 | *** |
| InferenceCountZeroInflatedNegBin | count | 4.43 | statsmodels | ZeroInflatedNegativeBinomialP+summary | 216.05 | 48.73x | 1.05e-27 | *** |
| InferenceCountZeroInflatedPoisson | count | 12.07 | statsmodels | ZeroInflatedPoisson+summary | 35.84 | 2.97x | 8.69e-28 | *** |
| InferenceIncidGCompRiskDiff | incidence | 1.19 | statsmodels | GLM(Binomial)+gcomp(RD)+delta-method SE | 3.49 | 2.93x | 8.34e-30 | *** |
| InferenceIncidGCompRiskRatio | incidence | 1.17 | statsmodels | GLM(Binomial)+gcomp(RR)+delta-method SE | 3.27 | 2.79x | 4.2e-24 | *** |
| InferenceIncidKKCondLogitGLMMOneLik | incidence | NA | None | NA | NA | NA | ||
| InferenceIncidLogBinomial | incidence | 0.52 | statsmodels | GLM(Binomial, log link)+summary | 4.48 | 8.56x | 9.24e-31 | *** |
| InferenceIncidLogRegr | incidence | 0.26 | statsmodels | GLM(Binomial)+summary | 2.46 | 9.38x | 1.82e-26 | *** |
| InferenceIncidMiettinenNurminenRiskDiff | incidence | 0.03 | statsmodels | stats.proportion.confint_proportions_2indep(score) | 2.65 | 92.63x | 1.55e-27 | *** |
| InferenceIncidNewcombeRiskDiff | incidence | 0.000303 | statsmodels | stats.proportion.confint_proportions_2indep(newcomb) | 0.19 | 624.56x | 2.49e-24 | *** |
| InferenceIncidProbitRegr | incidence | 0.47 | statsmodels | GLM(Binomial, probit link)+summary | 4.45 | 9.45x | 7.71e-27 | *** |
| InferenceIncidRiskDiff | incidence | 0.18 | statsmodels | OLS+summary (LPM) | 0.61 | 3.40x | 5.2e-24 | *** |
| InferenceOrdinalAdjCatLogitRegr | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalContRatioRegr | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalGCompMeanDiff | ordinal | 2.92 | statsmodels | OrderedModel(logit)+gcomp+delta-method SE | 96.61 | 33.13x | 2.82e-29 | *** |
| InferenceOrdinalJonckheereTerpstraTest | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalKKCLMM | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalKKGLMM | ordinal | NA | None | NA | NA | NA | ||
| InferenceOrdinalPropOddsRegr | ordinal | 0.85 | statsmodels | OrderedModel(logit)+summary | 76.83 | 90.64x | 1.99e-29 | *** |
| InferenceOrdinalRidit | ordinal | 0.09 | numpy | manual ridit computation | 0.28 | 3.17x | 4.82e-22 | *** |
| InferenceOrdinalStereotypeLogitRegr | ordinal | NA | None | NA | NA | NA | ||
| InferencePropBetaRegr | proportion | 1.08 | statsmodels | BetaModel+summary | 8.36 | 7.77x | 5.39e-25 | *** |
| InferencePropGCompMeanDiff | proportion | 1.03 | statsmodels | GLM(Binomial)+gcomp+delta-method SE | 2.87 | 2.79x | 1.06e-26 | *** |
| InferencePropZeroOneInflatedBetaRegr | proportion | NA | None | NA | NA | NA | ||
| InferenceSurvivalCoxPHRegr | survival | 0.48 | lifelines | CoxPHFitter+summary | 64.13 | 134.51x | 1.99e-30 | *** |
| InferenceSurvivalGehanWilcox | survival | 0.08 | lifelines | statistics.logrank_test(weightings='wilcoxon') | 17.64 | 224.94x | 4.58e-31 | *** |
| InferenceSurvivalKKWeibullFrailtyOneLik | survival | NA | None | NA | NA | NA | ||
| InferenceSurvivalKMDiff | survival | 0.01 | lifelines | KaplanMeierFitter(median)+CI | 13.93 | 1267.95x | 1.74e-29 | *** |
| InferenceSurvivalLogRank | survival | 0.08 | lifelines | statistics.logrank_test | 15.99 | 197.11x | 7.95e-29 | *** |
| InferenceSurvivalStratCoxPHRegr | survival | 0.45 | lifelines | CoxPHFitter(strata=) | 160.27 | 359.32x | 1.12e-32 | *** |
| InferenceSurvivalWeibullRegr | survival | 0.19 | lifelines | WeibullAFTFitter.fit()+summary | 128.70 | 676.59x | 4.37e-23 | *** |
30 of 43 rows have a working canonical Python timing; 0 canonical fit(s) failed on this run (see console log); 13 are documented Baseline Gaps; 1 rows from the point-estimate table are excluded entirely (see above).
EDI faster, significant NA timing comparison no canonical Python implementation
EDI's internal fast_* scalar math kernels — every one that exists in R/EDI/src (fast_digamma, fast_trigamma, fast_lgamma, fast_lbeta, fast_qnorm, fast_log_pnorm, fast_log_dnorm, fast_dnbinom_mu, fast_pchisq_upper, fast_erfc, pnorm_fast, dnorm_fast, fast_atan, fast_log1pexp) — vs. their scipy/numpy vectorized equivalents, over a length-5000 vector. All 14 are bound in python/cpp/bindings_fast_math.cpp as vectorized elementwise wrappers around the same portable inline scalar functions EDI's model-fitting kernels call internally, so every row times a real EDI call against its canonical vectorized counterpart.
| Class | Response | EDI Time (ms) | Canonical Pkg | Canonical Func | Canonical Time (ms) | Speedup | Timing Pval | |
|---|---|---|---|---|---|---|---|---|
| dnorm_fast | utility | 0.03 | scipy | stats.norm.pdf | 0.15 | 4.60x | 1.32e-32 | *** |
| fast_atan | utility | 0.02 | numpy | arctan | 0.06 | 2.44x | 8.5e-32 | *** |
| fast_digamma | utility | 0.06 | scipy | special.digamma | 0.09 | 1.52x | 1.24e-20 | *** |
| fast_dnbinom_mu | utility | 0.40 | scipy | stats.nbinom.logpmf | 0.47 | 1.15x | 1.67e-06 | *** |
| fast_erfc | utility | 0.08 | scipy | special.erfc | 0.09 | 1.21x | 9.94e-09 | *** |
| fast_lbeta | utility | 0.22 | scipy | special.betaln | 0.51 | 2.29x | 3.23e-39 | *** |
| fast_lgamma | utility | 0.07 | scipy | special.gammaln | 0.09 | 1.27x | 7.8e-12 | *** |
| fast_log1pexp | utility | 0.06 | numpy | logaddexp(0,.) | 0.10 | 1.63x | 8.69e-29 | *** |
| fast_log_dnorm | utility | 0.00179 | scipy | stats.norm.logpdf | 0.13 | 75.01x | 1.01e-31 | *** |
| fast_log_pnorm | utility | 0.12 | scipy | stats.norm.logcdf | 0.27 | 2.30x | 3.28e-29 | *** |
| fast_pchisq_upper | utility | 0.55 | scipy | stats.chi2.sf | 0.77 | 1.42x | 7.83e-20 | *** |
| fast_qnorm | utility | 0.03 | scipy | stats.norm.ppf | 0.22 | 8.60x | 5.72e-30 | *** |
| fast_trigamma | utility | 0.02 | scipy | special.polygamma(1,.) | 1.33 | 69.17x | 3.55e-30 | *** |
| pnorm_fast | utility | 0.07 | scipy | stats.norm.cdf | 0.20 | 2.85x | 3.81e-27 | *** |
14 of 14 functions have a working canonical timing; 0 failed on this run.
See R/package_metadata/python_bindings_package_spec.md for the full kernel-binding plan.