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 being bound to Python in an active, uncommitted,
in-progress scaffold under python/ (a separate effort from this benchmark script
— see R/package_metadata/python_bindings_package_spec.md). This script does not
own or edit that scaffold; at the top of every run it configures and builds whatever is
currently there (via CMake, into an isolated /tmp directory) and imports
whatever compiles, so the EDI Time column reflects the real state of that
work at run time rather than a stale snapshot — different runs of this script can show
different EDI coverage as that scaffold evolves, 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 without one, or where the Wald table needs
standard errors these 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 matches R's wald_specs exactly (41 classes) rather than reusing the point-estimate table's 40 — it adds several nonparametric-test-only classes with no point-estimate-table row at all (pooled-variance t-test, Wilcoxon rank-sum, Lin's estimator, Fisher exact, 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). 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 (a scalar-loop binding would unfairly penalize a C++ side that hasn't been written yet).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 | *** |
| InferenceContinQuantileRegr | continuous | NA | statsmodels | QuantReg | 15.56 | NA | NA | |
| 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 | *** |
33 of 47 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 three rows 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 | |
|---|---|---|---|---|---|---|---|---|
| InferenceAllSimpleMeanDiffPooledVar | continuous | NA | scipy | stats.ttest_ind(pooled) | 0.85 | NA | NA | |
| InferenceAllSimpleWilcox | continuous | NA | scipy | stats.mannwhitneyu | 0.62 | NA | NA | |
| 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 | *** |
| InferenceContinQuantileRegr | continuous | NA | statsmodels | QuantReg+summary | 22.69 | NA | NA | |
| 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 | *** |
| InferenceIncidExactFisher | incidence | NA | scipy | stats.fisher_exact | 1.29 | NA | NA | |
| 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 | *** |
34 of 47 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. Only fast_pchisq_upper is declared in the python/ fast_math stub (python/cpp/bindings_fast_math.cpp), and even that build currently fails to import (an unrelated undefined symbol from other in-progress bindings in the same compiled module — python/build_verify/), so no row has a usable EDI binding yet and every row is grey today.
| 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.