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.
@@ -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
+ ![logo](images/cropped_logo.jpeg)
@@ -0,0 +1,3 @@
1
+ # MiniCausal
2
+
3
+ ![logo](images/cropped_logo.jpeg)
@@ -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
+ ![logo](images/cropped_logo.jpeg)
@@ -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,3 @@
1
+ pandas>=3.0.2
2
+ numpy>=2.4.4
3
+ scipy>=1.17.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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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)