Skip to content

Commit 1da80fd

Browse files
committed
resolved merge
2 parents 2996331 + a626c1e commit 1da80fd

29 files changed

+1379
-1297
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ repos:
2525
exclude: &exclude_pattern 'iv_weak_instruments.ipynb'
2626
args: ["--maxkb=1500"]
2727
- repo: https://github.com/astral-sh/ruff-pre-commit
28-
rev: v0.11.11
28+
rev: v0.11.12
2929
hooks:
3030
# Run the linter
3131
- id: ruff

CONTRIBUTING.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,19 @@ We recommend that your contribution complies with the following guidelines befor
167167

168168
## Building the documentation locally
169169

170-
A local build of the docs is achieved by:
170+
To build the documentation, run from the **project root**:
171171

172172
```bash
173-
cd docs
174173
make html
175174
```
176-
177-
Sometimes not all changes are recognised. In that case run this (again from within the `docs` folder):
178-
175+
To clean and rebuild the documentation from scratch:
179176
```bash
180-
make clean && make html
177+
make cleandocs
178+
make html
181179
```
180+
Docs are built in docs/_build/html, but these docs are not committed to the GitHub repository due to .gitignore.
182181

183-
Docs are built in `docs/_build`, but these docs are _not_ committed to the GitHub repository due to `.gitignore`.
182+
📌 Note: The previous docs/Makefile has been removed. Please use only the root-level Makefile for documentation commands
184183

185184
## Overview of code structure
186185

Makefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: init lint check_lint test
1+
.PHONY: init lint check_lint test uml html cleandocs
22

33
init:
44
python -m pip install -e . --no-deps
@@ -20,3 +20,12 @@ test:
2020

2121
uml:
2222
pyreverse -o png causalpy --output-directory docs/source/_static --ignore tests
23+
24+
# Docs build commands
25+
26+
html:
27+
sphinx-build -b html docs/source docs/_build
28+
29+
cleandocs:
30+
rm -rf docs/_build
31+
rm -rf docs/source/api/generated

causalpy/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
# limitations under the License.
1414
import arviz as az
1515

16-
import causalpy.pymc_experiments as pymc_experiments # to be deprecated
1716
import causalpy.pymc_models as pymc_models
18-
import causalpy.skl_experiments as skl_experiments # to be deprecated
1917
import causalpy.skl_models as skl_models
2018
from causalpy.skl_models import create_causalpy_compatible_class
2119
from causalpy.version import __version__
@@ -41,11 +39,9 @@
4139
"InversePropensityWeighting",
4240
"load_data",
4341
"PrePostNEGD",
44-
"pymc_experiments", # to be deprecated
4542
"pymc_models",
4643
"RegressionDiscontinuity",
4744
"RegressionKink",
48-
"skl_experiments", # to be deprecated
4945
"skl_models",
5046
"SyntheticControl",
5147
]

causalpy/experiments/diff_in_diff.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import numpy as np
2020
import pandas as pd
2121
import seaborn as sns
22+
import xarray as xr
2223
from matplotlib import pyplot as plt
2324
from patsy import build_design_matrices, dmatrices
2425
from sklearn.base import RegressorMixin
@@ -87,7 +88,8 @@ def __init__(
8788
**kwargs,
8889
) -> None:
8990
super().__init__(model=model)
90-
91+
# rename the index to "obs_ind"
92+
data.index.name = "obs_ind"
9193
self.data = data
9294
self.expt_type = "Difference in Differences"
9395
self.formula = formula
@@ -102,6 +104,21 @@ def __init__(
102104
self.y, self.X = np.asarray(y), np.asarray(X)
103105
self.outcome_variable_name = y.design_info.column_names[0]
104106

107+
# turn into xarray.DataArray's
108+
self.X = xr.DataArray(
109+
self.X,
110+
dims=["obs_ind", "coeffs"],
111+
coords={
112+
"obs_ind": np.arange(self.X.shape[0]),
113+
"coeffs": self.labels,
114+
},
115+
)
116+
self.y = xr.DataArray(
117+
self.y[:, 0],
118+
dims=["obs_ind"],
119+
coords={"obs_ind": np.arange(self.y.shape[0])},
120+
)
121+
105122
# fit model
106123
if isinstance(self.model, PyMCModel):
107124
COORDS = {"coeffs": self.labels, "obs_ind": np.arange(self.X.shape[0])}
@@ -183,13 +200,15 @@ def __init__(
183200
)
184201
elif isinstance(self.model, RegressorMixin):
185202
# This is the coefficient on the interaction term
186-
# TODO: THIS IS NOT YET CORRECT ?????
203+
# TODO: CHECK FOR CORRECTNESS
187204
self.causal_impact = (
188205
self.y_pred_treatment[1] - self.y_pred_counterfactual[0]
189-
)[0]
206+
)
190207
else:
191208
raise ValueError("Model type not recognized")
192209

210+
return
211+
193212
def input_validation(self):
194213
"""Validate the input data and model formula for correctness"""
195214
if "post_treatment" not in self.formula:

causalpy/experiments/interrupted_time_series.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import arviz as az
2121
import numpy as np
2222
import pandas as pd
23+
import xarray as xr
2324
from matplotlib import pyplot as plt
2425
from patsy import build_design_matrices, dmatrices
2526
from sklearn.base import RegressorMixin
@@ -231,7 +232,13 @@ def __init__(
231232
**kwargs,
232233
) -> None:
233234
super().__init__(model=model)
235+
236+
# rename the index to "obs_ind"
237+
data.index.name = "obs_ind"
234238
self.input_validation(data, treatment_time, model)
239+
self.treatment_time = treatment_time
240+
# set experiment type - usually done in subclasses
241+
self.expt_type = "Pre-Post Fit"
235242

236243
self.treatment_time = treatment_time
237244
self.formula = formula
@@ -285,13 +292,38 @@ def __init__(
285292
)
286293
self.post_X = np.asarray(new_x)
287294
self.post_y = np.asarray(new_y)
295+
# turn into xarray.DataArray's
296+
self.pre_X = xr.DataArray(
297+
self.pre_X,
298+
dims=["obs_ind", "coeffs"],
299+
coords={
300+
"obs_ind": self.datapre.index,
301+
"coeffs": self.labels,
302+
},
303+
)
304+
self.pre_y = xr.DataArray(
305+
self.pre_y[:, 0],
306+
dims=["obs_ind"],
307+
coords={"obs_ind": self.datapre.index},
308+
)
309+
self.post_X = xr.DataArray(
310+
self.post_X,
311+
dims=["obs_ind", "coeffs"],
312+
coords={
313+
"obs_ind": self.datapost.index,
314+
"coeffs": self.labels,
315+
},
316+
)
317+
self.post_y = xr.DataArray(
318+
self.post_y[:, 0],
319+
dims=["obs_ind"],
320+
coords={"obs_ind": self.datapost.index},
321+
)
288322

289323
# calculate the counterfactual
290324
self.post_pred = self.model.predict(X=self.post_X)
291-
self.pre_impact = self.model.calculate_impact(self.pre_y[:, 0], self.pre_pred)
292-
self.post_impact = self.model.calculate_impact(
293-
self.post_y[:, 0], self.post_pred
294-
)
325+
self.pre_impact = self.model.calculate_impact(self.pre_y, self.pre_pred)
326+
self.post_impact = self.model.calculate_impact(self.post_y, self.post_pred)
295327
self.post_impact_cumulative = self.model.calculate_cumulative_impact(
296328
self.post_impact
297329
)

causalpy/experiments/prepostnegd.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import numpy as np
2222
import pandas as pd
2323
import seaborn as sns
24+
import xarray as xr
2425
from matplotlib import pyplot as plt
2526
from patsy import build_design_matrices, dmatrices
2627
from sklearn.base import RegressorMixin
@@ -111,6 +112,21 @@ def __init__(
111112
self.y, self.X = np.asarray(y), np.asarray(X)
112113
self.outcome_variable_name = y.design_info.column_names[0]
113114

115+
# turn into xarray.DataArray's
116+
self.X = xr.DataArray(
117+
self.X,
118+
dims=["obs_ind", "coeffs"],
119+
coords={
120+
"obs_ind": np.arange(self.X.shape[0]),
121+
"coeffs": self.labels,
122+
},
123+
)
124+
self.y = xr.DataArray(
125+
self.y[:, 0],
126+
dims=["obs_ind"],
127+
coords={"obs_ind": self.data.index},
128+
)
129+
114130
# fit the model to the observed (pre-intervention) data
115131
if isinstance(self.model, PyMCModel):
116132
COORDS = {"coeffs": self.labels, "obs_ind": np.arange(self.X.shape[0])}

causalpy/experiments/regression_discontinuity.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from matplotlib import pyplot as plt
2424
from patsy import build_design_matrices, dmatrices
2525
from sklearn.base import RegressorMixin
26-
26+
import xarray as xr
2727
from causalpy.custom_exceptions import (
2828
DataException,
2929
FormulaException,
@@ -121,6 +121,21 @@ def __init__(
121121
self.y, self.X = np.asarray(y), np.asarray(X)
122122
self.outcome_variable_name = y.design_info.column_names[0]
123123

124+
# turn into xarray.DataArray's
125+
self.X = xr.DataArray(
126+
self.X,
127+
dims=["obs_ind", "coeffs"],
128+
coords={
129+
"obs_ind": np.arange(self.X.shape[0]),
130+
"coeffs": self.labels,
131+
},
132+
)
133+
self.y = xr.DataArray(
134+
self.y[:, 0],
135+
dims=["obs_ind"],
136+
coords={"obs_ind": np.arange(self.y.shape[0])},
137+
)
138+
124139
# fit model
125140
if isinstance(self.model, PyMCModel):
126141
# fit the model to the observed (pre-intervention) data

causalpy/experiments/regression_kink.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import pandas as pd
2424
import seaborn as sns
2525
from patsy import build_design_matrices, dmatrices
26-
26+
import xarray as xr
2727
from causalpy.plot_utils import plot_xY
2828

2929
from .base import BaseExperiment
@@ -84,6 +84,21 @@ def __init__(
8484
self.y, self.X = np.asarray(y), np.asarray(X)
8585
self.outcome_variable_name = y.design_info.column_names[0]
8686

87+
# turn into xarray.DataArray's
88+
self.X = xr.DataArray(
89+
self.X,
90+
dims=["obs_ind", "coeffs"],
91+
coords={
92+
"obs_ind": np.arange(self.X.shape[0]),
93+
"coeffs": self.labels,
94+
},
95+
)
96+
self.y = xr.DataArray(
97+
self.y[:, 0],
98+
dims=["obs_ind"],
99+
coords={"obs_ind": np.arange(self.y.shape[0])},
100+
)
101+
87102
COORDS = {"coeffs": self.labels, "obs_ind": np.arange(self.X.shape[0])}
88103
self.model.fit(X=self.X, y=self.y, coords=COORDS)
89104

0 commit comments

Comments
 (0)