Skip to content

io

I/O helpers for brmspy.

This module contains helpers for: - loading example datasets from R packages - saving/loading R objects via saveRDS / readRDS

Notes

These functions are executed inside the worker process that hosts the embedded R session.

Attributes

FitResult = IDResult[IDBrm] module-attribute

ProxyListSexpVector = Union[SexpWrapper, ListSexpVector, None] module-attribute

Classes

RListVectorExtension dataclass

Generic result container with R objects.

Attributes:

Name Type Description
r ListVector

R object from brms

Source code in brmspy/types/brms_results.py
@dataclass
class RListVectorExtension:
    """Generic result container with R objects.

    Attributes
    ----------
    r : robjects.ListVector
        R object from brms
    """

    r: ProxyListSexpVector

Attributes

r instance-attribute

Functions

__init__(r)

Functions

brmsfit_to_idata(brmsfit_obj, model_data=None)

Source code in brmspy/helpers/_rpy2/_conversion.py
def brmsfit_to_idata(brmsfit_obj, model_data=None) -> IDBrm:
    posterior_dict, _ = _brmsfit_get_posterior(brmsfit_obj)
    resp_names = _brmsfit_get_response_names(brmsfit_obj)
    dims, coords = _brmsfit_get_dims_and_coords(brmsfit_obj, resp_names=resp_names)
    observed_data_dict = _brmsfit_get_observed_data(brmsfit_obj, resp_names)
    post_pred_dict, _ = _brmsfit_get_predict_generic(
        brmsfit_obj, function="brms::posterior_predict", resp_names=resp_names
    )
    log_lik_dict, _ = _brmsfit_get_predict_generic(
        brmsfit_obj, function="brms::log_lik", resp_names=resp_names
    )
    constant_data_dict = _brmsfit_get_constant_data(
        brmsfit_obj, newdata=None, resp_names=resp_names
    )
    for name in constant_data_dict:
        if name not in dims:
            dims[name] = ["obs_id"]

    idata = az.from_dict(
        posterior=posterior_dict,
        posterior_predictive=post_pred_dict or None,
        log_likelihood=log_lik_dict or None,
        observed_data=observed_data_dict or None,
        coords=coords or None,
        constant_data=constant_data_dict or None,
        dims=dims or None,
    )

    return cast(IDBrm, idata)

kwargs_r(kwargs)

Convert Python keyword arguments to R-compatible format.

Convenience function that applies py_to_r() to all values in a keyword arguments dictionary, preparing them for R function calls.

Parameters:

Name Type Description Default
kwargs dict or None

Dictionary of keyword arguments where values may be Python objects (dicts, lists, DataFrames, arrays, etc.)

required

Returns:

Type Description
dict

Dictionary with same keys but R-compatible values, or empty dict if None

Notes

This is a thin wrapper around py_to_r() that operates on dictionaries. It's commonly used to prepare keyword arguments for R function calls via rpy2.

Examples:

from brmspy.helpers.conversion import kwargs_r
import pandas as pd
import numpy as np

# Prepare kwargs for R function
py_kwargs = {
    'data': pd.DataFrame({'y': [1, 2], 'x': [1, 2]}),
    'prior': {'b': [0, 1]},
    'chains': 4,
    'iter': 2000
}

r_kwargs = kwargs_r(py_kwargs)
# All values converted to R objects
# Can now call: r_function(**r_kwargs)
See Also

py_to_r : Underlying conversion function for individual values brmspy.brms.fit : Uses this to prepare user kwargs for R

Source code in brmspy/helpers/_rpy2/_conversion.py
def kwargs_r(kwargs: dict | None) -> dict:
    """
    Convert Python keyword arguments to R-compatible format.

    Convenience function that applies py_to_r() to all values in a
    keyword arguments dictionary, preparing them for R function calls.

    Parameters
    ----------
    kwargs : dict or None
        Dictionary of keyword arguments where values may be Python objects
        (dicts, lists, DataFrames, arrays, etc.)

    Returns
    -------
    dict
        Dictionary with same keys but R-compatible values, or empty dict if None

    Notes
    -----
    This is a thin wrapper around `py_to_r()` that operates on dictionaries.
    It's commonly used to prepare keyword arguments for R function calls via rpy2.

    Examples
    --------

    ```python
    from brmspy.helpers.conversion import kwargs_r
    import pandas as pd
    import numpy as np

    # Prepare kwargs for R function
    py_kwargs = {
        'data': pd.DataFrame({'y': [1, 2], 'x': [1, 2]}),
        'prior': {'b': [0, 1]},
        'chains': 4,
        'iter': 2000
    }

    r_kwargs = kwargs_r(py_kwargs)
    # All values converted to R objects
    # Can now call: r_function(**r_kwargs)
    ```

    See Also
    --------
    py_to_r : Underlying conversion function for individual values
    brmspy.brms.fit : Uses this to prepare user kwargs for R
    """
    if kwargs is None:
        return {}
    return {k: py_to_r(v) for k, v in kwargs.items()}

r_to_py(obj, shm=None)

Convert R objects to Python objects via rpy2.

Comprehensive converter that handles R lists (named/unnamed), vectors, formulas, and language objects. Provides sensible Python equivalents for all R types with special handling for edge cases.

Parameters:

Name Type Description Default
obj rpy2 R object

R object to convert to Python

required

Returns:

Type Description
any

Python representation of the R object: - R NULL → None - Named list → dict (recursively) - Unnamed list → list (recursively) - Length-1 vector → scalar (int, float, str, bool) - Length-N vector → list of scalars - Formula/Language object → str (descriptive representation) - Other objects → default rpy2 conversion or str fallback

Notes

Conversion Rules:

  1. R NULL: → Python None
  2. Atomic vectors (numeric, character, logical):
  3. Length 1: → Python scalar (int, float, str, bool)
  4. Length >1: → Python list of scalars
  5. Named lists (ListVector with names): → Python dict, recursively
  6. Unnamed lists: → Python list, recursively
  7. Formulas (e.g., y ~ x): → String representation
  8. Language objects (calls, expressions): → String representation
  9. Functions: → String representation
  10. Everything else: Try default rpy2 conversion, fallback to string

Recursive Conversion:

List elements and dictionary values are recursively converted:

list(a = list(b = c(1, 2)))    {'a': {'b': [1, 2]}}

Safe Fallback:

R language objects, formulas, and functions are converted to descriptive strings rather than attempting complex conversions that might fail.

Examples:

from brmspy.helpers.conversion import r_to_py
import rpy2.robjects as ro

# R NULL
r_to_py(ro.NULL)  # None

# Scalars
r_to_py(ro.IntVector([5]))    # 5
r_to_py(ro.FloatVector([3.14]))  # 3.14
r_to_py(ro.StrVector(["hello"]))  # "hello"

# Vectors
r_to_py(ro.IntVector([1, 2, 3]))  # [1, 2, 3]
See Also

py_to_r : Convert Python objects to R brmspy.brms.summary : Returns Python-friendly summary dict

Source code in brmspy/helpers/_rpy2/_converters/_dispatch.py
def r_to_py(obj: Sexp, shm: ShmPool | None = None) -> PyObject:
    """
    Convert R objects to Python objects via rpy2.

    Comprehensive converter that handles R lists (named/unnamed), vectors,
    formulas, and language objects. Provides sensible Python equivalents
    for all R types with special handling for edge cases.

    Parameters
    ----------
    obj : rpy2 R object
        R object to convert to Python

    Returns
    -------
    any
        Python representation of the R object:
        - R NULL → None
        - Named list → dict (recursively)
        - Unnamed list → list (recursively)
        - Length-1 vector → scalar (int, float, str, bool)
        - Length-N vector → list of scalars
        - Formula/Language object → str (descriptive representation)
        - Other objects → default rpy2 conversion or str fallback

    Notes
    -----
    **Conversion Rules:**

    1. **R NULL**: → Python None
    2. **Atomic vectors** (numeric, character, logical):
       - Length 1: → Python scalar (int, float, str, bool)
       - Length >1: → Python list of scalars
    3. **Named lists** (ListVector with names): → Python dict, recursively
    4. **Unnamed lists**: → Python list, recursively
    5. **Formulas** (e.g., `y ~ x`): → String representation
    6. **Language objects** (calls, expressions): → String representation
    7. **Functions**: → String representation
    8. **Everything else**: Try default rpy2 conversion, fallback to string

    **Recursive Conversion:**

    List elements and dictionary values are recursively converted:
    ```R
    list(a = list(b = c(1, 2)))  →  {'a': {'b': [1, 2]}}
    ```

    **Safe Fallback:**

    R language objects, formulas, and functions are converted to descriptive
    strings rather than attempting complex conversions that might fail.

    Examples
    --------

    ```python
    from brmspy.helpers.conversion import r_to_py
    import rpy2.robjects as ro

    # R NULL
    r_to_py(ro.NULL)  # None

    # Scalars
    r_to_py(ro.IntVector([5]))    # 5
    r_to_py(ro.FloatVector([3.14]))  # 3.14
    r_to_py(ro.StrVector(["hello"]))  # "hello"

    # Vectors
    r_to_py(ro.IntVector([1, 2, 3]))  # [1, 2, 3]
    ```

    See Also
    --------
    py_to_r : Convert Python objects to R
    brmspy.brms.summary : Returns Python-friendly summary dict
    """
    import rpy2.robjects as ro

    from brmspy._singleton._shm_singleton import _get_shm

    if obj is ro.NULL:
        return None

    _type = type(obj)
    converter = None

    if shm is None:
        shm = _get_shm()

    if _type in _registry._R2PY_CONVERTERS:
        # O(1) lookup first
        converter = _registry._R2PY_CONVERTERS[_type]
    else:
        for _type, _con in _registry._R2PY_CONVERTERS.items():
            if isinstance(obj, _type):
                converter = _con
                break

    assert len(_registry._R2PY_CONVERTERS) > 0, "NO R2PY CONVERTERS"
    assert (
        converter
    ), "object fallback must be in place in __init__.py! This is an issue with the library, not the user!"
    return converter(obj, shm)

get_data(dataset_name, **kwargs)

Load an R dataset and return it as a pandas DataFrame.

This is a thin wrapper around R's data() that loads the object into the R global environment and converts it to a :class:pandas.DataFrame.

Parameters:

Name Type Description Default
dataset_name str

Name of the dataset as used in R (e.g. "BTdata").

required
**kwargs

Additional keyword arguments forwarded to R's data() function, for example package="MCMCglmm" or other arguments supported by utils::data() in R.

{}

Returns:

Type Description
DataFrame

Dataset converted to a pandas DataFrame.

Raises:

Type Description
KeyError

If the dataset is not found in the R global environment after calling data().

RuntimeError

If conversion from the R object to a pandas DataFrame fails.

See Also

get_brms_data Convenience wrapper for datasets from the brms package.

Source code in brmspy/_brms_functions/io.py
def get_data(dataset_name: str, **kwargs) -> pd.DataFrame:
    """
    Load an R dataset and return it as a pandas DataFrame.

    This is a thin wrapper around R's ``data()`` that loads the object
    into the R global environment and converts it to a
    :class:`pandas.DataFrame`.

    Parameters
    ----------
    dataset_name : str
        Name of the dataset as used in R (e.g. ``"BTdata"``).
    **kwargs
        Additional keyword arguments forwarded to R's ``data()`` function,
        for example ``package="MCMCglmm"`` or other arguments supported
        by ``utils::data()`` in R.

    Returns
    -------
    pd.DataFrame
        Dataset converted to a pandas DataFrame.

    Raises
    ------
    KeyError
        If the dataset is not found in the R global environment after
        calling ``data()``.
    RuntimeError
        If conversion from the R object to a pandas DataFrame fails.

    See Also
    --------
    get_brms_data
        Convenience wrapper for datasets from the ``brms`` package.
    """
    import rpy2.robjects as ro

    r_kwargs = kwargs_r(kwargs)

    r_data = typing.cast(typing.Callable, ro.r["data"])
    r_data(dataset_name, **r_kwargs)
    r_obj = ro.globalenv[dataset_name]

    return typing.cast(pd.DataFrame, r_to_py(r_obj))

get_brms_data(dataset_name, **kwargs)

Load an example dataset from the R brms package.

Parameters:

Name Type Description Default
dataset_name str

Dataset name (for example "epilepsy" or "kidney").

required
**kwargs

Forwarded to R utils::data() via get_data().

{}

Returns:

Type Description
DataFrame

Dataset converted to a DataFrame.

Examples:

from brmspy import brms

epilepsy = brms.get_brms_data("epilepsy")
assert epilepsy.shape[0] > 0
Source code in brmspy/_brms_functions/io.py
def get_brms_data(dataset_name: str, **kwargs) -> pd.DataFrame:
    """
    Load an example dataset from the R ``brms`` package.

    Parameters
    ----------
    dataset_name : str
        Dataset name (for example ``"epilepsy"`` or ``"kidney"``).
    **kwargs
        Forwarded to R ``utils::data()`` via `get_data()`.

    Returns
    -------
    pandas.DataFrame
        Dataset converted to a DataFrame.

    Examples
    --------
    ```python
    from brmspy import brms

    epilepsy = brms.get_brms_data("epilepsy")
    assert epilepsy.shape[0] > 0
    ```
    """
    return get_data(dataset_name, package="brms", **kwargs)

save_rds(object, file, **kwargs)

Save an R object to an .rds file via R saveRDS().

Parameters:

Name Type Description Default
object RListVectorExtension or ProxyListSexpVector

Object to save. If you pass a FitResult, the underlying brmsfit is saved.

required
file str

Output path.

required
**kwargs

Forwarded to R saveRDS() (for example compress="xz").

{}

Returns:

Type Description
None

Examples:

from brmspy import brms

model = brms.brm("y ~ x", data=df, chains=4)
brms.save_rds(model, "model.rds")
Source code in brmspy/_brms_functions/io.py
def save_rds(
    object: RListVectorExtension | ProxyListSexpVector, file: str, **kwargs
) -> None:
    """
    Save an R object to an ``.rds`` file via R ``saveRDS()``.

    Parameters
    ----------
    object : RListVectorExtension or ProxyListSexpVector
        Object to save. If you pass a `FitResult`, the underlying brmsfit is saved.
    file : str
        Output path.
    **kwargs
        Forwarded to R ``saveRDS()`` (for example ``compress="xz"``).

    Returns
    -------
    None

    Examples
    --------
    ```python
    from brmspy import brms

    model = brms.brm("y ~ x", data=df, chains=4)
    brms.save_rds(model, "model.rds")
    ```
    """
    import rpy2.robjects as ro

    if isinstance(object, RListVectorExtension):
        brmsfit = object.r
    else:
        brmsfit = object

    kwargs = kwargs_r(kwargs)

    r_save_rds = typing.cast(typing.Callable, ro.r("saveRDS"))
    r_save_rds(brmsfit, file, **kwargs)

read_rds_raw(file, **kwargs)

Load an R object from an .rds file via R readRDS().

This returns the raw R object handle.

Parameters:

Name Type Description Default
file str

Input path.

required
**kwargs

Forwarded to R readRDS().

{}

Returns:

Type Description
ListSexpVector

Raw R object.

Examples:

from brmspy import brms

obj = brms.read_rds_raw("model.rds")
Source code in brmspy/_brms_functions/io.py
def read_rds_raw(file: str, **kwargs) -> ListSexpVector:
    """
    Load an R object from an ``.rds`` file via R ``readRDS()``.

    This returns the raw R object handle.

    Parameters
    ----------
    file : str
        Input path.
    **kwargs
        Forwarded to R ``readRDS()``.

    Returns
    -------
    rpy2.rinterface.ListSexpVector
        Raw R object.

    Examples
    --------
    ```python
    from brmspy import brms

    obj = brms.read_rds_raw("model.rds")
    ```
    """
    import rpy2.robjects as ro

    r_read_rds = typing.cast(typing.Callable, ro.r("readRDS"))

    kwargs = kwargs_r(kwargs)
    brmsobject = r_read_rds(file, **kwargs)
    return brmsobject

read_rds_fit(file, **kwargs)

Load a saved brms model from an .rds file.

Parameters:

Name Type Description Default
file str

Input path containing a saved brmsfit.

required
**kwargs

Forwarded to R readRDS().

{}

Returns:

Type Description
FitResult

FitResult containing ArviZ InferenceData and an underlying R handle.

Examples:

from brmspy import brms

fit = brms.read_rds_fit("model.rds")
fit.idata.posterior
Source code in brmspy/_brms_functions/io.py
def read_rds_fit(file: str, **kwargs) -> FitResult:
    """
    Load a saved brms model from an ``.rds`` file.

    Parameters
    ----------
    file : str
        Input path containing a saved brmsfit.
    **kwargs
        Forwarded to R ``readRDS()``.

    Returns
    -------
    FitResult
        `FitResult` containing ArviZ `InferenceData` and an underlying R handle.

    Examples
    --------
    ```python
    from brmspy import brms

    fit = brms.read_rds_fit("model.rds")
    fit.idata.posterior
    ```
    """
    brmsfit = read_rds_raw(file, **kwargs)
    idata = brmsfit_to_idata(brmsfit)

    return FitResult(idata=idata, r=brmsfit)