mini-causal 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mini_causal-0.1.3/LICENSE +21 -0
- mini_causal-0.1.3/PKG-INFO +21 -0
- mini_causal-0.1.3/README.md +3 -0
- mini_causal-0.1.3/mini_causal/__init__.py +1 -0
- mini_causal-0.1.3/mini_causal/model_selection.py +1 -0
- mini_causal-0.1.3/mini_causal/utils.py +157 -0
- mini_causal-0.1.3/mini_causal.egg-info/PKG-INFO +21 -0
- mini_causal-0.1.3/mini_causal.egg-info/SOURCES.txt +19 -0
- mini_causal-0.1.3/mini_causal.egg-info/dependency_links.txt +1 -0
- mini_causal-0.1.3/mini_causal.egg-info/requires.txt +3 -0
- mini_causal-0.1.3/mini_causal.egg-info/top_level.txt +1 -0
- mini_causal-0.1.3/pyproject.toml +31 -0
- mini_causal-0.1.3/setup.cfg +4 -0
- mini_causal-0.1.3/tests/test_causal_counter.py +134 -0
- mini_causal-0.1.3/tests/test_causal_counter_classifier.py +74 -0
- mini_causal-0.1.3/tests/test_causal_counter_reg.py +136 -0
- mini_causal-0.1.3/tests/test_causality_classifier.py +69 -0
- mini_causal-0.1.3/tests/test_causality_reg.py +67 -0
- mini_causal-0.1.3/tests/test_partial_counter.py +105 -0
- mini_causal-0.1.3/tests/test_partial_counter_classifier.py +57 -0
- mini_causal-0.1.3/tests/test_partial_counter_reg.py +47 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MasemeneMatlakanaBenny
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mini-causal
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: A mini package for causal inference
|
|
5
|
+
Author-email: Masemene Matlakana Benny <bennymasemene46@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/MasemeneMatlakanaBenny/Mini_Causal
|
|
7
|
+
Project-URL: Issues, https://github.com/MasemeneMatlakana/Mini_Causal/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: pandas>=3.0.2
|
|
15
|
+
Requires-Dist: numpy>=2.4.4
|
|
16
|
+
Requires-Dist: scipy>=1.17.1
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# MiniCausal
|
|
20
|
+
|
|
21
|
+

|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from mini_causal.utils import treatment_control_selection
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from sklearn import clone
|
|
4
|
+
|
|
5
|
+
def clone_model(model):
|
|
6
|
+
return clone(model)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def treatment_control_selection(df, control_size=0.2, random_seed=None):
|
|
10
|
+
"""
|
|
11
|
+
Randomly split dataframe into treatment and control groups.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
df (pd.DataFrame):
|
|
15
|
+
the input dataframe
|
|
16
|
+
|
|
17
|
+
control_size (float):
|
|
18
|
+
Fraction assigned to control group
|
|
19
|
+
|
|
20
|
+
random_seed(int or None):
|
|
21
|
+
for reproducibilit
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
treatment,control
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
if random_seed is not None:
|
|
28
|
+
np.random.seed(random_seed)
|
|
29
|
+
|
|
30
|
+
n_samples = len(df)
|
|
31
|
+
|
|
32
|
+
# Shuffle row indices
|
|
33
|
+
indices = np.random.permutation(n_samples)
|
|
34
|
+
|
|
35
|
+
# Split point
|
|
36
|
+
split_idx = int(n_samples * (1 - control_size))
|
|
37
|
+
|
|
38
|
+
# Indices
|
|
39
|
+
treat_idx = indices[:split_idx]
|
|
40
|
+
control_idx = indices[split_idx:]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
treatment = df.iloc[treat_idx]
|
|
44
|
+
control = df.iloc[control_idx]
|
|
45
|
+
|
|
46
|
+
return treatment,control
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def make_treatment_control_df(treatment,control)->pd.DataFrame:
|
|
51
|
+
df=pd.concat([treatment,control])
|
|
52
|
+
|
|
53
|
+
return df.sort_index()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def summary_stats(treatment:np.ndarray,control:np.ndarray)->pd.DataFrame:
|
|
57
|
+
n_treatment=len(treatment)
|
|
58
|
+
n_control=len(control)
|
|
59
|
+
|
|
60
|
+
mean_control_preds=float(np.mean(control))
|
|
61
|
+
mean_treatment_preds=float(np.mean(treatment))
|
|
62
|
+
|
|
63
|
+
variance_treatment=float(np.var(treatment,ddof=1))
|
|
64
|
+
variance_control=float(np.var(control,ddof=1))
|
|
65
|
+
|
|
66
|
+
return pd.DataFrame(
|
|
67
|
+
{
|
|
68
|
+
"type":["treatment","control"],
|
|
69
|
+
"n":[n_treatment,n_control],
|
|
70
|
+
"mean":[mean_treatment_preds,mean_control_preds],
|
|
71
|
+
"sample_variance":[variance_treatment,variance_control]
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def causal_effects_stratum(X:pd.DataFrame,causal_effects:np.ndarray,strata_feature:str):
|
|
77
|
+
"""
|
|
78
|
+
Args:
|
|
79
|
+
X (pd.DataFrame):
|
|
80
|
+
X values stored in a dataframe that will be used for the prediction.
|
|
81
|
+
|
|
82
|
+
causal_effects(np.ndarray):
|
|
83
|
+
the causal effects values
|
|
84
|
+
|
|
85
|
+
strata_feature(str):
|
|
86
|
+
the name of the feature that will be used for strata
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
pd.DataFrame:
|
|
90
|
+
- a dataframe with the following columns: strata_feature,mean,size and weight of the strata
|
|
91
|
+
- the mean is based on the type arg i.e if preds ,then it will be the mean for the
|
|
92
|
+
predictions, else if probs then it will be the mean for the predicted probabilities
|
|
93
|
+
"""
|
|
94
|
+
N=len(X)
|
|
95
|
+
X["causal_effects"]=causal_effects
|
|
96
|
+
|
|
97
|
+
results=X.groupby(strata_feature)["causal_effects"].agg(["mean","size"]).reset_index()
|
|
98
|
+
results["weight_rss"]= results["size"] * N
|
|
99
|
+
|
|
100
|
+
return results
|
|
101
|
+
|
|
102
|
+
def stratum_weight_rss(X:pd.DataFrame,
|
|
103
|
+
treatment_model,
|
|
104
|
+
control_model,
|
|
105
|
+
feature:str,
|
|
106
|
+
strata_feature:str,
|
|
107
|
+
type:str="preds")->pd.DataFrame:
|
|
108
|
+
"""
|
|
109
|
+
The causal effect based on the stratum to validate the effect per stratum of the treatment.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
X (pd.DataFrame):
|
|
113
|
+
X values stored in a dataframe that will be used for the prediction.
|
|
114
|
+
|
|
115
|
+
strata_feature (str):
|
|
116
|
+
the name of the feature that will be used for strata
|
|
117
|
+
|
|
118
|
+
treatment_model:
|
|
119
|
+
the trained treatment estimator
|
|
120
|
+
|
|
121
|
+
control_model:
|
|
122
|
+
the trained control estimator
|
|
123
|
+
|
|
124
|
+
type (str): {preds,probs}
|
|
125
|
+
return the stratum values based on the predicted probabilites or predicted values of the target
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
pd.DataFrame:
|
|
130
|
+
- a dataframe with the following columns: strata_feature,mean,size and weight of the strata
|
|
131
|
+
- the mean is based on the type arg i.e if preds ,then it will be the mean for the
|
|
132
|
+
predictions, else if probs then it will be the mean for the predicted probabilities
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
X_control=X.drop([feature,strata_feature],axis=1)
|
|
136
|
+
X_treatment=X.drop(strata_feature,axis=1)
|
|
137
|
+
|
|
138
|
+
treatment_probs=treatment_model.predict_proba(X_treatment)[:,1]
|
|
139
|
+
control_probs=control_model.predict_proba(X_control)[:,1]
|
|
140
|
+
|
|
141
|
+
treatment_preds=treatment_model.predict(X_treatment)
|
|
142
|
+
control_preds=control_model.predict(X_control)
|
|
143
|
+
|
|
144
|
+
causal_effects_probs=treatment_probs-control_probs
|
|
145
|
+
causal_effects=treatment_preds-control_preds
|
|
146
|
+
|
|
147
|
+
if type=="preds":
|
|
148
|
+
return causal_effects_stratum(X=X,causal_effects=causal_effects_probs,
|
|
149
|
+
strata_feature=strata_feature)
|
|
150
|
+
|
|
151
|
+
elif type=="probs":
|
|
152
|
+
return causal_effects_stratum(X=X,causal_effects=causal_effects,
|
|
153
|
+
strata_feature=strata_feature)
|
|
154
|
+
|
|
155
|
+
else:
|
|
156
|
+
raise ValueError("Type invalid")
|
|
157
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mini-causal
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: A mini package for causal inference
|
|
5
|
+
Author-email: Masemene Matlakana Benny <bennymasemene46@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/MasemeneMatlakanaBenny/Mini_Causal
|
|
7
|
+
Project-URL: Issues, https://github.com/MasemeneMatlakana/Mini_Causal/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: pandas>=3.0.2
|
|
15
|
+
Requires-Dist: numpy>=2.4.4
|
|
16
|
+
Requires-Dist: scipy>=1.17.1
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# MiniCausal
|
|
20
|
+
|
|
21
|
+

|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
mini_causal/__init__.py
|
|
5
|
+
mini_causal/model_selection.py
|
|
6
|
+
mini_causal/utils.py
|
|
7
|
+
mini_causal.egg-info/PKG-INFO
|
|
8
|
+
mini_causal.egg-info/SOURCES.txt
|
|
9
|
+
mini_causal.egg-info/dependency_links.txt
|
|
10
|
+
mini_causal.egg-info/requires.txt
|
|
11
|
+
mini_causal.egg-info/top_level.txt
|
|
12
|
+
tests/test_causal_counter.py
|
|
13
|
+
tests/test_causal_counter_classifier.py
|
|
14
|
+
tests/test_causal_counter_reg.py
|
|
15
|
+
tests/test_causality_classifier.py
|
|
16
|
+
tests/test_causality_reg.py
|
|
17
|
+
tests/test_partial_counter.py
|
|
18
|
+
tests/test_partial_counter_classifier.py
|
|
19
|
+
tests/test_partial_counter_reg.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mini_causal
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mini-causal"
|
|
7
|
+
version = "0.1.3"
|
|
8
|
+
description = "A mini package for causal inference"
|
|
9
|
+
authors = [
|
|
10
|
+
{name = "Masemene Matlakana Benny", email = "bennymasemene46@gmail.com"}
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.12"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
# requirements:
|
|
21
|
+
"pandas >= 3.0.2",
|
|
22
|
+
"numpy >= 2.4.4",
|
|
23
|
+
"scipy >= 1.17.1"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://github.com/MasemeneMatlakanaBenny/Mini_Causal"
|
|
28
|
+
Issues = "https://github.com/MasemeneMatlakana/Mini_Causal/issues"
|
|
29
|
+
|
|
30
|
+
[tool.setuptools]
|
|
31
|
+
packages = ["mini_causal"]
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.linear_model import LogisticRegression
|
|
5
|
+
from mini_causal.causal_counter import CausalCounterfactual
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def sample_data():
|
|
10
|
+
df=pd.DataFrame({
|
|
11
|
+
"X1":[11,19,20,23,24,25,11,19,20],
|
|
12
|
+
"X2":[23,15,17,8,12,15,17,16,17],
|
|
13
|
+
"location":["North","North","South","South","South","North","South","South","North"],
|
|
14
|
+
"y_class":np.array([19,11,17,30,31,32,77,80,19])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
return df
|
|
19
|
+
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def log_model():
|
|
22
|
+
"""
|
|
23
|
+
Returns:
|
|
24
|
+
LogisticRegression fitted on sample set
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
return LogisticRegression(solver="liblinear")
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def log_causal_counter(sample_data,log_model):
|
|
31
|
+
treatment=sample_data
|
|
32
|
+
control=sample_data
|
|
33
|
+
model=log_model
|
|
34
|
+
|
|
35
|
+
log_counter=CausalCounterfactual(model=model,
|
|
36
|
+
treatment=treatment,
|
|
37
|
+
control=control,
|
|
38
|
+
feature="X1",
|
|
39
|
+
label="y_class")
|
|
40
|
+
|
|
41
|
+
return log_counter
|
|
42
|
+
|
|
43
|
+
def test_hypotheses_keys(log_causal_counter):
|
|
44
|
+
log_counter=log_causal_counter
|
|
45
|
+
|
|
46
|
+
assert "Ho" in log_counter.hypotheses()
|
|
47
|
+
assert "Ha" in log_counter.hypotheses()
|
|
48
|
+
|
|
49
|
+
def test_control_model(log_causal_counter,log_model,sample_data):
|
|
50
|
+
log_counter=log_causal_counter
|
|
51
|
+
control=sample_data
|
|
52
|
+
model=log_model
|
|
53
|
+
|
|
54
|
+
X_control=control.drop(["X1","y_class"],axis=1)
|
|
55
|
+
y_control=control["y_class"]
|
|
56
|
+
|
|
57
|
+
model.fit(X_control,y_control)
|
|
58
|
+
|
|
59
|
+
assert model == log_counter.control_model()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_treatment_model(log_causal_counter,log_model,sample_data):
|
|
63
|
+
log_counter=log_causal_counter
|
|
64
|
+
treatment=sample_data
|
|
65
|
+
model=log_model
|
|
66
|
+
|
|
67
|
+
X=treatment.drop("y_class",axis=1)
|
|
68
|
+
y=treatment["y_class"]
|
|
69
|
+
|
|
70
|
+
model.fit(X,y)
|
|
71
|
+
|
|
72
|
+
assert model == log_counter.treatment_model()
|
|
73
|
+
|
|
74
|
+
def test_average_causality(log_causal_counter):
|
|
75
|
+
log_counter=log_causal_counter
|
|
76
|
+
|
|
77
|
+
assert type(log_counter.average_causal_effect()) == float
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_inferential_stats(log_causal_counter):
|
|
81
|
+
log_counter=log_causal_counter
|
|
82
|
+
|
|
83
|
+
correlation=log_counter.correlation()
|
|
84
|
+
pvalue=log_counter.p_value
|
|
85
|
+
|
|
86
|
+
t_stats=log_counter.t_statistic
|
|
87
|
+
|
|
88
|
+
assert type(correlation)==float
|
|
89
|
+
assert type(pvalue)==float
|
|
90
|
+
assert type(t_stats)==float
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_correlation_ci(log_causal_counter):
|
|
94
|
+
log_counter=log_causal_counter
|
|
95
|
+
|
|
96
|
+
assert "upper_bound" in log_counter.correlation_confidence_interval()
|
|
97
|
+
assert "lower_bound" in log_counter.correlation_confidence_interval()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_strat_exp(log_causal_counter,sample_data):
|
|
101
|
+
log_counter=log_causal_counter
|
|
102
|
+
X=sample_data.drop("y_class",axis=1)
|
|
103
|
+
|
|
104
|
+
strat_df=log_counter.causal_effect_stratified(
|
|
105
|
+
X=X,
|
|
106
|
+
strata_feature="location",
|
|
107
|
+
type="preds"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
columns=strat_df.columns
|
|
111
|
+
|
|
112
|
+
assert "mean" in columns
|
|
113
|
+
assert "size" in columns
|
|
114
|
+
assert "weight_rss" in columns
|
|
115
|
+
|
|
116
|
+
def test_individual_causal_effects(log_causal_counter,sample_data):
|
|
117
|
+
log_counter=log_causal_counter
|
|
118
|
+
df=sample_data
|
|
119
|
+
|
|
120
|
+
X=df.drop(["y_class","location"],axis=1)
|
|
121
|
+
y=df["y_class"]
|
|
122
|
+
|
|
123
|
+
causal_effects=log_counter.individual_causal_effects(X=X)
|
|
124
|
+
causal_resids=log_counter.individual_causal_effects_resid(X=X,y_true=y)
|
|
125
|
+
|
|
126
|
+
assert type(causal_effects)==np.ndarray
|
|
127
|
+
assert type(causal_resids)==np.ndarray
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.linear_model import LogisticRegression
|
|
5
|
+
from mini_causal.causal_counter import CausalCounterfactualClassifier
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def sample_data():
|
|
10
|
+
df=pd.DataFrame({
|
|
11
|
+
"X1":[11,19,20,23,24,25,11,19,20],
|
|
12
|
+
"X2":[23,15,17,8,12,15,17,16,17],
|
|
13
|
+
"y_class":np.array([19,11,17,30,31,32,77,80,19])
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
return df
|
|
18
|
+
|
|
19
|
+
@pytest.fixture
|
|
20
|
+
def log_model():
|
|
21
|
+
"""
|
|
22
|
+
Returns:
|
|
23
|
+
LogisticRegression fitted on sample set
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
return LogisticRegression(solver="liblinear")
|
|
27
|
+
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def log_causal_counter(sample_data,log_model):
|
|
30
|
+
treatment=sample_data
|
|
31
|
+
control=sample_data
|
|
32
|
+
model=log_model
|
|
33
|
+
|
|
34
|
+
log_counter=CausalCounterfactualClassifier(model=model,
|
|
35
|
+
treatment=treatment,
|
|
36
|
+
control=control,
|
|
37
|
+
feature="X1",
|
|
38
|
+
label="y_class")
|
|
39
|
+
|
|
40
|
+
return log_counter
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_individual_causal_effects(log_causal_counter,sample_data):
|
|
45
|
+
log_counter=log_causal_counter
|
|
46
|
+
df=sample_data
|
|
47
|
+
|
|
48
|
+
X=df.drop("y_class",axis=1)
|
|
49
|
+
y=df["y_class"]
|
|
50
|
+
|
|
51
|
+
causal_effects=log_counter.individual_causal_effects(X=X)
|
|
52
|
+
causal_resids=log_counter.individual_causal_effects_resid(X=X,y_true=y)
|
|
53
|
+
causal_probs=log_counter.individual_causal_effects_probs(X=X)
|
|
54
|
+
|
|
55
|
+
assert type(causal_effects)==np.ndarray
|
|
56
|
+
assert type(causal_resids)==np.ndarray
|
|
57
|
+
assert type(causal_probs)==np.ndarray
|
|
58
|
+
|
|
59
|
+
def test_causal_effect(log_causal_counter,sample_data):
|
|
60
|
+
log_counter=log_causal_counter
|
|
61
|
+
df=sample_data
|
|
62
|
+
|
|
63
|
+
X=df.drop("y_class",axis=1)
|
|
64
|
+
y=df["y_class"]
|
|
65
|
+
|
|
66
|
+
causal_effect_preds=log_counter.average_causal_effect(X=X)
|
|
67
|
+
causal_effect_resid=log_counter.average_causal_effect_resid(X=X,y_true=y)
|
|
68
|
+
causal_effect_probs=log_counter.average_causal_effect_probs(X=X)
|
|
69
|
+
|
|
70
|
+
assert type(causal_effect_preds)==float
|
|
71
|
+
assert type(causal_effect_resid)==float
|
|
72
|
+
assert type(causal_effect_probs)==float
|
|
73
|
+
|
|
74
|
+
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.linear_model import LinearRegression
|
|
5
|
+
from mini_causal.causal_counter import CausalCounterfactualRegression
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def sample_data():
|
|
10
|
+
df=pd.DataFrame({
|
|
11
|
+
"X1":[11,19,20,23,24,25,11,19,20],
|
|
12
|
+
"X2":[23,15,17,8,12,15,17,16,17],
|
|
13
|
+
"location":["North","North","South","South","South","North","South","South","North"],
|
|
14
|
+
"y_reg":np.array([19,11,17,30,31,32,77,80,19])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
return df
|
|
19
|
+
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def linear_model():
|
|
22
|
+
"""
|
|
23
|
+
Returns:
|
|
24
|
+
Linear Regression class
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
return LinearRegression()
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def linear_causal_counter(sample_data,log_model):
|
|
31
|
+
treatment=sample_data
|
|
32
|
+
control=sample_data
|
|
33
|
+
model=log_model
|
|
34
|
+
|
|
35
|
+
linear_counter=CausalCounterfactualRegression(
|
|
36
|
+
model=model,
|
|
37
|
+
treatment=treatment,
|
|
38
|
+
control=control,
|
|
39
|
+
feature="X1",
|
|
40
|
+
label="y_reg")
|
|
41
|
+
|
|
42
|
+
return linear_counter
|
|
43
|
+
|
|
44
|
+
def test_hypotheses_keys(linear_causal_counter):
|
|
45
|
+
linear_counter=linear_causal_counter
|
|
46
|
+
|
|
47
|
+
assert "Ho" in linear_counter.hypotheses()
|
|
48
|
+
assert "Ha" in linear_counter.hypotheses()
|
|
49
|
+
|
|
50
|
+
def test_control_model(linear_causal_counter,log_model,sample_data):
|
|
51
|
+
linear_counter=linear_causal_counter
|
|
52
|
+
control=sample_data
|
|
53
|
+
model=log_model
|
|
54
|
+
|
|
55
|
+
X_control=control.drop(["X1","location","y_class"],axis=1)
|
|
56
|
+
y_control=control["y_class"]
|
|
57
|
+
|
|
58
|
+
model.fit(X_control,y_control)
|
|
59
|
+
|
|
60
|
+
assert model == linear_counter.control_model()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_treatment_model(linear_causal_counter,linear_model,sample_data):
|
|
64
|
+
linear_counter=linear_causal_counter
|
|
65
|
+
treatment=sample_data
|
|
66
|
+
model=linear_model
|
|
67
|
+
|
|
68
|
+
X=treatment.drop(["location","y_reg"],axis=1)
|
|
69
|
+
y=treatment["y_reg"]
|
|
70
|
+
|
|
71
|
+
model.fit(X,y)
|
|
72
|
+
|
|
73
|
+
assert model == linear_counter.treatment_model()
|
|
74
|
+
|
|
75
|
+
def test_average_causality(linear_causal_counter,sample_data):
|
|
76
|
+
linear_counter=linear_causal_counter
|
|
77
|
+
df=sample_data
|
|
78
|
+
|
|
79
|
+
X=df.drop(["location","y_reg"],axis=1)
|
|
80
|
+
|
|
81
|
+
assert type(linear_counter.average_causal_effect(X=X))==float
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_inferential_stats(linear_causal_counter):
|
|
85
|
+
linear_counter=linear_causal_counter
|
|
86
|
+
|
|
87
|
+
correlation=linear_counter.correlation()
|
|
88
|
+
pvalue=linear_counter.p_value
|
|
89
|
+
|
|
90
|
+
t_stats=linear_counter.t_statistic
|
|
91
|
+
|
|
92
|
+
assert type(correlation)==float
|
|
93
|
+
assert type(pvalue)==float
|
|
94
|
+
assert type(t_stats)==float
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_correlation_ci(linear_causal_counter):
|
|
98
|
+
linear_counter=linear_causal_counter
|
|
99
|
+
|
|
100
|
+
assert "upper_bound" in linear_counter.correlation_confidence_interval()
|
|
101
|
+
assert "lower_bound" in linear_counter.correlation_confidence_interval()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_strat_exp(linear_causal_counter,sample_data):
|
|
105
|
+
linear_counter=linear_causal_counter
|
|
106
|
+
X=sample_data
|
|
107
|
+
|
|
108
|
+
strat_df=linear_counter.causal_effect_stratified(
|
|
109
|
+
X=X,
|
|
110
|
+
strata_feature="location",
|
|
111
|
+
type="preds"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
columns=strat_df.columns
|
|
115
|
+
|
|
116
|
+
assert "mean" in columns
|
|
117
|
+
assert "size" in columns
|
|
118
|
+
assert "weight_rss" in columns
|
|
119
|
+
|
|
120
|
+
def test_individual_causal_effects(linear_causal_counter,sample_data):
|
|
121
|
+
linear_counter=linear_causal_counter
|
|
122
|
+
df=sample_data
|
|
123
|
+
|
|
124
|
+
X=df.drop(["y_reg","location"],axis=1)
|
|
125
|
+
y=df["y_reg"]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
causal_effects=linear_counter.individual_causal_effects(X=X)
|
|
129
|
+
causal_resids=linear_counter.individual_causal_effects_resid(X=X,y_true=y)
|
|
130
|
+
|
|
131
|
+
assert type(causal_effects)==np.ndarray
|
|
132
|
+
assert type(causal_resids)==np.ndarray
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import numpy as np
|
|
4
|
+
from sklearn.linear_model import LogisticRegression
|
|
5
|
+
from sklearn.tree import DecisionTreeClassifier
|
|
6
|
+
from mini_causal.causality import CausalModelsClassifier
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def sample_data():
|
|
10
|
+
|
|
11
|
+
X=np.array([[1,2,3,4,5,6,7,8,9,10]]).reshape(-1,1)
|
|
12
|
+
y=np.array([1,1,1,0,0,0,1,1,0,0,1,0])
|
|
13
|
+
|
|
14
|
+
return X,y
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def log_model(sample_data):
|
|
18
|
+
X,y=sample_data
|
|
19
|
+
|
|
20
|
+
model=LogisticRegression(solver="liblinear")
|
|
21
|
+
|
|
22
|
+
return model.fit(X,y)
|
|
23
|
+
|
|
24
|
+
@pytest.fixture
|
|
25
|
+
def dt_model(sample_data):
|
|
26
|
+
X,y=sample_data
|
|
27
|
+
|
|
28
|
+
model=DecisionTreeClassifier()
|
|
29
|
+
|
|
30
|
+
return model.fit(X,y)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@pytest.fixture
|
|
34
|
+
def causal_classifier(log_model,dt_model):
|
|
35
|
+
|
|
36
|
+
first_model=log_model
|
|
37
|
+
sec_model=dt_model
|
|
38
|
+
|
|
39
|
+
return CausalModelsClassifier(
|
|
40
|
+
first_model=first_model,
|
|
41
|
+
second_model=sec_model
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_individual_causal_effect(causal_classifier):
|
|
46
|
+
causal_class=causal_classifier
|
|
47
|
+
|
|
48
|
+
causal_effects_arr=causal_class.individual_causal_effects()
|
|
49
|
+
causal_effects_resid=causal_class.individual_causal_effects_resid()
|
|
50
|
+
causal_effects_probs=causal_class.individual_causal_effects_probs()
|
|
51
|
+
|
|
52
|
+
assert type(causal_effects_arr)==np.array
|
|
53
|
+
assert type(causal_effects_resid)==np.array
|
|
54
|
+
assert type(causal_effects_probs)==np.array
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_causal_effects(causal_classifier):
|
|
58
|
+
causal_class=causal_classifier
|
|
59
|
+
|
|
60
|
+
causal_effect_preds=causal_class._average_causal_effect()
|
|
61
|
+
causal_effect_resid=causal_class.average_causal_effect_resid()
|
|
62
|
+
causal_effect_probs=causal_class.average_causal_effect_probs()
|
|
63
|
+
|
|
64
|
+
assert type(causal_effect_preds)==float
|
|
65
|
+
assert type(causal_effect_resid)==float
|
|
66
|
+
assert type(causal_effect_probs)==float
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
from sklearn.linear_model import LinearRegression
|
|
4
|
+
from sklearn.tree import DecisionTreeRegressor
|
|
5
|
+
from mini_causal.causality import CausalModelsRegression
|
|
6
|
+
|
|
7
|
+
@pytest.fixture
|
|
8
|
+
def sample_data():
|
|
9
|
+
|
|
10
|
+
X=np.array([[1,2,3,4,5,6,7,8,9,10]]).reshape(-1,1)
|
|
11
|
+
y=np.array([13,16,19,11,55,16,18,30,19,10])
|
|
12
|
+
|
|
13
|
+
return X,y
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def linear_model(sample_data):
|
|
17
|
+
X,y=sample_data
|
|
18
|
+
|
|
19
|
+
model=LinearRegression()
|
|
20
|
+
|
|
21
|
+
return model.fit(X,y)
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def dt_model(sample_data):
|
|
25
|
+
X,y=sample_data
|
|
26
|
+
|
|
27
|
+
model=DecisionTreeRegressor()
|
|
28
|
+
|
|
29
|
+
return model.fit(X,y)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.fixture
|
|
33
|
+
def causal_regressor(linear_model,dt_model):
|
|
34
|
+
|
|
35
|
+
first_model=linear_model
|
|
36
|
+
sec_model=dt_model
|
|
37
|
+
|
|
38
|
+
return CausalModelsRegression(
|
|
39
|
+
first_model=first_model,
|
|
40
|
+
second_model=sec_model
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_individual_causal_effect(causal_regressor):
|
|
45
|
+
causal_reg=causal_regressor
|
|
46
|
+
|
|
47
|
+
causal_effects_arr=causal_reg.individual_causal_effects()
|
|
48
|
+
causal_effects_resid=causal_reg.individual_causal_effects_resid()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
assert type(causal_effects_arr)==np.array
|
|
52
|
+
assert type(causal_effects_resid)==np.array
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_causal_effects(causal_regressor):
|
|
56
|
+
causal_reg=causal_regressor
|
|
57
|
+
|
|
58
|
+
causal_effect_preds=causal_reg._average_causal_effect()
|
|
59
|
+
causal_effect_resid=causal_reg.average_causal_effect_resid()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
assert type(causal_effect_preds)==float
|
|
63
|
+
assert type(causal_effect_resid)==float
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.linear_model import LogisticRegression,LinearRegression
|
|
5
|
+
from mini_causal.partial_counter import PartialCounterfactual
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def sample_data():
|
|
10
|
+
X=pd.DataFrame({"X1":[11,19,20,23,24,25],
|
|
11
|
+
"X2":[23,15,17,8,12,15]})
|
|
12
|
+
y_class=np.array([1,1,0,0,1,1])
|
|
13
|
+
y_reg=np.array([19,37,65,67,45])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
return X,y_class,y_reg
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture
|
|
20
|
+
def log_model(sample_data):
|
|
21
|
+
"""
|
|
22
|
+
Returns:
|
|
23
|
+
LogisticRegression fitted on sample set
|
|
24
|
+
"""
|
|
25
|
+
X,y=sample_data
|
|
26
|
+
log_model=LogisticRegression(solver="liblinear")
|
|
27
|
+
return log_model.fit(X,y)
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def linear_model(sample_data):
|
|
31
|
+
"""
|
|
32
|
+
Returns:
|
|
33
|
+
LinearRegression fitted on sample set
|
|
34
|
+
"""
|
|
35
|
+
X,_,y=sample_data
|
|
36
|
+
lr=LinearRegression()
|
|
37
|
+
|
|
38
|
+
return lr.fit(X,y)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_initialization_reg(linear_model,sample_data):
|
|
42
|
+
"""
|
|
43
|
+
"""
|
|
44
|
+
X,_,y_reg = sample_data
|
|
45
|
+
|
|
46
|
+
causal_feat_reg= PartialCounterfactual(linear_model, X, y_reg)
|
|
47
|
+
|
|
48
|
+
assert causal_feat_reg.model== linear_model
|
|
49
|
+
assert len(causal_feat_reg.y) == len(y_reg)
|
|
50
|
+
|
|
51
|
+
def test_initialization_class(log_model,sample_data):
|
|
52
|
+
"""
|
|
53
|
+
"""
|
|
54
|
+
X, y_class,_ = sample_data
|
|
55
|
+
|
|
56
|
+
causal_feat_classifier= PartialCounterfactual(log_model, X, y_class)
|
|
57
|
+
|
|
58
|
+
assert causal_feat_classifier.model ==log_model
|
|
59
|
+
assert len(causal_feat_classifier.y) == len(y_class)
|
|
60
|
+
|
|
61
|
+
def test_causal_effects(linear_model,log_model):
|
|
62
|
+
"""
|
|
63
|
+
Testing If individual causal effects are returned as numpy array
|
|
64
|
+
|
|
65
|
+
Parameters:
|
|
66
|
+
linear_model : LinearRegression
|
|
67
|
+
log_model : LogisticRegression
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
X, y_class,y_reg= sample_data
|
|
71
|
+
|
|
72
|
+
causal_feat_reg = PartialCounterfactual(linear_model,X, y_reg)
|
|
73
|
+
causal_feat_classifier = PartialCounterfactual(log_model,X, y_class)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
individual_causals_reg=causal_feat_reg._individual_causal_effects(feature="X1")
|
|
77
|
+
individual_causals_classifier=causal_feat_classifier._individual_causal_effects(feature="X2")
|
|
78
|
+
|
|
79
|
+
assert isinstance(individual_causals_reg, np.ndarray)
|
|
80
|
+
assert isinstance(individual_causals_classifier,np.ndarray)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_average_causal_effects(linear_model,log_model):
|
|
84
|
+
"""
|
|
85
|
+
Testing If average causal effects are returned as float values rather
|
|
86
|
+
|
|
87
|
+
Parameters:
|
|
88
|
+
linear_model : LinearRegression
|
|
89
|
+
log_model : LogisticRegression
|
|
90
|
+
|
|
91
|
+
"""
|
|
92
|
+
X, y_class,y_reg= sample_data
|
|
93
|
+
|
|
94
|
+
causal_feat_reg = PartialCounterfactual(linear_model,X, y_reg)
|
|
95
|
+
causal_feat_classifier = PartialCounterfactual(log_model,X, y_class)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
ace_reg=causal_feat_reg._average_causal_effects(feature="X1")
|
|
99
|
+
ace_classifier=causal_feat_classifier.average_effects(feature="X2")
|
|
100
|
+
|
|
101
|
+
assert isinstance(ace_reg,float)
|
|
102
|
+
assert isinstance(ace_classifier,float)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.linear_model import LogisticRegression
|
|
5
|
+
from mini_causal.partial_counter import PartialCounterfactualClassifier
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def sample_data():
|
|
11
|
+
X=pd.DataFrame({"X1":[11,19,20,23,24,25],
|
|
12
|
+
"X2":[23,15,17,8,12,15]})
|
|
13
|
+
y=[1,1,0,0,1,1]
|
|
14
|
+
|
|
15
|
+
return X,y
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def model(sample_data):
|
|
20
|
+
X,y=sample_data
|
|
21
|
+
log_model= LogisticRegression(solver="liblinear")
|
|
22
|
+
|
|
23
|
+
return log_model.fit(X,y)
|
|
24
|
+
|
|
25
|
+
def test_initialization(model, sample_data):
|
|
26
|
+
X, y = sample_data
|
|
27
|
+
|
|
28
|
+
partial_counter= PartialCounterfactualClassifier(model, X, y)
|
|
29
|
+
|
|
30
|
+
assert partial_counter.model == model
|
|
31
|
+
assert len(partial_counter.y) == len(y)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_causal_effects():
|
|
35
|
+
X, y = sample_data
|
|
36
|
+
|
|
37
|
+
partial_counter= PartialCounterfactualClassifier(model, X, y)
|
|
38
|
+
|
|
39
|
+
individual_causals=partial_counter._individual_causal_effects(feature="X1")
|
|
40
|
+
individual_causals_probs=partial_counter._individual_causal_effects_probs(feature="X2")
|
|
41
|
+
|
|
42
|
+
assert isinstance(individual_causals, np.ndarray)
|
|
43
|
+
assert isinstance(individual_causals_probs,np.ndarray)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_average_causal_effects():
|
|
47
|
+
X, y = sample_data
|
|
48
|
+
|
|
49
|
+
partial_counter= PartialCounterfactualClassifier(model, X, y)
|
|
50
|
+
ate=partial_counter.average_treatment_effect(feature="X1")
|
|
51
|
+
ate_probs=partial_counter.average_treatment_effect_probs(feature="X2")
|
|
52
|
+
|
|
53
|
+
assert isinstance(ate,float)
|
|
54
|
+
assert isinstance(ate_probs,float)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.linear_model import LinearRegression
|
|
5
|
+
from mini_causal.partial_counter import PartialCounterfactualRegression
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def sample_data():
|
|
10
|
+
X=pd.DataFrame({"X1":[11,19,20,23,24,25],
|
|
11
|
+
"X2":[23,15,17,8,12,15]})
|
|
12
|
+
y=[12,19,13,4,3,11]
|
|
13
|
+
|
|
14
|
+
return X,y
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def model(sample_data):
|
|
18
|
+
X,y=sample_data
|
|
19
|
+
lr=LinearRegression()
|
|
20
|
+
|
|
21
|
+
return lr.fit(X,y)
|
|
22
|
+
|
|
23
|
+
def test_initialization(model, sample_data):
|
|
24
|
+
X, y = sample_data
|
|
25
|
+
|
|
26
|
+
partial_reg= PartialCounterfactualRegression(model, X, y)
|
|
27
|
+
|
|
28
|
+
assert partial_reg.model == model
|
|
29
|
+
assert len(partial_reg.X)== len(partial_reg.X)
|
|
30
|
+
assert len(partial_reg.y) == len(y)
|
|
31
|
+
|
|
32
|
+
def test_individual_causal_effect(model,sample_data):
|
|
33
|
+
X, y = sample_data
|
|
34
|
+
|
|
35
|
+
partial_reg= PartialCounterfactualRegression(model, X, y)
|
|
36
|
+
individual_effects=partial_reg.individual_causal_effects("X1")
|
|
37
|
+
|
|
38
|
+
assert isinstance(individual_effects,np.ndarray)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_average_causal_effect(model,sample_data):
|
|
42
|
+
X, y = sample_data
|
|
43
|
+
|
|
44
|
+
partial_reg= PartialCounterfactualRegression(model, X, y)
|
|
45
|
+
average_effect=partial_reg.average_causal_effect("X1")
|
|
46
|
+
|
|
47
|
+
assert isinstance(average_effect,float)
|