Skip to content

Commit 9cf6b51

Browse files
committed
add integration tests for regression kink design
1 parent 8ce77a1 commit 9cf6b51

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

causalpy/tests/test_integration_pymc_examples.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
import pandas as pd
23
import pytest
34

@@ -6,6 +7,18 @@
67
sample_kwargs = {"tune": 20, "draws": 20, "chains": 2, "cores": 2}
78

89

10+
def reg_kink_function(x, beta, kink):
11+
"""Utility function for regression kink design. Returns a piecewise linear function
12+
evaluated at x with a kink at kink and parameters beta"""
13+
return (
14+
beta[0]
15+
+ beta[1] * x
16+
+ beta[2] * x**2
17+
+ beta[3] * (x - kink) * (x >= kink)
18+
+ beta[4] * (x - kink) ** 2 * (x >= kink)
19+
)
20+
21+
922
@pytest.mark.integration
1023
def test_did():
1124
"""
@@ -217,6 +230,77 @@ def test_rd_drinking():
217230
assert len(result.idata.posterior.coords["draw"]) == sample_kwargs["draws"]
218231

219232

233+
@pytest.mark.integration
234+
def test_rkink():
235+
"""
236+
Test Regression Kink design.
237+
238+
Loads data and checks:
239+
1. data is a dataframe
240+
2. pymc_experiments.RegressionKink returns correct type
241+
3. the correct number of MCMC chains exists in the posterior inference data
242+
4. the correct number of MCMC draws exists in the posterior inference data
243+
"""
244+
# define parameters for data generation
245+
seed = 42
246+
rng = np.random.default_rng(seed)
247+
N = 50
248+
kink = 0.5
249+
beta = [0, -1, 0, 2, 0]
250+
sigma = 0.05
251+
# generate data
252+
x = rng.uniform(-1, 1, N)
253+
y = reg_kink_function(x, beta, kink) + rng.normal(0, sigma, N)
254+
df = pd.DataFrame({"x": x, "y": y, "treated": x >= kink})
255+
# run experiment
256+
result = cp.pymc_experiments.RegressionKink(
257+
df,
258+
formula=f"y ~ 1 + x + I((x-{kink})*treated)",
259+
model=cp.pymc_models.LinearRegression(sample_kwargs=sample_kwargs),
260+
kink_point=kink,
261+
)
262+
assert isinstance(df, pd.DataFrame)
263+
assert isinstance(result, cp.pymc_experiments.RegressionKink)
264+
assert len(result.idata.posterior.coords["chain"]) == sample_kwargs["chains"]
265+
assert len(result.idata.posterior.coords["draw"]) == sample_kwargs["draws"]
266+
267+
268+
@pytest.mark.integration
269+
def test_rkink_bandwidth():
270+
"""
271+
Test Regression Kink experiment with bandwidth parameter.
272+
273+
Generates synthetic data and checks:
274+
1. data is a dataframe
275+
2. pymc_experiments.RegressionKink returns correct type
276+
3. the correct number of MCMC chains exists in the posterior inference data
277+
4. the correct number of MCMC draws exists in the posterior inference data
278+
"""
279+
# define parameters for data generation
280+
seed = 42
281+
rng = np.random.default_rng(seed)
282+
N = 50
283+
kink = 0.5
284+
beta = [0, -1, 0, 2, 0]
285+
sigma = 0.05
286+
# generate data
287+
x = rng.uniform(-1, 1, N)
288+
y = reg_kink_function(x, beta, kink) + rng.normal(0, sigma, N)
289+
df = pd.DataFrame({"x": x, "y": y, "treated": x >= kink})
290+
# run experiment
291+
result = cp.pymc_experiments.RegressionKink(
292+
df,
293+
formula=f"y ~ 1 + x + I((x-{kink})*treated)",
294+
model=cp.pymc_models.LinearRegression(sample_kwargs=sample_kwargs),
295+
kink_point=kink,
296+
bandwidth=0.3,
297+
)
298+
assert isinstance(df, pd.DataFrame)
299+
assert isinstance(result, cp.pymc_experiments.RegressionKink)
300+
assert len(result.idata.posterior.coords["chain"]) == sample_kwargs["chains"]
301+
assert len(result.idata.posterior.coords["draw"]) == sample_kwargs["draws"]
302+
303+
220304
@pytest.mark.integration
221305
def test_its():
222306
"""

0 commit comments

Comments
 (0)