Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion doubleml/rdd/rdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
from collections.abc import Callable

from scipy.stats import norm
from rdrobust import rdrobust, rdbwselect
try:
from rdrobust import rdrobust, rdbwselect
_rdrobust_available = True
except ImportError:
_rdrobust_available = False

from sklearn.base import clone
from sklearn.utils.multiclass import type_of_target
Expand Down Expand Up @@ -105,6 +109,9 @@ def __init__(self,
fs_kernel="triangular",
**kwargs):

if not _rdrobust_available:
raise ImportError("rdrobust is not installed. Please install it using 'pip install DoubleML[rdd]'")

self._check_data(obj_dml_data, cutoff)
self._dml_data = obj_dml_data

Expand Down
9 changes: 8 additions & 1 deletion doubleml/rdd/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
from doubleml import DoubleMLData
from doubleml.rdd import RDFlex

from rdrobust import rdrobust
try:
from rdrobust import rdrobust
_rdrobust_available = True
except ImportError:
_rdrobust_available = False

from sklearn.dummy import DummyRegressor, DummyClassifier

Expand All @@ -25,6 +29,9 @@ def predict_dummy():
- make predictions using rdrobust as a reference
"""
def _predict_dummy(data: DoubleMLData, cutoff, alpha, n_rep, p, fs_specification, ml_g=ml_g_dummy):
if not _rdrobust_available:
raise ImportError("rdrobust is not installed. Please install it using 'pip install DoubleML[rdd]'")

dml_rdflex = RDFlex(
data,
ml_g=ml_g,
Expand Down
2 changes: 1 addition & 1 deletion doubleml/rdd/tests/test_rdd_classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
dml_rdflex = RDFlex(dml_data, ml_g=LogisticRegression(), ml_m=LogisticRegression(), fuzzy=True)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_classifier():
dml_rdflex.fit()
12 changes: 6 additions & 6 deletions doubleml/rdd/tests/test_rdd_classifier_fuzzy.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,37 +62,37 @@ def predict_nonplacebo(predict_dummy, data, cutoff, alpha, p, n_rep, fs_specific
)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_coef(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_coef(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_se(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_se(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_ci(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_ci(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)
12 changes: 6 additions & 6 deletions doubleml/rdd/tests/test_rdd_classifier_fuzzy_left.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,37 +62,37 @@ def predict_nonplacebo(predict_dummy, data, cutoff, alpha, p, n_rep, fs_specific
)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_coef(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_coef(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_se(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_se(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_ci(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_ci(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)
12 changes: 6 additions & 6 deletions doubleml/rdd/tests/test_rdd_classifier_fuzzy_right.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,37 +62,37 @@ def predict_nonplacebo(predict_dummy, data, cutoff, alpha, p, n_rep, fs_specific
)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_coef(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_coef(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_se(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_se(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_ci(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_ci(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)
12 changes: 6 additions & 6 deletions doubleml/rdd/tests/test_rdd_classifier_sharp.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,37 +62,37 @@ def predict_nonplacebo(predict_dummy, data, cutoff, alpha, p, n_rep, fs_specific
)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_coef(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_coef(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_se(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_se(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_ci(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_ci(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)
2 changes: 1 addition & 1 deletion doubleml/rdd/tests/test_rdd_default_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ def _assert_resampling_default_settings(dml_obj):
assert dml_obj.fuzzy is False


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_defaults():
_assert_resampling_default_settings(dml_rdflex)
20 changes: 10 additions & 10 deletions doubleml/rdd/tests/test_rdd_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def predict_proba(self, X):
)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_data():
# DoubleMLData
msg = r"The data must be of DoubleMLData type. \[\] of type <class 'list'> was passed."
Expand Down Expand Up @@ -101,7 +101,7 @@ def test_rdd_exception_data():
_ = RDFlex(tmp_dml_data, ml_g)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_cutoff():
msg = "Cutoff value has to be a float or int. Object of type <class 'list'> passed."
with pytest.raises(TypeError, match=msg):
Expand All @@ -112,14 +112,14 @@ def test_rdd_exception_cutoff():
_ = RDFlex(dml_data, ml_g, cutoff=200)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_warning_fuzzy():
msg = 'A sharp RD design is being estimated, but the data indicate that the design is fuzzy.'
with pytest.warns(UserWarning, match=msg):
_ = RDFlex(dml_data, ml_g, cutoff=0.1)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_warning_treatment_assignment():
msg = ("Treatment probability within bandwidth left from cutoff higher than right from cutoff.\n"
"Treatment assignment might be based on the wrong side of the cutoff.")
Expand All @@ -129,7 +129,7 @@ def test_rdd_warning_treatment_assignment():
_ = RDFlex(tmp_dml_data, ml_g, ml_m, fuzzy=True)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_learner():

# ml_g
Expand Down Expand Up @@ -163,7 +163,7 @@ def test_rdd_exception_learner():
_ = RDFlex(tmp_dml_data, ml_g, ml_m, fuzzy=False)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_resampling():
# n_folds
msg = r"The number of folds must be of int type. \[1\] of type <class 'list'> was passed."
Expand All @@ -182,7 +182,7 @@ def test_rdd_exception_resampling():
_ = RDFlex(dml_data, ml_g, ml_m, n_rep=0)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_kernel():
msg = "fs_kernel must be either a string or a callable. 2 of type <class 'int'> was passed."
with pytest.raises(TypeError, match=msg):
Expand All @@ -192,14 +192,14 @@ def test_rdd_exception_kernel():
_ = RDFlex(dml_data, ml_g, ml_m, fs_kernel='rbf')


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_h_fs():
msg = "Initial bandwidth 'h_fs' has to be a float. Object of type <class 'int'> passed."
with pytest.raises(TypeError, match=msg):
_ = RDFlex(dml_data, ml_g, ml_m, h_fs=1)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_fs_specification():
msg = "fs_specification must be a string. 1 of type <class 'int'> was passed."
with pytest.raises(TypeError, match=msg):
Expand All @@ -211,7 +211,7 @@ def test_rdd_exception_fs_specification():
_ = RDFlex(dml_data, ml_g, ml_m, fs_specification='local_constant')


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_exception_fit():
rdd_model = RDFlex(dml_data, ml_g, ml_m)
msg = (r"The number of iterations for the iterative bandwidth fitting must be of int type. \[0\] of type <class 'list'> "
Expand Down
12 changes: 6 additions & 6 deletions doubleml/rdd/tests/test_rdd_fuzzy.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,37 +59,37 @@ def predict_nonplacebo(predict_dummy, data, cutoff, alpha, p, n_rep, fs_specific
)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_coef(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_coef(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['coef'], reference['coef'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_se(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_se(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['se'], reference['se'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_placebo_ci(predict_placebo):
reference, actual = predict_placebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)


@pytest.mark.ci
@pytest.mark.ci_rdd
def test_rdd_nonplacebo_ci(predict_nonplacebo):
reference, actual = predict_nonplacebo
assert np.allclose(actual['ci'], reference['ci'], rtol=1e-9, atol=1e-4)
Loading