97 lines
3.6 KiB
Python
97 lines
3.6 KiB
Python
|
|
import pytest
|
|
import numpy as np
|
|
from numpy.testing import assert_allclose, assert_equal
|
|
from scipy.stats.contingency import relative_risk
|
|
|
|
|
|
# Test just the calculation of the relative risk, including edge
|
|
# cases that result in a relative risk of 0, inf or nan.
|
|
@pytest.mark.parametrize(
|
|
'exposed_cases, exposed_total, control_cases, control_total, expected_rr',
|
|
[(1, 4, 3, 8, 0.25 / 0.375),
|
|
(0, 10, 5, 20, 0),
|
|
(0, 10, 0, 20, np.nan),
|
|
(5, 15, 0, 20, np.inf)]
|
|
)
|
|
def test_relative_risk(exposed_cases, exposed_total,
|
|
control_cases, control_total, expected_rr):
|
|
result = relative_risk(exposed_cases, exposed_total,
|
|
control_cases, control_total)
|
|
assert_allclose(result.relative_risk, expected_rr, rtol=1e-13)
|
|
|
|
|
|
def test_relative_risk_confidence_interval():
|
|
result = relative_risk(exposed_cases=16, exposed_total=128,
|
|
control_cases=24, control_total=256)
|
|
rr = result.relative_risk
|
|
ci = result.confidence_interval(confidence_level=0.95)
|
|
# The corresponding calculation in R using the epitools package.
|
|
#
|
|
# > library(epitools)
|
|
# > c <- matrix(c(232, 112, 24, 16), nrow=2)
|
|
# > result <- riskratio(c)
|
|
# > result$measure
|
|
# risk ratio with 95% C.I.
|
|
# Predictor estimate lower upper
|
|
# Exposed1 1.000000 NA NA
|
|
# Exposed2 1.333333 0.7347317 2.419628
|
|
#
|
|
# The last line is the result that we want.
|
|
assert_allclose(rr, 4/3)
|
|
assert_allclose((ci.low, ci.high), (0.7347317, 2.419628), rtol=5e-7)
|
|
|
|
|
|
def test_relative_risk_ci_conflevel0():
|
|
result = relative_risk(exposed_cases=4, exposed_total=12,
|
|
control_cases=5, control_total=30)
|
|
rr = result.relative_risk
|
|
assert_allclose(rr, 2.0, rtol=1e-14)
|
|
ci = result.confidence_interval(0)
|
|
assert_allclose((ci.low, ci.high), (2.0, 2.0), rtol=1e-12)
|
|
|
|
|
|
def test_relative_risk_ci_conflevel1():
|
|
result = relative_risk(exposed_cases=4, exposed_total=12,
|
|
control_cases=5, control_total=30)
|
|
ci = result.confidence_interval(1)
|
|
assert_equal((ci.low, ci.high), (0, np.inf))
|
|
|
|
|
|
def test_relative_risk_ci_edge_cases_00():
|
|
result = relative_risk(exposed_cases=0, exposed_total=12,
|
|
control_cases=0, control_total=30)
|
|
assert_equal(result.relative_risk, np.nan)
|
|
ci = result.confidence_interval()
|
|
assert_equal((ci.low, ci.high), (np.nan, np.nan))
|
|
|
|
|
|
def test_relative_risk_ci_edge_cases_01():
|
|
result = relative_risk(exposed_cases=0, exposed_total=12,
|
|
control_cases=1, control_total=30)
|
|
assert_equal(result.relative_risk, 0)
|
|
ci = result.confidence_interval()
|
|
assert_equal((ci.low, ci.high), (0.0, np.nan))
|
|
|
|
|
|
def test_relative_risk_ci_edge_cases_10():
|
|
result = relative_risk(exposed_cases=1, exposed_total=12,
|
|
control_cases=0, control_total=30)
|
|
assert_equal(result.relative_risk, np.inf)
|
|
ci = result.confidence_interval()
|
|
assert_equal((ci.low, ci.high), (np.nan, np.inf))
|
|
|
|
|
|
@pytest.mark.parametrize('ec, et, cc, ct', [(0, 0, 10, 20),
|
|
(-1, 10, 1, 5),
|
|
(1, 10, 0, 0),
|
|
(1, 10, -1, 4)])
|
|
def test_relative_risk_bad_value(ec, et, cc, ct):
|
|
with pytest.raises(ValueError, match="must be an integer not less than"):
|
|
relative_risk(ec, et, cc, ct)
|
|
|
|
|
|
def test_relative_risk_bad_type():
|
|
with pytest.raises(TypeError, match="must be an integer"):
|
|
relative_risk(1, 10, 2.0, 40)
|