Skip to main content

GeDS for Python

This package provides a Python interface to the GeDS R package. The R package is the sole implementation of the statistical methods. Python supplies a scikit-learn-style API, pandas/NumPy conversion, environment diagnostics, and model serialization.

Requirements

  • R 4.4 or newer (R 4.6.1 is used for development)
  • GeDS 0.3.6 or newer with the Python bridge fixes
  • Python 3.10 or newer

Install the Python package, including the optional plotting dependency used in the example:

python -m pip install "geds-python[plot]"

Install the R package separately, using R 4.6.1 or another supported R installation. Install the tested GeDS 0.3.6 build from GitHub:

install.packages("remotes")
remotes::install_git(
  "https://github.com/emilioluissaenzguillen/GeDS.git",
  ref = "91b8ddd13aae8f39994c87fc356f05da4799f911",
  dependencies = NA, upgrade = "never"
)

An older GeDS build, even one reporting version 0.3.6, may lack the fixes required by this wrapper. install.packages("GeDS") alone is not guaranteed to provide them while the CRAN review follows its separate schedule. Check the installed R version with packageVersion("GeDS").

On Windows, building the GitHub source package requires Rtools compatible with the selected R installation. GeDS remains version 0.3.6 on GitHub; the wrapper checks an internal compatibility marker for the fit and prediction fixes as well as the package version.

The wrapper discovers the newest R installation under Program Files/R on Windows or uses Rscript from PATH on other platforms. Set R_HOME to select a particular R installation. If GeDS is installed in a non-default R library, set GEDS_R_LIBRARY to that library directory before importing geds.

The Python and R packages have independent release cycles. geds-python checks the installed GeDS version when its backend first starts and reports the selected R installation and package library through geds.diagnostics().

Check the backend before fitting:

python -m geds.check

For a machine-readable report, use python -m geds.check --json. The same information is available inside Python:

import geds

print(geds.diagnostics())

Selecting R and its package library

Usually no configuration is necessary. If several R installations are available, select one before starting Python:

$env:R_HOME = "C:\Program Files\R\R-4.6.1"
python -m geds.check
export R_HOME="/Library/Frameworks/R.framework/Resources"  # macOS
# export R_HOME="/usr/lib/R"                               # Linux
python -m geds.check

If GeDS is installed in a personal or otherwise non-default R library, set GEDS_R_LIBRARY to the directory that contains the GeDS folder. You can find that directory from R with find.package("GeDS"); use its parent directory as GEDS_R_LIBRARY.

If the check reports that R is missing, install R or set R_HOME. If it finds R but not GeDS, start that same R installation and run one of the GeDS installation commands above, then rerun the check.

Example

Install the optional plotting dependency with python -m pip install "geds-python[plot]", then fit and visualize a nonlinear regression:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from geds import GeDSRegressor, plot_fit

rng = np.random.RandomState(123)
n = 500


def f_1(x):
    return (10 * x / (1 + 100 * x**2)) * 4 + 4


x = np.sort(rng.uniform(-2.0, 2.0, size=n))
means = f_1(x)
y = rng.normal(means, scale=0.1)
X = pd.DataFrame({"x": x})

model = GeDSRegressor(order=3).fit(X, y)
knots = np.asarray(model.knots_, dtype=float)

print("Internal knots:", knots)

fig, ax = plt.subplots()
plot_fit(model, X, y, ax=ax)
grid_x = np.linspace(x.min(), x.max(), 500)
ax.plot(
    grid_x,
    f_1(grid_x),
    color="0.25",
    linestyle=":",
    linewidth=2,
    label="True mean",
)
ax.set(ylabel="y")
ax.legend()
fig.tight_layout()
plt.show()

With GeDS 0.3.6 and R 4.6.1, this seeded example fits 16 internal knots. The dashed vertical lines show how GeDS places more knots around the sharp variation near zero while retaining knots across the wider domain.

GeDSRegressor delegates to GeDS::NGeDS(). For exponential-family models, use GeDSGeneralizedRegressor, which delegates to GeDS::GGeDS().

For fitted models, get_deviance(order=...), get_log_likelihood(order=...), and get_confidence_intervals(order=..., level=...) call the corresponding R methods. Confidence intervals are returned as a pandas DataFrame with lower and upper columns. As in R, these are coefficient intervals, not confidence bands for the fitted curve.

The estimators also work with standard scikit-learn tools such as cross_val_score() and GridSearchCV. Use sequential execution (n_jobs=1) when cross-validating: the wrapper embeds R in the Python process, and parallel-worker behavior is not part of the supported interface.

R also has a specialized crossv_GeDS() routine, which returns a parameter grid with cross-validated mean squared error and knot/iteration summaries. Use its Python interface when those R-specific results are needed:

from geds import cross_validate_geds

cv = cross_validate_geds(
    GeDSRegressor(order=3), X, y,
    {"beta": [0.5, 0.7], "phi": [0.95], "q": [2]},
    n_folds=5, n_cores=1, random_state=123,
)
print(cv.best_params)
print(cv.results)

This delegates the entire search to R and does not fit or change the input estimator. It currently supports Gaussian models only, accepts the R tuning parameters beta, phi, q, and (for boosting) int_knots_init and shrinkage, and defaults to one R worker. R's current non-boost routine does not forward other fitting settings; the Python interface rejects custom settings it would otherwise silently ignore. Use scikit-learn's grid search when you need those settings or a non-Gaussian family.

For a fitted univariate spline without extra linear features, R's calculus and spline-conversion utilities are available as model methods:

slopes = model.derive([-0.5, 0.0, 0.5], derivative_order=1)
areas = model.integrate(-1.0, [-0.5, 0.0, 0.5])
piece_knots, piece_coefficients = model.piecewise_polynomial()

derive() and integrate() operate on the predictor (link) scale, as in R. piecewise_polynomial() returns the R PPolyRep() knot vector and coefficient matrix; its last coefficient row is extraneous in R's representation. These methods use the estimator's selected spline order unless order= is given.

For a normal univariate fit, impose a shape constraint without changing the original fitted model:

increasing_model = model.shape_constrain("increasing")
increasing_and_convex = model.shape_constrain(["increasing", "convex"])

This calls R's shapeConstrain() and returns a new Python estimator. R also supports constraints on one selected univariate smoother in Gaussian GAM and boosting fits, via shape_constrain(..., base_learner="f(x)"). Those additive fits must use normalize_data=False. Constrained fits do not provide the usual unconstrained coefficient confidence intervals.

For count data, the generalized estimator uses GeDS::GGeDS() and supports both response-scale and link-scale prediction:

import numpy as np
import pandas as pd
from geds import GeDSGeneralizedRegressor, plot_fit

rng = np.random.default_rng(123)
x = np.sort(rng.uniform(-2, 2, 120))
X = pd.DataFrame({"x": x})
counts = rng.poisson(np.exp(1 + np.sin(x)))

model = GeDSGeneralizedRegressor(
    family="poisson", beta=0.2, phi=0.95, min_internal_knots=3
).fit(X, counts)
mean_counts = model.predict(X)
log_mean_counts = model.predict_link(X)
ax = plot_fit(model, X, counts)

min_internal_knots controls the minimum number of stage-A knots; it is used here to make a small sample's fitted spline visible. GeDS determines the final knot positions.

For a univariate spline with a known offset (for example log exposure in a Poisson model), pass one offset value per observation to both fitting and prediction. These values are on the link scale:

import numpy as np
import pandas as pd
from geds import GeDSGeneralizedRegressor

rng = np.random.default_rng(321)
x = np.linspace(-1.5, 1.5, 90)
X = pd.DataFrame({"x": x})
exposure = np.linspace(1.1, 2.0, len(x))
counts = rng.poisson(exposure * np.exp(1.4 + np.sin(x))) + 1
log_exposure = np.log(exposure)
model = GeDSGeneralizedRegressor(
    family="poisson", spline_features=["x"], order=2,
    higher_order=False,
).fit(X, counts, offset=log_exposure)
expected_counts = model.predict(X, offset=log_exposure)
contributions = model.predict_terms(X, offset=log_exposure)

predict_terms() returns a DataFrame of the R spline and parametric term contributions. Its rows sum to the link prediction after adding the offset; the offset is not itself a term column. Offset prediction currently supports one spline feature only because the R bivariate prediction method does not apply new-data offsets consistently. A model fitted with an offset requires an offset at prediction time.

This offset interface requires the GeDS GitHub fit and prediction fixes. A earlier GeDS 0.3.6 installation without those fixes may mishandle generalized-model offsets; the backend rejects that version.

Choose spline and parametric components explicitly for mixed data:

model = GeDSRegressor(
    spline_features=["x"],
    linear_features=["group"],
).fit(X, y)

Spline features must be numeric. Parametric features may be numeric or categorical; their encoding is performed by the R package so fitting and prediction use R's native factor semantics. If spline_features is omitted, all columns are used in a single joint spline term. Select spline_features=["x"] and linear_features=["group"] to keep group parametric instead. Two spline features create a joint bivariate surface, not two separate additive smooths; R's support for more than two spline features is experimental. With named pandas columns, prediction may receive columns in a different order because the wrapper restores the fitted column order before calling R.

Additive GAM and boosting models

Use GeDSGAMRegressor for R's NGeDSgam() and GeDSBoostRegressor for NGeDSboost(). Each entry in spline_terms is one additive smooth. Put two features in the same entry for a joint surface. If omitted, each non-linear feature gets its own smooth; linear_features selects parametric terms.

import numpy as np
import pandas as pd
from geds import GeDSGAMRegressor, GeDSBoostRegressor

x = np.linspace(-2, 2, 100)
X = pd.DataFrame({"x": x, "z": x**2})
y = np.sin(x) + 0.3 * x**2

gam = GeDSGAMRegressor(
    spline_terms=[("x",), ("z",)], max_iterations=10
).fit(X, y)
boost = GeDSBoostRegressor(
    spline_terms=[("x",), ("z",)], max_iterations=20
).fit(X, y)

gam_predictions = gam.predict(X)
boost_predictions = boost.predict(X)
x_contribution = gam.predict_component(X, "f(x)")
importance = boost.get_base_learner_importance()

Both estimators expose predict_link(), order-specific coefficients, knots, deviance, log likelihood, and coefficient confidence intervals through R. predict_component() delegates a named learner prediction to R. The R GAM/boost prediction method does not support type="terms", so these estimators do not offer predict_terms(). The GAM wrapper supports the families accepted by GeDSGeneralizedRegressor; for binomial fits it accepts 0/1 responses and creates the factor required by R. The boosting wrapper maps gaussian, poisson, binomial, and gamma to mboost families. The fitted boosting estimator's n_iter_ is R's total boosting iteration count. get_base_learner_importance() returns R's bl_imp() in-bag risk reductions as a pandas Series with the original Python feature names. For a boosted fit with one univariate spline feature, R's iteration plots can be saved to a multipage PDF without opening R directly:

single_boost = GeDSBoostRegressor(max_iterations=10).fit(X[["x"]], y)
single_boost.save_boosting_diagnostics(
    "boosting.pdf", iterations=[0, 1, 2], final_fits=True
)

The method refuses to replace an existing file unless overwrite=True. For binomial boosting, R expects responses encoded as -1 and 1. Offset prediction is not offered for these additive estimators yet.

Fitted estimators contain a serialized R model and can be saved with model.save(path) and restored with GeDSRegressor.load(path). As with any pickle-based format, only load files from trusted sources.

Development

Clone the repository, then install the development dependencies and run the integration tests with:

git clone https://github.com/emilioluissaenzguillen/GeDS-python.git
cd GeDS-python
python -m pip install -e ".[dev]"
python -m pytest
python -m build

The tests start an embedded R session and therefore require a working GeDS installation; they do not substitute or reimplement any GeDS calculations.

Contact

For questions about the Python interface, contact Emilio L. Sáenz Guillén at emilioluissaenzguillen@gmail.com.

Release files for geds-python 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for geds-python 0.1.0
File Size Uploaded
geds_python-0.1.0.tar.gz 43.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for geds-python 0.1.0
File Interpreter ABI Platform
geds_python-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 80.1 kB

Release files / geds_python-0.1.0.tar.gz

Download URL geds_python-0.1.0.tar.gz
Size 43.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ddf7f8fe7feb450254a2716a322590d40111febc85be105fee929a1423e64763
BLAKE2b-256 checksum
How to use checksums
5e85c040b2c0fa9447bce1266ade133ecc035534aa1dc718b318c673d7f64e7d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / geds_python-0.1.0-py3-none-any.whl

Download URL geds_python-0.1.0-py3-none-any.whl
Size 37.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b72b4a931a86cafc012d20f3cf0ad1024700262a6fefa1414699941d095108cb
BLAKE2b-256 checksum
How to use checksums
2e1a18d816e534676afbcc56f2bd0ed9af651360b629944e9db518b138bafc1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page