Skip to content

Test the linearity of a given Time-Series Dataset🔗

Introduction🔗

Summary

Linearity testing evaluates whether the relationship between variables in a model follows a linear specification. In the context of time-series analysis, these tests help determine if linear regression models are appropriate or if non-linear dynamics (such as structural breaks or exponential trends) are present.

As stated by James Ramsey (1969):

Specification errors, such as the omission of relevant variables, incorrect functional form, or correlation between the regressor and the error term, can lead to biased and inconsistent estimators. The RESET test provides a robust method for detecting these departures from linearity.


For more info, see: Ramsey RESET test.

Implementation Details

The suite of tests provided here includes measures based on recursive residuals, subset fitting, and power transformations. These tests are typically applied to the residuals of an estimated OLS model to verify that no significant non-linear information remains in the error term.


For more info, see: Statsmodels Linearity Tests.

Source Library

The statsmodels package was chosen because it provides the industry-standard implementation of econometric diagnostic tests, ensuring mathematical rigor and consistency with well-established statistical literature.

Source Module

All of the source code can be found within these modules:

Modules🔗

ts_stat_tests.linearity.tests 🔗

Summary

This module contains convenience functions and tests for linearity measures, allowing for easy access to different linearity algorithms.

linearity 🔗

linearity(
    res: Union[RegressionResults, RegressionResultsWrapper],
    algorithm: str = "rr",
    **kwargs: Union[float, int, str, bool, ArrayLike, None]
) -> Union[tuple[float, ...], ContrastResults]

Summary

Perform a linearity test on a fitted regression model.

Details

This function is a convenience wrapper around four underlying algorithms:
- hc()
- lm()
- rb()
- rr()

Parameters:

Name Type Description Default
res Union[RegressionResults, RegressionResultsWrapper]

The fitted regression model to be checked.

required
algorithm str

Which linearity algorithm to use.
- hc(): ["hc", "harvey", "harvey-collier"]
- lm(): ["lm", "lagrange", "lagrange-multiplier"]
- rb(): ["rb", "rainbow"]
- rr(): ["rr", "reset", "ramsey-reset"]
Default: "rr"

'rr'
kwargs Union[float, int, str, bool, ArrayLike, None]

Additional keyword arguments passed to the underlying test function.

{}

Raises:

Type Description
ValueError

When the given value for algorithm is not valid.

Returns:

Type Description
Union[tuple[float, float], tuple[float, float, float, float], ContrastResults]
  • For "hc": (statistic, pvalue)
  • For "lm": (lm_stat, lm_pval, f_stat, f_pval)
  • For "rb": (statistic, pvalue)
  • For "rr": ContrastResults object

Credit

Calculations are performed by statsmodels.

Examples
Setup
1
2
3
4
5
6
>>> import statsmodels.api as sm
>>> from ts_stat_tests.linearity.tests import linearity
>>> from ts_stat_tests.utils.data import data_line, data_random
>>> x = sm.add_constant(data_line)
>>> y = 3 + 2 * data_line + data_random
>>> res = sm.OLS(y, x).fit()
Example 1: Ramsey RESET test
1
2
3
>>> result = linearity(res, algorithm="rr")
>>> print(f"p-value: {result.pvalue:.4f}")
p-value: 0.9912
Example 2: Rainbow test
1
2
3
>>> stat, pval = linearity(res, algorithm="rb")
>>> print(f"Rainbow p-value: {pval:.4f}")
Rainbow p-value: 0.5391
Source code in src/ts_stat_tests/linearity/tests.py
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
@typechecked
def linearity(
    res: Union[RegressionResults, RegressionResultsWrapper],
    algorithm: str = "rr",
    **kwargs: Union[float, int, str, bool, ArrayLike, None],
) -> Union[tuple[float, ...], ContrastResults]:
    """
    !!! note "Summary"
        Perform a linearity test on a fitted regression model.

    ???+ abstract "Details"
        This function is a convenience wrapper around four underlying algorithms:<br>
        - [`hc()`][ts_stat_tests.linearity.algorithms.hc]<br>
        - [`lm()`][ts_stat_tests.linearity.algorithms.lm]<br>
        - [`rb()`][ts_stat_tests.linearity.algorithms.rb]<br>
        - [`rr()`][ts_stat_tests.linearity.algorithms.rr]

    Params:
        res (Union[RegressionResults, RegressionResultsWrapper]):
            The fitted regression model to be checked.
        algorithm (str):
            Which linearity algorithm to use.<br>
            - `hc()`: `["hc", "harvey", "harvey-collier"]`<br>
            - `lm()`: `["lm", "lagrange", "lagrange-multiplier"]`<br>
            - `rb()`: `["rb", "rainbow"]`<br>
            - `rr()`: `["rr", "reset", "ramsey-reset"]`<br>
            Default: `"rr"`
        kwargs (Union[float, int, str, bool, ArrayLike, None]):
            Additional keyword arguments passed to the underlying test function.

    Raises:
        (ValueError):
            When the given value for `algorithm` is not valid.

    Returns:
        (Union[tuple[float, float], tuple[float, float, float, float], ContrastResults]):
            - For `"hc"`: `(statistic, pvalue)`
            - For `"lm"`: `(lm_stat, lm_pval, f_stat, f_pval)`
            - For `"rb"`: `(statistic, pvalue)`
            - For `"rr"`: `ContrastResults` object

    !!! success "Credit"
        Calculations are performed by `statsmodels`.

    ???+ example "Examples"

        ```pycon {.py .python linenums="1" title="Setup"}
        >>> import statsmodels.api as sm
        >>> from ts_stat_tests.linearity.tests import linearity
        >>> from ts_stat_tests.utils.data import data_line, data_random
        >>> x = sm.add_constant(data_line)
        >>> y = 3 + 2 * data_line + data_random
        >>> res = sm.OLS(y, x).fit()

        ```

        ```pycon {.py .python linenums="1" title="Example 1: Ramsey RESET test"}
        >>> result = linearity(res, algorithm="rr")
        >>> print(f"p-value: {result.pvalue:.4f}")
        p-value: 0.9912

        ```

        ```pycon {.py .python linenums="1" title="Example 2: Rainbow test"}
        >>> stat, pval = linearity(res, algorithm="rb")
        >>> print(f"Rainbow p-value: {pval:.4f}")
        Rainbow p-value: 0.5391

        ```
    """
    options: dict[str, tuple[str, ...]] = {
        "hc": ("hc", "harvey", "harvey-collier"),
        "lm": ("lm", "lagrange", "lagrange-multiplier"),
        "rb": ("rb", "rainbow"),
        "rr": ("rr", "reset", "ramsey-reset"),
    }

    # Internal helper to handle kwargs casting for ty
    def _call(
        func: Callable[..., Union[tuple[float, ...], ContrastResults]],
        **args: Union[
            float,
            int,
            str,
            bool,
            ArrayLike,
            None,
            RegressionResults,
            RegressionResultsWrapper,
        ],
    ) -> Union[tuple[float, ...], ContrastResults]:
        """
        !!! note "Summary"
            Internal helper to handle keyword arguments types.

        Params:
            func (Callable[..., Union[tuple[float, ...], ContrastResults]]):
                The function to call.
            args (Union[float, int, str, bool, ArrayLike, None, RegressionResults, RegressionResultsWrapper]):
                The arguments to pass.

        Returns:
            (Union[tuple[float, ...], ContrastResults]):
                The result of the function call.

        ???+ example "Examples"
            ```python
            # Internal use only
            ```
        """
        return func(**args)

    if algorithm in options["hc"]:
        return _call(_hc, res=res, **kwargs)

    if algorithm in options["lm"]:
        return _call(_lm, resid=res.resid, exog=res.model.exog, **kwargs)

    if algorithm in options["rb"]:
        return _call(_rb, res=res, **kwargs)

    if algorithm in options["rr"]:
        return _call(_rr, res=res, **kwargs)

    raise ValueError(
        generate_error_message(
            parameter_name="algorithm",
            value_parsed=algorithm,
            options=options,
        )
    )

is_linear 🔗

is_linear(
    res: Union[RegressionResults, RegressionResultsWrapper],
    algorithm: str = "rr",
    alpha: float = 0.05,
    **kwargs: Union[float, int, str, bool, ArrayLike, None]
) -> dict[str, Union[str, float, bool, None]]

Summary

Test whether the relationship in a fitted model is linear or not.

Details

This function returns a dictionary containing the test results and a boolean indicating whether the null hypothesis of linearity is rejected at the given significance level.

Parameters:

Name Type Description Default
res Union[RegressionResults, RegressionResultsWrapper]

The fitted regression model to be checked.

required
algorithm str

Which linearity algorithm to use. See linearity() for options. Default: "rr"

'rr'
alpha float

The significance level for the test. Default: 0.05

0.05
kwargs Union[float, int, str, bool, ArrayLike, None]

Additional keyword arguments passed to the underlying test function.

{}

Returns:

Type Description
dict[str, Union[str, float, bool, None]]

A dictionary with the following keys: - "algorithm" (str): The name of the algorithm used. - "statistic" (float): The test statistic. - "pvalue" (float): The p-value of the test. - "alpha" (float): The significance level used. - "result" (bool): Whether the relationship is linear (i.e., p-value > alpha).

Examples
Setup
1
2
3
4
5
6
>>> import statsmodels.api as sm
>>> from ts_stat_tests.linearity.tests import is_linear
>>> from ts_stat_tests.utils.data import data_line, data_random
>>> x = sm.add_constant(data_line)
>>> y = 3 + 2 * data_line + data_random
>>> res = sm.OLS(y, x).fit()
Example 1: Check linearity with RR
1
2
3
>>> result = is_linear(res, algorithm="rr")
>>> print(result["result"])
True
Source code in src/ts_stat_tests/linearity/tests.py
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
@typechecked
def is_linear(
    res: Union[RegressionResults, RegressionResultsWrapper],
    algorithm: str = "rr",
    alpha: float = 0.05,
    **kwargs: Union[float, int, str, bool, ArrayLike, None],
) -> dict[str, Union[str, float, bool, None]]:
    """
    !!! note "Summary"
        Test whether the relationship in a fitted model is `linear` or not.

    ???+ abstract "Details"
        This function returns a dictionary containing the test results and a boolean indicating whether the null hypothesis of linearity is rejected at the given significance level.

    Params:
        res (Union[RegressionResults, RegressionResultsWrapper]):
            The fitted regression model to be checked.
        algorithm (str):
            Which linearity algorithm to use. See [`linearity()`][ts_stat_tests.linearity.tests.linearity] for options.
            Default: `"rr"`
        alpha (float):
            The significance level for the test.
            Default: `0.05`
        kwargs (Union[float, int, str, bool, ArrayLike, None]):
            Additional keyword arguments passed to the underlying test function.

    Returns:
        (dict[str, Union[str, float, bool, None]]):
            A dictionary with the following keys:
            - `"algorithm"` (str): The name of the algorithm used.
            - `"statistic"` (float): The test statistic.
            - `"pvalue"` (float): The p-value of the test.
            - `"alpha"` (float): The significance level used.
            - `"result"` (bool): Whether the relationship is linear (i.e., p-value > alpha).

    ???+ example "Examples"

        ```pycon {.py .python linenums="1" title="Setup"}
        >>> import statsmodels.api as sm
        >>> from ts_stat_tests.linearity.tests import is_linear
        >>> from ts_stat_tests.utils.data import data_line, data_random
        >>> x = sm.add_constant(data_line)
        >>> y = 3 + 2 * data_line + data_random
        >>> res = sm.OLS(y, x).fit()

        ```

        ```pycon {.py .python linenums="1" title="Example 1: Check linearity with RR"}
        >>> result = is_linear(res, algorithm="rr")
        >>> print(result["result"])
        True

        ```
    """
    options: dict[str, tuple[str, ...]] = {
        "hc": ("hc", "harvey", "harvey-collier"),
        "lm": ("lm", "lagrange", "lagrange-multiplier"),
        "rb": ("rb", "rainbow"),
        "rr": ("rr", "reset", "ramsey-reset"),
    }

    raw_res = linearity(res=res, algorithm=algorithm, **kwargs)

    if algorithm in options["hc"] or algorithm in options["rb"]:
        # raw_res is tuple[float, float]
        stat, pvalue = raw_res[0], raw_res[1]  # type: ignore
    elif algorithm in options["lm"]:
        # raw_res is tuple[float, float, float, float]
        stat, pvalue = raw_res[0], raw_res[1]  # type: ignore
    else:
        # raw_res is ContrastResults (Ramsey RESET)
        stat = float(getattr(raw_res, "statistic", getattr(raw_res, "fvalue", np.nan)))
        pvalue = float(getattr(raw_res, "pvalue", np.nan))

    return {
        "algorithm": algorithm,
        "statistic": float(stat),
        "pvalue": float(pvalue),
        "alpha": alpha,
        "result": bool(pvalue > alpha),
    }

ts_stat_tests.linearity.algorithms 🔗

Summary

This module provides implementations of various linearity test algorithms using the statsmodels library.

VALID_RR_TEST_TYPE_OPTIONS module-attribute 🔗

VALID_RR_TEST_TYPE_OPTIONS = Literal[
    "fitted", "exog", "princomp"
]

VALID_RR_COV_TYPE_OPTIONS module-attribute 🔗

VALID_RR_COV_TYPE_OPTIONS = Literal[
    "nonrobust", "HC0", "HC1", "HC2", "HC3", "HAC"
]

hc 🔗

hc(
    res: Union[RegressionResults, RegressionResultsWrapper],
    order_by: Optional[ArrayLike] = None,
    skip: Optional[int] = None,
) -> tuple[float, float]

Summary

The Harvey-Collier test is a statistical test used to determine whether a dataset follows a linear relationship. In time series forecasting, the test can be used to evaluate whether the residuals of a model follow a linear distribution.

Details

The Harvey-Collier test is based on a recursive residuals analysis. The test statistic follows a t-distribution under the null hypothesis of linearity.

Parameters:

Name Type Description Default
res Union[RegressionResults, RegressionResultsWrapper]

The results of a linear regression model from statsmodels.

required
order_by Optional[ArrayLike]

Variable(s) to order by. If None, the original order is used.

None
skip Optional[int]

The number of observations to skip at the beginning of the series.

None

Returns:

Type Description
tuple[float, float]
  • statistic (float): The t-statistic of the test.
  • pvalue (float): The p-value associated with the t-statistic.
Examples
Setup
1
2
3
4
>>> import statsmodels.api as sm
>>> from ts_stat_tests.linearity.algorithms import lm
>>> from ts_stat_tests.utils.data import data_random, data_line
>>> exog = sm.add_constant(data_line.reshape(-1, 1))
Example 1: Linear Data
1
2
3
4
5
>>> lm_stat, lm_pval, f_stat, f_pval = lm(data_line, exog)
>>> print(f"LM Statistic: {lm_stat:.2f}")
LM Statistic: 1000.00
>>> print(f"LM p-value: {lm_pval:.4f}")
LM p-value: 0.0000
Example 2: Random Data
1
2
3
4
5
6
>>> # resid can be anything for this dummy example
>>> lm_stat, lm_pval, f_stat, f_pval = lm(data_random, exog)
>>> print(f"LM Statistic: {lm_stat:.2f}")
LM Statistic: 0.02
>>> print(f"LM p-value: {lm_pval:.4f}")
LM p-value: 0.8840
References
  • Harvey, A.C. and Collier, P. (1977). "Testing for Functional Form in Regression with Application to an Agricultural Production Function." Journal of Econometrics, 6(1), 103-119.
Source code in src/ts_stat_tests/linearity/algorithms.py
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
@typechecked
def hc(
    res: Union[RegressionResults, RegressionResultsWrapper],
    order_by: Optional[ArrayLike] = None,
    skip: Optional[int] = None,
) -> tuple[float, float]:
    r"""
    !!! note "Summary"
        The Harvey-Collier test is a statistical test used to determine whether a dataset follows a linear relationship. In time series forecasting, the test can be used to evaluate whether the residuals of a model follow a linear distribution.

    ???+ abstract "Details"
        The Harvey-Collier test is based on a recursive residuals analysis. The test statistic follows a t-distribution under the null hypothesis of linearity.

    Params:
        res (Union[RegressionResults, RegressionResultsWrapper]):
            The results of a linear regression model from `statsmodels`.
        order_by (Optional[ArrayLike]):
            Variable(s) to order by. If `None`, the original order is used.
        skip (Optional[int]):
            The number of observations to skip at the beginning of the series.

    Returns:
        (tuple[float, float]):
            - `statistic` (float): The t-statistic of the test.
            - `pvalue` (float): The p-value associated with the t-statistic.

    ???+ example "Examples"

        ```pycon {.py .python linenums="1" title="Setup"}
        >>> import statsmodels.api as sm
        >>> from ts_stat_tests.linearity.algorithms import lm
        >>> from ts_stat_tests.utils.data import data_random, data_line
        >>> exog = sm.add_constant(data_line.reshape(-1, 1))

        ```

        ```pycon {.py .python linenums="1" title="Example 1: Linear Data"}
        >>> lm_stat, lm_pval, f_stat, f_pval = lm(data_line, exog)
        >>> print(f"LM Statistic: {lm_stat:.2f}")
        LM Statistic: 1000.00
        >>> print(f"LM p-value: {lm_pval:.4f}")
        LM p-value: 0.0000

        ```

        ```pycon {.py .python linenums="1" title="Example 2: Random Data"}
        >>> # resid can be anything for this dummy example
        >>> lm_stat, lm_pval, f_stat, f_pval = lm(data_random, exog)
        >>> print(f"LM Statistic: {lm_stat:.2f}")
        LM Statistic: 0.02
        >>> print(f"LM p-value: {lm_pval:.4f}")
        LM p-value: 0.8840

        ```

    ??? question "References"
        - Harvey, A.C. and Collier, P. (1977). "Testing for Functional Form in Regression with Application to an Agricultural Production Function." Journal of Econometrics, 6(1), 103-119.
    """
    res_hc = linear_harvey_collier(res=res, order_by=order_by, skip=skip)
    return float(getattr(res_hc, "statistic", np.nan)), float(getattr(res_hc, "pvalue", np.nan))

lm 🔗

lm(
    resid: NDArray[float64],
    exog: NDArray[float64],
    func: Optional[Callable] = None,
) -> tuple[float, float, float, float]

Summary

Lagrange Multiplier test for functional form / linearity.

Details

This test checks whether the linear specification is appropriate for the data. It is a general test for functional form misspecification.

Parameters:

Name Type Description Default
resid NDArray[float64]

The residuals from a linear regression.

required
exog NDArray[float64]

The exogenous variables (predictors) used in the regression.

required
func Optional[Callable]

A function that takes exog and returns a transformed version of it to test against. Default: None

None

Returns:

Type Description
tuple[float, float, float, float]
  • lm (float): Lagrange multiplier statistic.
  • lmpval (float): p-value for LM statistic.
  • fval (float): F-statistic.
  • fpval (float): p-value for F-statistic.
Examples
Setup
1
2
3
4
5
6
7
>>> import statsmodels.api as sm
>>> from ts_stat_tests.linearity.algorithms import lm
>>> from ts_stat_tests.utils.data import data_random, data_line
>>> exog = sm.add_constant(data_line.reshape(-1, 1))
>>> y = 3 + 2 * data_line + 2 * data_line**2 + data_random
>>> res = sm.OLS(y, exog).fit()
>>> resid = res.resid
Example 1: Basic Usage
1
2
3
4
5
>>> lm_stat, lm_pval, f_stat, f_pval = lm(resid, exog)
>>> print(f"LM Statistic: {lm_stat:.2f}")
LM Statistic: 1000.00
>>> print(f"LM p-value: {lm_pval:.4f}")
LM p-value: 0.0000
Source code in src/ts_stat_tests/linearity/algorithms.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
@typechecked
def lm(
    resid: NDArray[np.float64], exog: NDArray[np.float64], func: Optional[Callable] = None
) -> tuple[float, float, float, float]:
    r"""
    !!! note "Summary"
        Lagrange Multiplier test for functional form / linearity.

    ???+ abstract "Details"
        This test checks whether the linear specification is appropriate for the data. It is a general test for functional form misspecification.

    Params:
        resid (NDArray[np.float64]):
            The residuals from a linear regression.
        exog (NDArray[np.float64]):
            The exogenous variables (predictors) used in the regression.
        func (Optional[Callable]):
            A function that takes `exog` and returns a transformed version of it to test against.
            Default: `None`

    Returns:
        (tuple[float, float, float, float]):
            - `lm` (float): Lagrange multiplier statistic.
            - `lmpval` (float): p-value for LM statistic.
            - `fval` (float): F-statistic.
            - `fpval` (float): p-value for F-statistic.

    ???+ example "Examples"

        ```pycon {.py .python linenums="1" title="Setup"}
        >>> import statsmodels.api as sm
        >>> from ts_stat_tests.linearity.algorithms import lm
        >>> from ts_stat_tests.utils.data import data_random, data_line
        >>> exog = sm.add_constant(data_line.reshape(-1, 1))
        >>> y = 3 + 2 * data_line + 2 * data_line**2 + data_random
        >>> res = sm.OLS(y, exog).fit()
        >>> resid = res.resid

        ```

        ```pycon {.py .python linenums="1" title="Example 1: Basic Usage"}
        >>> lm_stat, lm_pval, f_stat, f_pval = lm(resid, exog)
        >>> print(f"LM Statistic: {lm_stat:.2f}")
        LM Statistic: 1000.00
        >>> print(f"LM p-value: {lm_pval:.4f}")
        LM p-value: 0.0000

        ```
    """
    res_lm = linear_lm(resid=resid, exog=exog, func=func)
    return (
        float(res_lm[0]),
        float(res_lm[1]),
        float(getattr(res_lm[2], "fvalue", np.nan)),
        float(getattr(res_lm[2], "pvalue", np.nan)),
    )

rb 🔗

rb(
    res: Union[RegressionResults, RegressionResultsWrapper],
    frac: float = 0.5,
    order_by: Optional[
        Union[ArrayLike, str, list[str]]
    ] = None,
    use_distance: bool = False,
    center: Optional[Union[float, int]] = None,
) -> tuple[float, float]

Summary

The Rainbow test for linearity.

Details

The Rainbow test is a test for linearity that is based on the idea that if a relationship is non-linear, it is more likely to be linear in a subset of the data than in the entire dataset.

Parameters:

Name Type Description Default
res Union[RegressionResults, RegressionResultsWrapper]

The results of a linear regression model from statsmodels.

required
frac float

The fraction of the data to use for the subset. Default: 0.5

0.5
order_by Optional[Union[ArrayLike, str, list[str]]]

Variable(s) to order by. If None, the original order is used.

None
use_distance bool

Whether to use distance from the center for ordering. Default: False

False
center Optional[Union[float, int]]

The center to use for distance calculation. Default: None

None

Returns:

Type Description
tuple[float, float]
  • fstat (float): The F-statistic of the test.
  • pvalue (float): The p-value associated with the F-statistic.
Examples
Setup
1
2
3
4
5
6
>>> import statsmodels.api as sm
>>> from ts_stat_tests.linearity.algorithms import rb
>>> from ts_stat_tests.utils.data import data_line, data_random
>>> X = sm.add_constant(data_line)
>>> y = 3 + 2 * data_line + 2 * data_line**2 + data_random
>>> res = sm.OLS(y, X).fit()
Example 1: Basic Usage
1
2
3
4
5
>>> rb_stat, rb_pval = rb(res)
>>> print(f"Rainbow F-Statistic: {rb_stat:.2f}")
Rainbow F-Statistic: 30.88
>>> print(f"p-value: {rb_pval:.4e}")
p-value: 1.8319e-230
References
  • Utts, J.M. (1982). "The Rainbow Test for Linearity." Biometrika, 69(2), 319-326.
Source code in src/ts_stat_tests/linearity/algorithms.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
@typechecked
def rb(
    res: Union[RegressionResults, RegressionResultsWrapper],
    frac: float = 0.5,
    order_by: Optional[Union[ArrayLike, str, list[str]]] = None,
    use_distance: bool = False,
    center: Optional[Union[float, int]] = None,
) -> tuple[float, float]:
    r"""
    !!! note "Summary"
        The Rainbow test for linearity.

    ???+ abstract "Details"
        The Rainbow test is a test for linearity that is based on the idea that if a relationship is non-linear, it is more likely to be linear in a subset of the data than in the entire dataset.

    Params:
        res (Union[RegressionResults, RegressionResultsWrapper]):
            The results of a linear regression model from `statsmodels`.
        frac (float):
            The fraction of the data to use for the subset.
            Default: `0.5`
        order_by (Optional[Union[ArrayLike, str, list[str]]]):
            Variable(s) to order by. If `None`, the original order is used.
        use_distance (bool):
            Whether to use distance from the center for ordering.
            Default: `False`
        center (Optional[Union[float, int]]):
            The center to use for distance calculation.
            Default: `None`

    Returns:
        (tuple[float, float]):
            - `fstat` (float): The F-statistic of the test.
            - `pvalue` (float): The p-value associated with the F-statistic.

    ???+ example "Examples"

        ```pycon {.py .python linenums="1" title="Setup"}
        >>> import statsmodels.api as sm
        >>> from ts_stat_tests.linearity.algorithms import rb
        >>> from ts_stat_tests.utils.data import data_line, data_random
        >>> X = sm.add_constant(data_line)
        >>> y = 3 + 2 * data_line + 2 * data_line**2 + data_random
        >>> res = sm.OLS(y, X).fit()

        ```

        ```pycon {.py .python linenums="1" title="Example 1: Basic Usage"}
        >>> rb_stat, rb_pval = rb(res)
        >>> print(f"Rainbow F-Statistic: {rb_stat:.2f}")
        Rainbow F-Statistic: 30.88
        >>> print(f"p-value: {rb_pval:.4e}")
        p-value: 1.8319e-230

        ```

    ??? question "References"
        - Utts, J.M. (1982). "The Rainbow Test for Linearity." Biometrika, 69(2), 319-326.
    """
    res_rb = linear_rainbow(res=res, frac=frac, order_by=order_by, use_distance=use_distance, center=center)
    return float(res_rb[0]), float(res_rb[1])

rr 🔗

rr(
    res: Union[RegressionResults, RegressionResultsWrapper],
    power: Union[int, list[int]] = 3,
    test_type: VALID_RR_TEST_TYPE_OPTIONS = "fitted",
    use_f: bool = False,
    cov_type: VALID_RR_COV_TYPE_OPTIONS = "nonrobust",
    *,
    cov_kwargs: Optional[dict] = None
) -> ContrastResults

Summary

Ramsey's RESET (Regression Specification Error Test) for linearity.

Details

RESET test for functional form misspecification. The test is based on the idea that if the model is correctly specified, then powers of the fitted values (or other variables) should not have any explanatory power when added to the model.

Parameters:

Name Type Description Default
res Union[RegressionResults, RegressionResultsWrapper]

The results of a linear regression model from statsmodels.

required
power Union[int, list[int]]

The powers of the fitted values or exogenous variables to include in the auxiliary regression. Default: 3

3
test_type VALID_RR_TEST_TYPE_OPTIONS

The type of test to perform. Options are "fitted", "exog", or "princomp". Default: "fitted"

'fitted'
use_f bool

Whether to use an F-test or a Chi-squared test. Default: False

False
cov_type VALID_RR_COV_TYPE_OPTIONS

The type of covariance matrix to use in the test. Default: "nonrobust"

'nonrobust'
cov_kwargs Optional[dict]

Optional keyword arguments for the covariance matrix calculation. Default: None

None

Returns:

Type Description
ContrastResults

The results of the RESET test.

Examples
Setup
1
2
3
4
5
6
>>> import statsmodels.api as sm
>>> from ts_stat_tests.linearity.algorithms import rr
>>> from ts_stat_tests.utils.data import data_line, data_random
>>> X = sm.add_constant(data_line)
>>> y = 3 + 2 * data_line + 2 * data_line**2 + data_random
>>> res = sm.OLS(y, X).fit()
Example 1: Basic Usage
1
2
3
>>> rr_res = rr(res)
>>> print(f"RESET Test Statistic: {rr_res.statistic:.2f}")
RESET Test Statistic: 225070.65
References
  • Ramsey, J.B. (1969). "Tests for Specification Errors in Classical Linear Least-squares Regression Analysis." Journal of the Royal Statistical Society, Series B, 31(2), 350-371.
Source code in src/ts_stat_tests/linearity/algorithms.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
@typechecked
def rr(
    res: Union[RegressionResults, RegressionResultsWrapper],
    power: Union[int, list[int]] = 3,
    test_type: VALID_RR_TEST_TYPE_OPTIONS = "fitted",
    use_f: bool = False,
    cov_type: VALID_RR_COV_TYPE_OPTIONS = "nonrobust",
    *,
    cov_kwargs: Optional[dict] = None,
) -> ContrastResults:
    r"""
    !!! note "Summary"
        Ramsey's RESET (Regression Specification Error Test) for linearity.

    ???+ abstract "Details"
        RESET test for functional form misspecification. The test is based on the idea that if the model is correctly specified, then powers of the fitted values (or other variables) should not have any explanatory power when added to the model.

    Params:
        res (Union[RegressionResults, RegressionResultsWrapper]):
            The results of a linear regression model from `statsmodels`.
        power (Union[int, list[int]]):
            The powers of the fitted values or exogenous variables to include in the auxiliary regression.
            Default: `3`
        test_type (VALID_RR_TEST_TYPE_OPTIONS):
            The type of test to perform. Options are `"fitted"`, `"exog"`, or `"princomp"`.
            Default: `"fitted"`
        use_f (bool):
            Whether to use an F-test or a Chi-squared test.
            Default: `False`
        cov_type (VALID_RR_COV_TYPE_OPTIONS):
            The type of covariance matrix to use in the test.
            Default: `"nonrobust"`
        cov_kwargs (Optional[dict]):
            Optional keyword arguments for the covariance matrix calculation.
            Default: `None`

    Returns:
        (ContrastResults):
            The results of the RESET test.

    ???+ example "Examples"

        ```pycon {.py .python linenums="1" title="Setup"}
        >>> import statsmodels.api as sm
        >>> from ts_stat_tests.linearity.algorithms import rr
        >>> from ts_stat_tests.utils.data import data_line, data_random
        >>> X = sm.add_constant(data_line)
        >>> y = 3 + 2 * data_line + 2 * data_line**2 + data_random
        >>> res = sm.OLS(y, X).fit()

        ```

        ```pycon {.py .python linenums="1" title="Example 1: Basic Usage"}
        >>> rr_res = rr(res)
        >>> print(f"RESET Test Statistic: {rr_res.statistic:.2f}")
        RESET Test Statistic: 225070.65

        ```

    ??? question "References"
        - Ramsey, J.B. (1969). "Tests for Specification Errors in Classical Linear Least-squares Regression Analysis." Journal of the Royal Statistical Society, Series B, 31(2), 350-371.
    """
    return linear_reset(
        res=res,
        power=power,  # type: ignore[arg-type]
        test_type=test_type,
        use_f=use_f,
        cov_type=cov_type,
        cov_kwargs=cov_kwargs,
    )