Skip to content

Commit 24103e0

Browse files
committed
Upped the coverage
1 parent 190aa6e commit 24103e0

14 files changed

Lines changed: 140 additions & 52 deletions

causal_testing/causal_testing_framework.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,6 @@ def create_causal_test(self, test: dict) -> CausalTestCase:
171171
outcome_variable=outcome_variable,
172172
treatment_value=test.get("treatment_value"),
173173
control_value=test.get("control_value"),
174-
adjustment_set=test.get(
175-
"adjustment_set",
176-
self.dag.identification(
177-
treatment_variable=treatment_variable, outcome_variable=outcome_variable, effect_type=effect_type
178-
),
179-
),
180174
alpha=test.get("alpha", 0.05),
181175
**estimator_kwargs,
182176
)

causal_testing/discovery/abstract_discovery.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,6 @@ def write_dot(self, individual: CausalDAG, output_file: str):
176176

177177
nx.drawing.nx_pydot.write_dot(individual, output_file)
178178

179-
def _json_stub_params(self, outcome: str) -> str:
180-
if pd.api.types.is_bool_dtype(self.df[outcome]):
181-
return {"estimator": "LogisticRegressionEstimator", "effect_measure": "unit_odds_ratio"}
182-
if pd.api.types.is_categorical_dtype(self.df[outcome]) or pd.api.types.is_object_dtype(self.df[outcome]):
183-
return {"estimator": "MultinomialRegressionEstimator", "effect_measure": "unit_odds_ratio"}
184-
if pd.api.types.is_numeric_dtype(self.df[outcome]):
185-
return {"estimator": "LinearRegressionEstimator", "effect_measure": "coefficient"}
186-
raise ValueError(f"Invalid datatype {self.df.dtypes[outcome]}")
187-
188179
def evaluate_tests(self, causal_dag: CausalDAG) -> pd.DataFrame:
189180
"""
190181
Generate and evaluate causal test cases from the supplied CausalDAG and return a list of edges for which the

causal_testing/estimation/abstract_estimator.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def __init__(
3333
outcome_variable: str,
3434
control_value: float = None,
3535
treatment_value: float = None,
36-
adjustment_set: set = None,
3736
adjustment_config: dict[str, Any] = None,
3837
alpha: float = 0.05,
3938
):
@@ -44,9 +43,6 @@ def __init__(
4443
self.control_value = control_value
4544
self.alpha = alpha
4645
self.adjustment_config = {} if adjustment_config is None else adjustment_config
47-
self.adjustment_set = (
48-
set(self.adjustment_config) if adjustment_set is None else adjustment_set.union(set(self.adjustment_config))
49-
)
5046
self.modelling_assumptions = []
5147
self.add_modelling_assumptions()
5248

@@ -68,8 +64,8 @@ def to_dict(self) -> dict:
6864
"treatment_variable": self.treatment_variable,
6965
"outcome_variable": self.outcome_variable,
7066
"alpha": self.alpha,
71-
"adjustment_set": sorted(self.adjustment_set),
7267
}
68+
7369
if self.adjustment_config:
7470
result["adjustment_config"] = self.adjustment_config
7571
if self.control_value is not None:

causal_testing/estimation/abstract_regression_estimator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@ def __init__(
3737
outcome_variable=outcome_variable,
3838
control_value=control_value,
3939
treatment_value=treatment_value,
40-
adjustment_set=adjustment_set,
4140
alpha=alpha,
4241
)
43-
4442
if formula is not None:
4543
self.formula = formula
4644
self._adjustment_set_from_formula()
@@ -49,6 +47,7 @@ def __init__(
4947
f"Specified formula {self.formula} does not match specified adjustment set {adjustment_set}"
5048
)
5149
elif adjustment_set is not None:
50+
self.adjustment_set = adjustment_set
5251
terms = [treatment_variable] + sorted(list(adjustment_set))
5352
self.formula = f"{outcome_variable} ~ {' + '.join(terms)}"
5453
else:
@@ -192,6 +191,8 @@ def to_dict(self) -> dict:
192191
:returns: A JSON serialisable dict representing the estimator.
193192
"""
194193
result = super().to_dict()
194+
if self.adjustment_set:
195+
result["adjustment_set"] = sorted(self.adjustment_set)
195196
if self.adjustment_config:
196197
result["adjustment_config"] = self.adjustment_config
197198
if self.formula:

causal_testing/estimation/experimental_estimator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ def __init__(
3232
outcome_variable=outcome_variable,
3333
treatment_value=treatment_value,
3434
control_value=control_value,
35-
adjustment_set=set(adjustment_config),
3635
adjustment_config=adjustment_config,
3736
alpha=alpha,
3837
)

causal_testing/estimation/instrumental_variable_estimator.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ def __init__(
2727
treatment_variable: str,
2828
treatment_value: float,
2929
control_value: float,
30-
adjustment_set: set,
3130
instrument: str,
3231
alpha: float = 0.05,
3332
bootstrap_size=100,
@@ -37,7 +36,6 @@ def __init__(
3736
outcome_variable=outcome_variable,
3837
treatment_value=treatment_value,
3938
control_value=control_value,
40-
adjustment_set=adjustment_set,
4139
alpha=alpha,
4240
)
4341

@@ -49,17 +47,13 @@ def add_modelling_assumptions(self):
4947
Add modelling assumptions to the estimator. This is a list of strings which list the modelling assumptions that
5048
must hold if the resulting causal inference is to be considered valid.
5149
"""
52-
self.modelling_assumptions.append(
53-
"""The instrument and the treatment, and the treatment and the outcome must be
54-
related linearly in the form Y = aX + b."""
55-
)
56-
self.modelling_assumptions.append(
57-
"""The three IV conditions must hold
50+
self.modelling_assumptions.append("""The instrument and the treatment, and the treatment and the outcome must be
51+
related linearly in the form Y = aX + b.""")
52+
self.modelling_assumptions.append("""The three IV conditions must hold
5853
(i) Instrument is associated with treatment
5954
(ii) Instrument does not affect outcome except through its potential effect on treatment
6055
(iii) Instrument and outcome do not share causes
61-
"""
62-
)
56+
""")
6357

6458
def iv_coefficient(self, df) -> float:
6559
"""

examples/poisson-line-process/example_pure_python.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from causal_testing.estimation.abstract_estimator import Estimator
1212
from causal_testing.estimation.effect_estimate import EffectEstimate
1313

14-
1514
logger = logging.getLogger(__name__)
1615
logging.basicConfig(level=logging.DEBUG, format="%(message)s")
1716

@@ -71,9 +70,6 @@ def test_poisson_intensity_num_shapes(save=False):
7170
outcome_variable="num_shapes_unit",
7271
treatment_value=treatment_value,
7372
control_value=control_value,
74-
adjustment_set=causal_dag.identification(
75-
treatment_variable="intensity", outcome_variable="num_shapes_unit"
76-
),
7773
alpha=0.05,
7874
),
7975
),

tests/estimation_tests/test_genetic_programming_regression_fitter.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import unittest
22

3+
import deap
34
import pandas as pd
45

5-
from causal_testing.estimation.genetic_programming_regression_fitter import GP
6+
from causal_testing.estimation.genetic_programming_regression_fitter import GP, mut_insert
67

78

89
def root(x):
@@ -11,10 +12,16 @@ def root(x):
1112

1213
class TestGP(unittest.TestCase):
1314
def test_init_invalid_fun_name(self):
15+
"""
16+
Test that GP raises ValueError if sympy conversions are provided for invalid function names.
17+
"""
1418
with self.assertRaises(ValueError):
1519
GP(df=pd.DataFrame(), features=[], outcome="", max_order=2, sympy_conversions={"power_1": ""})
1620

1721
def test_simplify_string(self):
22+
"""
23+
Test GP simplification
24+
"""
1825
gp = GP(
1926
df=None,
2027
features=["x1"],
@@ -24,6 +31,9 @@ def test_simplify_string(self):
2431
self.assertEqual(str(gp.simplify("power_1(x1)")), "x1")
2532

2633
def test_fitness(self):
34+
"""
35+
Test GP fitness function for perfect expression.
36+
"""
2737
gp = GP(
2838
df=pd.DataFrame({"x1": [1, 2, 3], "outcome": [2, 3, 4]}),
2939
features=["x1"],
@@ -33,6 +43,9 @@ def test_fitness(self):
3343
self.assertEqual(gp.fitness("add(x1, 1)"), (0,))
3444

3545
def test_fitness_inf(self):
46+
"""
47+
Test that GP returns infinity fitness for incalculable expressions.
48+
"""
3649
gp = GP(
3750
df=pd.DataFrame({"x1": [1, 2, 3], "outcome": [2, 3, 4]}),
3851
features=["x1"],
@@ -41,3 +54,17 @@ def test_fitness_inf(self):
4154
extra_operators=[(root, 1)],
4255
)
4356
self.assertEqual(gp.fitness("root(-1)"), (float("inf"),))
57+
58+
def test_mut_insert_no_primitives(self):
59+
"""Test that mut_insert returns the unmodified expression if there are no
60+
primitives of the appropriate type."""
61+
pset = deap.gp.PrimitiveSet("MAIN", 1)
62+
pset.addPrimitive(lambda x1, x2: x1 + x2, 1, name="add")
63+
expression = deap.gp.PrimitiveTree.from_string("add(ARG0, 1)", pset)
64+
self.assertEqual(
65+
mut_insert(
66+
expression,
67+
deap.gp.PrimitiveSet("MAIN", 1),
68+
),
69+
(expression,),
70+
)

tests/estimation_tests/test_instrumental_variable_estimator.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,31 @@ def test_estimate_coefficient(self):
2727
outcome_variable="Y",
2828
treatment_value=None,
2929
control_value=None,
30-
adjustment_set=set(),
3130
instrument="Z",
3231
)
3332
effect_estimate = iv_estimator.estimate_coefficient(self.df)
3433
self.assertEqual(effect_estimate.value[0], 2)
3534
self.assertEqual(effect_estimate.ci_low[0], 2)
3635
self.assertEqual(effect_estimate.ci_high[0], 2)
36+
37+
def test_to_dict(self):
38+
iv_estimator = InstrumentalVariableEstimator(
39+
treatment_variable="X",
40+
outcome_variable="Y",
41+
control_value=0,
42+
treatment_value=1,
43+
instrument="Z",
44+
)
45+
self.assertEqual(
46+
iv_estimator.to_dict(),
47+
{
48+
"name": "InstrumentalVariableEstimator",
49+
"treatment_variable": "X",
50+
"outcome_variable": "Y",
51+
"alpha": 0.05,
52+
"control_value": 0,
53+
"treatment_value": 1,
54+
"instrument": "Z",
55+
"bootstrap_size": 100,
56+
},
57+
)

tests/estimation_tests/test_linear_regression_estimator.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,35 @@ def test_program_11_2_with_robustness_validation(self):
296296
round(cv.estimate_robustness(linear_regression_estimator.fit_model(df))["treatments"], 4), 0.7353
297297
)
298298

299+
def test_to_dict(self):
300+
linear_regression_estimator = LinearRegressionEstimator(
301+
treatment_variable="X",
302+
outcome_variable="Y",
303+
control_value=0,
304+
treatment_value=1,
305+
adjustment_set={"Z"},
306+
adjustment_config={"Z": 1},
307+
)
308+
self.assertEqual(
309+
linear_regression_estimator.to_dict(),
310+
{
311+
"name": "LinearRegressionEstimator",
312+
"treatment_variable": "X",
313+
"outcome_variable": "Y",
314+
"alpha": 0.05,
315+
"adjustment_set": ["Z"],
316+
"formula": "Y ~ X + Z",
317+
"adjustment_set": ["Z"],
318+
"adjustment_config": {"Z": 1},
319+
"control_value": 0,
320+
"treatment_value": 1,
321+
},
322+
)
323+
299324
def test_gp(self):
300325
df = pd.DataFrame()
301326
df["X"] = np.arange(10).astype(float)
302327
df["Y"] = 1 / (df["X"] + 1)
303-
print(df)
304328
linear_regression_estimator = LinearRegressionEstimator(
305329
treatment_variable="X",
306330
outcome_variable="Y",

0 commit comments

Comments
 (0)