406 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import copy
 | |
| 
 | |
| import numpy as np
 | |
| import pytest
 | |
| from numpy.testing import assert_allclose
 | |
| 
 | |
| from scipy import stats
 | |
| from scipy.stats._multicomp import _pvalue_dunnett, DunnettResult
 | |
| 
 | |
| 
 | |
| class TestDunnett:
 | |
|     # For the following tests, p-values were computed using Matlab, e.g.
 | |
|     #     sample = [18.  15.  18.  16.  17.  15.  14.  14.  14.  15.  15....
 | |
|     #               14.  15.  14.  22.  18.  21.  21.  10.  10.  11.  9....
 | |
|     #               25.  26.  17.5 16.  15.5 14.5 22.  22.  24.  22.5 29....
 | |
|     #               24.5 20.  18.  18.5 17.5 26.5 13.  16.5 13.  13.  13....
 | |
|     #               28.  27.  34.  31.  29.  27.  24.  23.  38.  36.  25....
 | |
|     #               38. 26.  22.  36.  27.  27.  32.  28.  31....
 | |
|     #               24.  27.  33.  32.  28.  19. 37.  31.  36.  36....
 | |
|     #               34.  38.  32.  38.  32....
 | |
|     #               26.  24.  26.  25.  29. 29.5 16.5 36.  44....
 | |
|     #               25.  27.  19....
 | |
|     #               25.  20....
 | |
|     #               28.];
 | |
|     #     j = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
 | |
|     #          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
 | |
|     #          0 0 0 0...
 | |
|     #          1 1 1 1 1 1 1 1 1 1 1 1 1 1 1...
 | |
|     #          2 2 2 2 2 2 2 2 2...
 | |
|     #          3 3 3...
 | |
|     #          4 4...
 | |
|     #          5];
 | |
|     #     [~, ~, stats] = anova1(sample, j, "off");
 | |
|     #     [results, ~, ~, gnames] = multcompare(stats, ...
 | |
|     #     "CriticalValueType", "dunnett", ...
 | |
|     #     "Approximate", false);
 | |
|     #     tbl = array2table(results, "VariableNames", ...
 | |
|     #     ["Group", "Control Group", "Lower Limit", ...
 | |
|     #     "Difference", "Upper Limit", "P-value"]);
 | |
|     #     tbl.("Group") = gnames(tbl.("Group"));
 | |
|     #     tbl.("Control Group") = gnames(tbl.("Control Group"))
 | |
| 
 | |
|     # Matlab doesn't report the statistic, so the statistics were
 | |
|     # computed using R multcomp `glht`, e.g.:
 | |
|     #     library(multcomp)
 | |
|     #     options(digits=16)
 | |
|     #     control < - c(18.0, 15.0, 18.0, 16.0, 17.0, 15.0, 14.0, 14.0, 14.0,
 | |
|     #                   15.0, 15.0, 14.0, 15.0, 14.0, 22.0, 18.0, 21.0, 21.0,
 | |
|     #                   10.0, 10.0, 11.0, 9.0, 25.0, 26.0, 17.5, 16.0, 15.5,
 | |
|     #                   14.5, 22.0, 22.0, 24.0, 22.5, 29.0, 24.5, 20.0, 18.0,
 | |
|     #                   18.5, 17.5, 26.5, 13.0, 16.5, 13.0, 13.0, 13.0, 28.0,
 | |
|     #                   27.0, 34.0, 31.0, 29.0, 27.0, 24.0, 23.0, 38.0, 36.0,
 | |
|     #                   25.0, 38.0, 26.0, 22.0, 36.0, 27.0, 27.0, 32.0, 28.0,
 | |
|     #                   31.0)
 | |
|     #     t < - c(24.0, 27.0, 33.0, 32.0, 28.0, 19.0, 37.0, 31.0, 36.0, 36.0,
 | |
|     #             34.0, 38.0, 32.0, 38.0, 32.0)
 | |
|     #     w < - c(26.0, 24.0, 26.0, 25.0, 29.0, 29.5, 16.5, 36.0, 44.0)
 | |
|     #     x < - c(25.0, 27.0, 19.0)
 | |
|     #     y < - c(25.0, 20.0)
 | |
|     #     z < - c(28.0)
 | |
|     #
 | |
|     #     groups = factor(rep(c("control", "t", "w", "x", "y", "z"),
 | |
|     #                         times=c(length(control), length(t), length(w),
 | |
|     #                                 length(x), length(y), length(z))))
 | |
|     #     df < - data.frame(response=c(control, t, w, x, y, z),
 | |
|     #                       group=groups)
 | |
|     #     model < - aov(response
 | |
|     #     ~group, data = df)
 | |
|     #     test < - glht(model=model,
 | |
|     #                   linfct=mcp(group="Dunnett"),
 | |
|     #                   alternative="g")
 | |
|     #     summary(test)
 | |
|     #     confint(test)
 | |
|     # p-values agreed with those produced by Matlab to at least atol=1e-3
 | |
| 
 | |
|     # From Matlab's documentation on multcompare
 | |
|     samples_1 = [
 | |
|         [
 | |
|             24.0, 27.0, 33.0, 32.0, 28.0, 19.0, 37.0, 31.0, 36.0, 36.0,
 | |
|             34.0, 38.0, 32.0, 38.0, 32.0
 | |
|         ],
 | |
|         [26.0, 24.0, 26.0, 25.0, 29.0, 29.5, 16.5, 36.0, 44.0],
 | |
|         [25.0, 27.0, 19.0],
 | |
|         [25.0, 20.0],
 | |
|         [28.0]
 | |
|     ]
 | |
|     control_1 = [
 | |
|         18.0, 15.0, 18.0, 16.0, 17.0, 15.0, 14.0, 14.0, 14.0, 15.0, 15.0,
 | |
|         14.0, 15.0, 14.0, 22.0, 18.0, 21.0, 21.0, 10.0, 10.0, 11.0, 9.0,
 | |
|         25.0, 26.0, 17.5, 16.0, 15.5, 14.5, 22.0, 22.0, 24.0, 22.5, 29.0,
 | |
|         24.5, 20.0, 18.0, 18.5, 17.5, 26.5, 13.0, 16.5, 13.0, 13.0, 13.0,
 | |
|         28.0, 27.0, 34.0, 31.0, 29.0, 27.0, 24.0, 23.0, 38.0, 36.0, 25.0,
 | |
|         38.0, 26.0, 22.0, 36.0, 27.0, 27.0, 32.0, 28.0, 31.0
 | |
|     ]
 | |
|     pvalue_1 = [4.727e-06, 0.022346, 0.97912, 0.99953, 0.86579]  # Matlab
 | |
|     # Statistic, alternative p-values, and CIs computed with R multcomp `glht`
 | |
|     p_1_twosided = [1e-4, 0.02237, 0.97913, 0.99953, 0.86583]
 | |
|     p_1_greater = [1e-4, 0.011217, 0.768500, 0.896991, 0.577211]
 | |
|     p_1_less = [1, 1, 0.99660, 0.98398, .99953]
 | |
|     statistic_1 = [5.27356, 2.91270, 0.60831, 0.27002, 0.96637]
 | |
|     ci_1_twosided = [[5.3633917835622, 0.7296142201217, -8.3879817106607,
 | |
|                       -11.9090753452911, -11.7655021543469],
 | |
|                      [15.9709832164378, 13.8936496687672, 13.4556900439941,
 | |
|                       14.6434503452911, 25.4998771543469]]
 | |
|     ci_1_greater = [5.9036402398526, 1.4000632918725, -7.2754756323636,
 | |
|                     -10.5567456382391, -9.8675629499576]
 | |
|     ci_1_less = [15.4306165948619, 13.2230539537359, 12.3429406339544,
 | |
|                  13.2908248513211, 23.6015228251660]
 | |
|     pvalues_1 = dict(twosided=p_1_twosided, less=p_1_less, greater=p_1_greater)
 | |
|     cis_1 = dict(twosided=ci_1_twosided, less=ci_1_less, greater=ci_1_greater)
 | |
|     case_1 = dict(samples=samples_1, control=control_1, statistic=statistic_1,
 | |
|                   pvalues=pvalues_1, cis=cis_1)
 | |
| 
 | |
|     # From Dunnett1955 comparing with R's DescTools: DunnettTest
 | |
|     samples_2 = [[9.76, 8.80, 7.68, 9.36], [12.80, 9.68, 12.16, 9.20, 10.55]]
 | |
|     control_2 = [7.40, 8.50, 7.20, 8.24, 9.84, 8.32]
 | |
|     pvalue_2 = [0.6201, 0.0058]
 | |
|     # Statistic, alternative p-values, and CIs computed with R multcomp `glht`
 | |
|     p_2_twosided = [0.6201020, 0.0058254]
 | |
|     p_2_greater = [0.3249776, 0.0029139]
 | |
|     p_2_less = [0.91676, 0.99984]
 | |
|     statistic_2 = [0.85703, 3.69375]
 | |
|     ci_2_twosided = [[-1.2564116462124, 0.8396273539789],
 | |
|                      [2.5564116462124, 4.4163726460211]]
 | |
|     ci_2_greater = [-0.9588591188156, 1.1187563667543]
 | |
|     ci_2_less = [2.2588591188156, 4.1372436332457]
 | |
|     pvalues_2 = dict(twosided=p_2_twosided, less=p_2_less, greater=p_2_greater)
 | |
|     cis_2 = dict(twosided=ci_2_twosided, less=ci_2_less, greater=ci_2_greater)
 | |
|     case_2 = dict(samples=samples_2, control=control_2, statistic=statistic_2,
 | |
|                   pvalues=pvalues_2, cis=cis_2)
 | |
| 
 | |
|     samples_3 = [[55, 64, 64], [55, 49, 52], [50, 44, 41]]
 | |
|     control_3 = [55, 47, 48]
 | |
|     pvalue_3 = [0.0364, 0.8966, 0.4091]
 | |
|     # Statistic, alternative p-values, and CIs computed with R multcomp `glht`
 | |
|     p_3_twosided = [0.036407, 0.896539, 0.409295]
 | |
|     p_3_greater = [0.018277, 0.521109, 0.981892]
 | |
|     p_3_less = [0.99944, 0.90054, 0.20974]
 | |
|     statistic_3 = [3.09073, 0.56195, -1.40488]
 | |
|     ci_3_twosided = [[0.7529028025053, -8.2470971974947, -15.2470971974947],
 | |
|                      [21.2470971974947, 12.2470971974947, 5.2470971974947]]
 | |
|     ci_3_greater = [2.4023682323149, -6.5976317676851, -13.5976317676851]
 | |
|     ci_3_less = [19.5984402363662, 10.5984402363662, 3.5984402363662]
 | |
|     pvalues_3 = dict(twosided=p_3_twosided, less=p_3_less, greater=p_3_greater)
 | |
|     cis_3 = dict(twosided=ci_3_twosided, less=ci_3_less, greater=ci_3_greater)
 | |
|     case_3 = dict(samples=samples_3, control=control_3, statistic=statistic_3,
 | |
|                   pvalues=pvalues_3, cis=cis_3)
 | |
| 
 | |
|     # From Thomson and Short,
 | |
|     # Mucociliary function in health, chronic obstructive airway disease,
 | |
|     # and asbestosis, Journal of Applied Physiology, 1969. Table 1
 | |
|     # Comparing with R's DescTools: DunnettTest
 | |
|     samples_4 = [[3.8, 2.7, 4.0, 2.4], [2.8, 3.4, 3.7, 2.2, 2.0]]
 | |
|     control_4 = [2.9, 3.0, 2.5, 2.6, 3.2]
 | |
|     pvalue_4 = [0.5832, 0.9982]
 | |
|     # Statistic, alternative p-values, and CIs computed with R multcomp `glht`
 | |
|     p_4_twosided = [0.58317, 0.99819]
 | |
|     p_4_greater = [0.30225, 0.69115]
 | |
|     p_4_less = [0.91929, 0.65212]
 | |
|     statistic_4 = [0.90875, -0.05007]
 | |
|     ci_4_twosided = [[-0.6898153448579, -1.0333456251632],
 | |
|                      [1.4598153448579, 0.9933456251632]]
 | |
|     ci_4_greater = [-0.5186459268412, -0.8719655502147 ]
 | |
|     ci_4_less = [1.2886459268412, 0.8319655502147]
 | |
|     pvalues_4 = dict(twosided=p_4_twosided, less=p_4_less, greater=p_4_greater)
 | |
|     cis_4 = dict(twosided=ci_4_twosided, less=ci_4_less, greater=ci_4_greater)
 | |
|     case_4 = dict(samples=samples_4, control=control_4, statistic=statistic_4,
 | |
|                   pvalues=pvalues_4, cis=cis_4)
 | |
| 
 | |
|     @pytest.mark.parametrize(
 | |
|         'rho, n_groups, df, statistic, pvalue, alternative',
 | |
|         [
 | |
|             # From Dunnett1955
 | |
|             # Tables 1a and 1b pages 1117-1118
 | |
|             (0.5, 1, 10, 1.81, 0.05, "greater"),  # different than two-sided
 | |
|             (0.5, 3, 10, 2.34, 0.05, "greater"),
 | |
|             (0.5, 2, 30, 1.99, 0.05, "greater"),
 | |
|             (0.5, 5, 30, 2.33, 0.05, "greater"),
 | |
|             (0.5, 4, 12, 3.32, 0.01, "greater"),
 | |
|             (0.5, 7, 12, 3.56, 0.01, "greater"),
 | |
|             (0.5, 2, 60, 2.64, 0.01, "greater"),
 | |
|             (0.5, 4, 60, 2.87, 0.01, "greater"),
 | |
|             (0.5, 4, 60, [2.87, 2.21], [0.01, 0.05], "greater"),
 | |
|             # Tables 2a and 2b pages 1119-1120
 | |
|             (0.5, 1, 10, 2.23, 0.05, "two-sided"),  # two-sided
 | |
|             (0.5, 3, 10, 2.81, 0.05, "two-sided"),
 | |
|             (0.5, 2, 30, 2.32, 0.05, "two-sided"),
 | |
|             (0.5, 3, 20, 2.57, 0.05, "two-sided"),
 | |
|             (0.5, 4, 12, 3.76, 0.01, "two-sided"),
 | |
|             (0.5, 7, 12, 4.08, 0.01, "two-sided"),
 | |
|             (0.5, 2, 60, 2.90, 0.01, "two-sided"),
 | |
|             (0.5, 4, 60, 3.14, 0.01, "two-sided"),
 | |
|             (0.5, 4, 60, [3.14, 2.55], [0.01, 0.05], "two-sided"),
 | |
|         ],
 | |
|     )
 | |
|     def test_critical_values(
 | |
|         self, rho, n_groups, df, statistic, pvalue, alternative
 | |
|     ):
 | |
|         rng = np.random.default_rng(165250594791731684851746311027739134893)
 | |
|         rho = np.full((n_groups, n_groups), rho)
 | |
|         np.fill_diagonal(rho, 1)
 | |
| 
 | |
|         statistic = np.array(statistic)
 | |
|         res = _pvalue_dunnett(
 | |
|             rho=rho, df=df, statistic=statistic,
 | |
|             alternative=alternative,
 | |
|             rng=rng
 | |
|         )
 | |
|         assert_allclose(res, pvalue, atol=5e-3)
 | |
| 
 | |
|     @pytest.mark.parametrize(
 | |
|         'samples, control, pvalue, statistic',
 | |
|         [
 | |
|             (samples_1, control_1, pvalue_1, statistic_1),
 | |
|             (samples_2, control_2, pvalue_2, statistic_2),
 | |
|             (samples_3, control_3, pvalue_3, statistic_3),
 | |
|             (samples_4, control_4, pvalue_4, statistic_4),
 | |
|         ]
 | |
|     )
 | |
|     def test_basic(self, samples, control, pvalue, statistic):
 | |
|         rng = np.random.default_rng(11681140010308601919115036826969764808)
 | |
| 
 | |
|         res = stats.dunnett(*samples, control=control, rng=rng)
 | |
| 
 | |
|         assert isinstance(res, DunnettResult)
 | |
|         assert_allclose(res.statistic, statistic, rtol=5e-5)
 | |
|         assert_allclose(res.pvalue, pvalue, rtol=1e-2, atol=1e-4)
 | |
| 
 | |
|     @pytest.mark.parametrize(
 | |
|         'alternative',
 | |
|         ['two-sided', 'less', 'greater']
 | |
|     )
 | |
|     def test_ttest_ind(self, alternative):
 | |
|         # check that `dunnett` agrees with `ttest_ind`
 | |
|         # when there are only two groups
 | |
|         rng = np.random.default_rng(114184017807316971636137493526995620351)
 | |
| 
 | |
|         for _ in range(10):
 | |
|             sample = rng.integers(-100, 100, size=(10,))
 | |
|             control = rng.integers(-100, 100, size=(10,))
 | |
| 
 | |
|             # preserve use of old random_state during SPEC 7 transition
 | |
|             res = stats.dunnett(
 | |
|                 sample, control=control,
 | |
|                 alternative=alternative, random_state=rng
 | |
|             )
 | |
|             ref = stats.ttest_ind(
 | |
|                 sample, control,
 | |
|                 alternative=alternative
 | |
|             )
 | |
| 
 | |
|             assert_allclose(res.statistic, ref.statistic, rtol=1e-3, atol=1e-5)
 | |
|             assert_allclose(res.pvalue, ref.pvalue, rtol=1e-3, atol=1e-5)
 | |
| 
 | |
|     @pytest.mark.parametrize(
 | |
|         'alternative, pvalue',
 | |
|         [
 | |
|             ('less', [0, 1]),
 | |
|             ('greater', [1, 0]),
 | |
|             ('two-sided', [0, 0]),
 | |
|         ]
 | |
|     )
 | |
|     def test_alternatives(self, alternative, pvalue):
 | |
|         rng = np.random.default_rng(114184017807316971636137493526995620351)
 | |
| 
 | |
|         # width of 20 and min diff between samples/control is 60
 | |
|         # and maximal diff would be 100
 | |
|         sample_less = rng.integers(0, 20, size=(10,))
 | |
|         control = rng.integers(80, 100, size=(10,))
 | |
|         sample_greater = rng.integers(160, 180, size=(10,))
 | |
| 
 | |
|         res = stats.dunnett(
 | |
|             sample_less, sample_greater, control=control,
 | |
|             alternative=alternative, rng=rng
 | |
|         )
 | |
|         assert_allclose(res.pvalue, pvalue, atol=1e-7)
 | |
| 
 | |
|         ci = res.confidence_interval()
 | |
|         # two-sided is comparable for high/low
 | |
|         if alternative == 'less':
 | |
|             assert np.isneginf(ci.low).all()
 | |
|             assert -100 < ci.high[0] < -60
 | |
|             assert 60 < ci.high[1] < 100
 | |
|         elif alternative == 'greater':
 | |
|             assert -100 < ci.low[0] < -60
 | |
|             assert 60 < ci.low[1] < 100
 | |
|             assert np.isposinf(ci.high).all()
 | |
|         elif alternative == 'two-sided':
 | |
|             assert -100 < ci.low[0] < -60
 | |
|             assert 60 < ci.low[1] < 100
 | |
|             assert -100 < ci.high[0] < -60
 | |
|             assert 60 < ci.high[1] < 100
 | |
| 
 | |
|     @pytest.mark.parametrize("case", [case_1, case_2, case_3, case_4])
 | |
|     @pytest.mark.parametrize("alternative", ['less', 'greater', 'two-sided'])
 | |
|     def test_against_R_multicomp_glht(self, case, alternative):
 | |
|         rng = np.random.default_rng(189117774084579816190295271136455278291)
 | |
|         samples = case['samples']
 | |
|         control = case['control']
 | |
|         alternatives = {'less': 'less', 'greater': 'greater',
 | |
|                         'two-sided': 'twosided'}
 | |
|         p_ref = case['pvalues'][alternative.replace('-', '')]
 | |
| 
 | |
|         res = stats.dunnett(*samples, control=control, alternative=alternative,
 | |
|                             rng=rng)
 | |
|         # atol can't be tighter because R reports some pvalues as "< 1e-4"
 | |
|         assert_allclose(res.pvalue, p_ref, rtol=5e-3, atol=1e-4)
 | |
| 
 | |
|         ci_ref = case['cis'][alternatives[alternative]]
 | |
|         if alternative == "greater":
 | |
|             ci_ref = [ci_ref, np.inf]
 | |
|         elif alternative == "less":
 | |
|             ci_ref = [-np.inf, ci_ref]
 | |
|         assert res._ci is None
 | |
|         assert res._ci_cl is None
 | |
|         ci = res.confidence_interval(confidence_level=0.95)
 | |
|         assert_allclose(ci.low, ci_ref[0], rtol=5e-3, atol=1e-5)
 | |
|         assert_allclose(ci.high, ci_ref[1], rtol=5e-3, atol=1e-5)
 | |
| 
 | |
|         # re-run to use the cached value "is" to check id as same object
 | |
|         assert res._ci is ci
 | |
|         assert res._ci_cl == 0.95
 | |
|         ci_ = res.confidence_interval(confidence_level=0.95)
 | |
|         assert ci_ is ci
 | |
| 
 | |
|     @pytest.mark.parametrize('alternative', ["two-sided", "less", "greater"])
 | |
|     def test_str(self, alternative):
 | |
|         rng = np.random.default_rng(189117774084579816190295271136455278291)
 | |
| 
 | |
|         res = stats.dunnett(
 | |
|             *self.samples_3, control=self.control_3, alternative=alternative,
 | |
|             rng=rng
 | |
|         )
 | |
| 
 | |
|         # check some str output
 | |
|         res_str = str(res)
 | |
|         assert '(Sample 2 - Control)' in res_str
 | |
|         assert '95.0%' in res_str
 | |
| 
 | |
|         if alternative == 'less':
 | |
|             assert '-inf' in res_str
 | |
|             assert '19.' in res_str
 | |
|         elif alternative == 'greater':
 | |
|             assert 'inf' in res_str
 | |
|             assert '-13.' in res_str
 | |
|         else:
 | |
|             assert 'inf' not in res_str
 | |
|             assert '21.' in res_str
 | |
| 
 | |
|     def test_warnings(self):
 | |
|         rng = np.random.default_rng(189117774084579816190295271136455278291)
 | |
| 
 | |
|         res = stats.dunnett(
 | |
|             *self.samples_3, control=self.control_3, rng=rng
 | |
|         )
 | |
|         msg = r"Computation of the confidence interval did not converge"
 | |
|         with pytest.warns(UserWarning, match=msg):
 | |
|             res._allowance(tol=1e-5)
 | |
| 
 | |
|     def test_raises(self):
 | |
|         samples, control = self.samples_3, self.control_3
 | |
| 
 | |
|         # alternative
 | |
|         with pytest.raises(ValueError, match="alternative must be"):
 | |
|             stats.dunnett(*samples, control=control, alternative='bob')
 | |
| 
 | |
|         # 2D for a sample
 | |
|         samples_ = copy.deepcopy(samples)
 | |
|         samples_[0] = [samples_[0]]
 | |
|         with pytest.raises(ValueError, match="must be 1D arrays"):
 | |
|             stats.dunnett(*samples_, control=control)
 | |
| 
 | |
|         # 2D for control
 | |
|         control_ = copy.deepcopy(control)
 | |
|         control_ = [control_]
 | |
|         with pytest.raises(ValueError, match="must be 1D arrays"):
 | |
|             stats.dunnett(*samples, control=control_)
 | |
| 
 | |
|         # No obs in a sample
 | |
|         samples_ = copy.deepcopy(samples)
 | |
|         samples_[1] = []
 | |
|         with pytest.raises(ValueError, match="at least 1 observation"):
 | |
|             stats.dunnett(*samples_, control=control)
 | |
| 
 | |
|         # No obs in control
 | |
|         control_ = []
 | |
|         with pytest.raises(ValueError, match="at least 1 observation"):
 | |
|             stats.dunnett(*samples, control=control_)
 | |
| 
 | |
|         res = stats.dunnett(*samples, control=control)
 | |
|         with pytest.raises(ValueError, match="Confidence level must"):
 | |
|             res.confidence_interval(confidence_level=3)
 | |
| 
 | |
|     @pytest.mark.filterwarnings("ignore:Computation of the confidence")
 | |
|     @pytest.mark.parametrize('n_samples', [1, 2, 3])
 | |
|     def test_shapes(self, n_samples):
 | |
|         rng = np.random.default_rng(689448934110805334)
 | |
|         samples = rng.normal(size=(n_samples, 10))
 | |
|         control = rng.normal(size=10)
 | |
|         res = stats.dunnett(*samples, control=control, rng=rng)
 | |
|         assert res.statistic.shape == (n_samples,)
 | |
|         assert res.pvalue.shape == (n_samples,)
 | |
|         ci = res.confidence_interval()
 | |
|         assert ci.low.shape == (n_samples,)
 | |
|         assert ci.high.shape == (n_samples,)
 |