Skip to content
Merged

Dev #51

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/api/basis_functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ Basis functions control how smooth terms behave in your GAM models -- different
::: pymgcv.basis_functions.AbstractBasis
options:
members: __str__
merge_init_into_class: false
8 changes: 4 additions & 4 deletions docs/api/gam.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ GAM model types from ``pymgcv.gam``.
- "!fit"
- "!predict"
- "!partial_effects"
- "all_predictors"

::: pymgcv.gam.GAM
options:
inherited_members:
- __init__
heading_level: 2
inherited_members: __init__

::: pymgcv.gam.BAM
options:
heading_level: 2
inherited_members: __init__

inherited_members:
- __init__

::: pymgcv.gam.FitState
options:
Expand Down
1 change: 1 addition & 0 deletions docs/api/plot.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
::: pymgcv.plot.plot_categorical
::: pymgcv.plot.plot_qq
::: pymgcv.plot.plot_residuals_vs_linear_predictor
::: pymgcv.plot.hexbin_residuals
1 change: 0 additions & 1 deletion docs/api/terms.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ assert L("x0") + S("x1") == [L("x0"), S("x1")]
- "__init__"
::: pymgcv.terms.AbstractTerm
options:
merge_init_into_class: false
members:
- label
- mgcv_identifier
Expand Down
752 changes: 752 additions & 0 deletions docs/examples/electricity_bam.ipynb

Large diffs are not rendered by default.

42 changes: 25 additions & 17 deletions docs/examples/gamlss.ipynb

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions docs/examples/linear_functional.ipynb

Large diffs are not rendered by default.

218 changes: 170 additions & 48 deletions docs/examples/ozone.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
"id": "353f16ed",
"metadata": {
"execution": {
"iopub.execute_input": "2025-08-25T05:53:18.928690Z",
"iopub.status.busy": "2025-08-25T05:53:18.928139Z",
"iopub.status.idle": "2025-08-25T05:53:28.161960Z",
"shell.execute_reply": "2025-08-25T05:53:28.161346Z"
"iopub.execute_input": "2025-09-01T12:05:04.942045Z",
"iopub.status.busy": "2025-09-01T12:05:04.941364Z",
"iopub.status.idle": "2025-09-01T12:05:15.585855Z",
"shell.execute_reply": "2025-09-01T12:05:15.585042Z"
}
},
"outputs": [
Expand All @@ -50,7 +50,6 @@
"data = load_rdata_dataframe_from_url(\n",
" \"https://github.com/cran/gamair/raw/master/data/co2s.rda\",\n",
")\n",
"\n",
"plt.plot(data[\"c.month\"], data[\"co2\"])\n",
"plt.xlabel(\"Cumulative month\")\n",
"plt.ylabel(r\"CO2 concentration\")\n",
Expand All @@ -76,10 +75,10 @@
"id": "c4b87eb8",
"metadata": {
"execution": {
"iopub.execute_input": "2025-08-25T05:53:28.163817Z",
"iopub.status.busy": "2025-08-25T05:53:28.163590Z",
"iopub.status.idle": "2025-08-25T05:53:28.989669Z",
"shell.execute_reply": "2025-08-25T05:53:28.989014Z"
"iopub.execute_input": "2025-09-01T12:05:15.588068Z",
"iopub.status.busy": "2025-09-01T12:05:15.587773Z",
"iopub.status.idle": "2025-09-01T12:05:17.053952Z",
"shell.execute_reply": "2025-09-01T12:05:17.052893Z"
}
},
"outputs": [
Expand All @@ -96,7 +95,9 @@
],
"source": [
"simple_gam = GAM({\"co2\": S(\"c.month\", bs=CubicSpline(), k=100)})\n",
"simple_gam.fit(data)\n",
"simple_gam.fit(\n",
" data[~data.isna().any(axis=1)],\n",
")\n",
"\n",
"cyclic_gam = GAM(\n",
" {\n",
Expand All @@ -105,7 +106,10 @@
" },\n",
")\n",
"\n",
"cyclic_gam.fit(data, knots={\"month\": np.arange(1, 13)})\n",
"cyclic_gam.fit(\n",
" data[~data.isna().any(axis=1)],\n",
" knots={\"month\": np.arange(1, 13)},\n",
" )\n",
"\n",
"def plot_prediction(gam: AbstractGAM, data, predict_data, ax):\n",
" predictions = gam.predict(data=predict_data, compute_se=True)\n",
Expand Down
28 changes: 14 additions & 14 deletions docs/examples/smooth_by_categorical.ipynb

Large diffs are not rendered by default.

Large diffs are not rendered by default.

264 changes: 264 additions & 0 deletions docs/examples/supplement_vs_placebo.ipynb

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions docs/index.ipynb

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ nav:
- GAMLSS: examples/gamlss.ipynb
- Smooth-by-categorical: examples/smooth_by_categorical.ipynb
- Linear functional: examples/linear_functional.ipynb
- Cyclical components: examples/cyclical_components.ipynb
- Applied Examples:
- Ozone: examples/ozone.ipynb
- Spatial interactions: examples/spatial_interactions.ipynb
- Seasonal CO2: examples/seasonal_co2.ipynb
- Spatial fish eggs: examples/spatial_fish_eggs.ipynb
- Electricity demand BAM: examples/electricity_bam.ipynb
- Supplement vs placebo: examples/supplement_vs_placebo.ipynb
- API Reference:
- api/gam.md
- api/terms.md
Expand Down Expand Up @@ -90,5 +93,9 @@ plugins:
heading_level: 3
members_order: source
show_signature_annotations: true
extensions:
- griffe_inherited_docstrings
merge_init_into_class: true

extra_css:
- stylesheets/extra.css
22 changes: 18 additions & 4 deletions pymgcv/basis_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

class _PassToS(TypedDict, total=False):
xt: ro.ListVector
m: int | float | tuple[int | float, ...]
m: int | float | ro.IntVector | ro.FloatVector


class AbstractBasis(ABC):
Expand Down Expand Up @@ -59,13 +59,16 @@ def _pass_to_s(self) -> _PassToS:
passing of these arguments to `mgcv.s`. Note the string should
include the leading comma if it is not empty.



Returns:
A dictionary, mapping a keyword (e.g. xt or m) to a dictionary of
variable values.
"""
...


@dataclass
class RandomEffect(AbstractBasis):
"""Random effect basis for correlated grouped data.

Expand All @@ -74,6 +77,17 @@ class RandomEffect(AbstractBasis):
the corresponding coefficients with a multiple of the identity matrix (i.e. a ridge
penalty), corresponding to an assumption of i.i.d. normality of the parameters.

!!! warning

Numeric variables (int/float), will be treated as a linear term with a single
penalized slope parameter. Do not use an integer variable to encode
categorical groups!

!!! example

For an example, see the
[supplement vs placebo example](../../examples/supplement_vs_placebo).

"""

def __str__(self) -> str:
Expand Down Expand Up @@ -235,7 +249,7 @@ def __str__(self) -> str:
return "ds"

def _pass_to_s(self) -> _PassToS:
return {"m": (self.m, self.s)}
return {"m": ro.FloatVector([self.m, self.s])}


@dataclass(kw_only=True)
Expand Down Expand Up @@ -292,7 +306,7 @@ def __str__(self) -> str:
return "bs"

def _pass_to_s(self) -> _PassToS:
return {"m": [self.degree] + self.penalty_orders}
return {"m": ro.IntVector([self.degree] + self.penalty_orders)}


@dataclass(kw_only=True)
Expand Down Expand Up @@ -326,7 +340,7 @@ def __str__(self) -> str:

def _pass_to_s(self) -> _PassToS:
# Note (unlike b-splines) seems mgcv uses m[1] for the penalty order, not degree so subtract 1
return {"m": (self.degree - 1, self.penalty_order)}
return {"m": ro.IntVector([self.degree - 1, self.penalty_order])}


@dataclass(kw_only=True)
Expand Down
6 changes: 1 addition & 5 deletions pymgcv/families.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@

import numpy as np
import rpy2.robjects as ro
from rpy2.robjects.packages import importr

from pymgcv.rlibs import rbase, rmgcv, rstats
from pymgcv.rpy_utils import is_null, to_py, to_rpy

rbase = importr("base")
rstats = importr("stats")
rmgcv = importr("mgcv")

# For qq_simulate we need sample, and for qq_cdf we need cdf implemented.


Expand Down
10 changes: 4 additions & 6 deletions pymgcv/formula_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
from typing import Any

from rpy2 import robjects as ro
from rpy2.robjects.packages import importr

from pymgcv.rlibs import rbase
from pymgcv.rpy_utils import to_rpy

rbase = importr("base")
rutils = importr("utils")


@dataclass
class _Var:
Expand All @@ -35,5 +32,6 @@ def _to_r_constructor_string(arg: Any) -> str:
connection = rbase.textConnection("__r_obj_str", "w")
rbase.dput(arg, file=connection)
rbase.close(connection)
assert len(ro.r["__r_obj_str"]) == 1
return ro.r["__r_obj_str"][0]
result = ro.r["__r_obj_str"]
assert len(result) == 1 # type: ignore
return result[0] # type: ignore
Loading