diff --git a/formulae/terms/terms.py b/formulae/terms/terms.py index 0462119..510f778 100644 --- a/formulae/terms/terms.py +++ b/formulae/terms/terms.py @@ -17,6 +17,7 @@ from formulae.terms.variable import Variable _log = logging.getLogger("formulae") +_NON_INTERACTABLE_TRANSFORMS = {"hsgp", "cr", "cc", "bs", "tp"} # XTODO: Components have 'value' and terms have 'data'... which one should be kept? @@ -226,6 +227,13 @@ def __init__(self, *components): for component in components: if component not in self.components: self.components.append(component) + if len(self.components) > 1: + for component in self.components: + if ( + isinstance(component, Call) + and component.call.callee in _NON_INTERACTABLE_TRANSFORMS + ): + raise TypeError(f"Interaction with '{component.call.callee}' is not supported.") self.data = None self.kind = None self.name = ":".join([str(component.name) for component in self.components]) diff --git a/tests/test_design_matrices.py b/tests/test_design_matrices.py index ebd5b85..c01b003 100644 --- a/tests/test_design_matrices.py +++ b/tests/test_design_matrices.py @@ -1179,40 +1179,6 @@ def test_categorical_ordered_series(): assert levels == list("bcd") -def test_bs_categorical_interaction(): - data = pd.DataFrame( - { - "state": np.tile( - ["lonely", "depressed", "hopeful", "stressed", "positive", "isolated"], 10 - ), - "time": np.repeat(np.arange(0, 5), 12), - } - ) - - formula = "0 + bs(time, degree=2, df=3) : state" - dm = design_matrices(formula, data) - assert dm.common.terms["bs(time, degree=2, df=3):state"].levels == [ - "0, depressed", - "0, hopeful", - "0, isolated", - "0, lonely", - "0, positive", - "0, stressed", - "1, depressed", - "1, hopeful", - "1, isolated", - "1, lonely", - "1, positive", - "1, stressed", - "2, depressed", - "2, hopeful", - "2, isolated", - "2, lonely", - "2, positive", - "2, stressed", - ] - - def test_calls_with_lazy_values(): # https://github.com/bambinos/formulae/issues/87 value = np.arange(5) diff --git a/tests/test_resolver.py b/tests/test_resolver.py index 7fb7946..abd7143 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -137,6 +137,13 @@ def test_term_interaction(): assert desc == comp +@pytest.mark.parametrize("transform", ["hsgp", "cr", "cc", "bs", "tp"]) +@pytest.mark.parametrize("operator", [":", "*"]) +def test_spline_transforms_reject_interactions(transform, operator): + with pytest.raises(TypeError, match=f"Interaction with '{transform}' is not supported"): + model_description(f"y{operator}{transform}(x)") + + def test_term_power_interaction(): desc = model_description("x*y") comp = Model(