OwenT
)powen4
)
OwenQ1
)OwenQ2
)ptOwen
)The purpose of this vignette is to assess the correctness of the functions of the OwenQ
package.
As said in the main vignette, the fourth Owen cumulative function \(O_4\), implemented under the name powen4
allows to evaluate the power of equivalence tests. This is perhaps the main application of the OwenQ
package and we will particularly focus on this situation.
Our strategy runs as follows:
To test the OwenT
function, we will compare some values it returns to those returned by other implementations. Note that the other functions of the OwenQ
package rely on OwenT
when the number of degrees of freedom is odd. Therefore, by testing these other functions for an odd number of degrees of freedom, we implicitely test the OwenT
function.
We will compare a couple of values returned by OwenQ1
and OwenQ2
to the values obtained by numerical integration in Wolfram|Alpha.
We will test powen4
by performing some power calculations relying on this function and comparing the results with the ones provided by SAS. We will also perform these power calculations with the help of the ipowen4
function, which evaluates the \(O_4\) function by a powerful numerical integration, and we will compare the results.
These power calculations will be performed for \(100\) different scenarios, and we will conclude that powen4
is reliable for these scenarios. Then, to test the other functions of the OwenQ
package, we will check that some mathematical relations hold for these \(100\) scenarios.
The folder tests/testthat
of the OwenQ
package contains many comparisons with Wolfram|Alpha. The results we obtain with OwenQ
are always the same as the ones obtained with Wolfram|Alpha up to a tolerance of at least \(10\) decimal digits.
OwenT
)The Owen \(T\)-function is implemented under the name OwenT
. This is a port of the function owens_t
of the C++ special_functions
library included in the boost
set of libraries. Some details about the C++ implementation are available here.
The libraries provided by boost
are peer-reviewed, and this is enough to trust the reliability of OwenT
. Nevertheless, below we compare the results of OwenT
to the six values given in Patefield’s article, up to \(14\) decimal digits. We have also checked that Wolfram|Alpha gives these values.
<- data.frame(
testData h = c(0.0625, 6.5, 7, 4.78125, 2, 1),
a = c(0.25, 0.4375, 0.96875, 0.0625, 0.5, 0.9999975),
Patefield = c(3.8911930234701e-02, 2.0005773048508e-11, 6.3990627193899e-13, 1.0632974804687e-07, 8.6250779855215e-03, 6.6741808978229e-02),
OwenT = numeric(6)
)for(i in 1:nrow(testData)){
$OwenT[i] <- OwenT(testData$h[i], testData$a[i])
testData
}print(testData, digits=14)
## h a Patefield OwenT
## 1 0.06250 0.2500000 3.8911930234701e-02 3.8911930234701e-02
## 2 6.50000 0.4375000 2.0005773048508e-11 2.0005773048508e-11
## 3 7.00000 0.9687500 6.3990627193899e-13 6.3990627193899e-13
## 4 4.78125 0.0625000 1.0632974804687e-07 1.0632974804687e-07
## 5 2.00000 0.5000000 8.6250779855215e-03 8.6250779855215e-03
## 6 1.00000 0.9999975 6.6741808978229e-02 6.6741808978229e-02
We get the same results with OwenT
.
The two Owen \(Q\)-functions \(Q_1\) and \(Q_2\) are defined by: \[ Q_1(\nu, t, \delta, R) = \frac{1}{\Gamma\left(\frac{\nu}{2}\right)2^{\frac12(\nu-2)}} \int_0^R \Phi\left(\frac{tx}{\sqrt{\nu}}-\delta\right) x^{\nu-1} e^{-\frac{x^2}{2}} \mathrm{d}x \] and \[ Q_2(\nu, t, \delta, R) = \frac{1}{\Gamma\left(\frac{\nu}{2}\right)2^{\frac12(\nu-2)}} \int_R^\infty \Phi\left(\frac{tx}{\sqrt{\nu}}-\delta\right) x^{\nu-1} e^{-\frac{x^2}{2}} \mathrm{d}x. \]
They are implemented in the OwenQ
package under the respective names OwenQ1
and OwenQ2
, for integer values of \(\nu\), following Owen’s algorithm (1965).
In Wolfram|Alpha, these functions are not available, but we can evaluate them by numerical integration.
Below we compare two values of OwenQ1
to the ones returned by Wolfram|Alpha.
# wolfram: Integrate[(1+Erf[(3*x/Sqrt[3]-2)/Sqrt[2]])*x^(3-1)*Exp[-x^2/2],{x,0,5}]/2/Gamma[3/2]/2^((3-2)/2)
OwenQ1(3, 3, 2, 5)
## [1] 0.6800117
Our value rounded to \(6\) digits is the same as the one given by Wolfram.
# wolfram: Integrate[(1+Erf[(3*x/Sqrt[1000]-2)/Sqrt[2]])*x^(1000-1)*Exp[-x^2/2],{x,0,30}]/2/Gamma[1000/2]/2^((1000-2)/2)
print(OwenQ1(1000, 3, 2, 30), digits=16)
## [1] 0.008518809463589428
The two values are the same up to \(13\) digits.
Now we compare two values of OwenQ2
to the ones returned by Wolfram|Alpha.
# wolfram: Integrate[(1+Erf[(3*x/Sqrt[3]-2)/Sqrt[2]])*x^(3-1)*Exp[-x^2/2],{x,5,Infinity}]/2/Gamma[3/2]/2^((3-2)/2)
OwenQ2(3, 3, 2, 5)
## [1] 1.54405e-05
The two values are identical.
# wolfram: Integrate[(1+Erf[(3*x/Sqrt[1000]-2)/Sqrt[2]])*x^(1000-1)*Exp[-x^2/2],{x,5,Infinity}]/2/Gamma[1000/2]/2^((1000-2)/2)
print(OwenQ2(1000, 3, 2, 5), digits=16)
## [1] 0.8406201459600969
The two values are identical up to \(13\) digits.
powen4
)As seen in the other vignette, the fourth Owen cumulative function \(O_4\), implemented under the name powen4
, can be used to evaluate the power of equivalence tests.
The powerTOST
function below returns the power of the equivalence test for a so-called parallel design with equal variances, when considering the alternative hypothesis \(H_1\colon\{-\Delta < \delta_0 < \Delta \}\), where \(\delta_0\) denotes the difference between the two means. This function takes as arguments the significance level \(\alpha\), the difference \(\delta_0\) between the two means, the threshold \(\Delta\), the common standard deviation \(\sigma\) of the two samples, and the two sample sizes \(n_1\) and \(n_2\).
<- function(alpha, delta0, Delta, sigma, n1, n2, algo=2) {
powerTOST <- sqrt(1/n1 + 1/n2) * sigma
se <- (delta0 + Delta) / se
delta1 <- (delta0 - Delta) / se
delta2 <- n1 + n2 - 2
dof <- qt(1 - alpha, dof)
q powen4(dof, q, -q, delta1, delta2, algo=algo)
}
As you can see, the powen4
function has an argument algo
. This is also the case for the other Owen functions, except for ptOwen
. The algo
argument can take two values, 1
or 2
. Th default value is algo=2
, and as we will see later, the evaluation is more reliable with this option. The value of algo
corresponds to a small difference in the algorithm. With algo=1
, the evaluation is a bit faster. And we will see that powerTOST
is reliable for algo=1
when the value of n1+n2
is not too large.
The table shown below contains \(100\) results of power calculations with SAS version 9.4, for a total sample size \(n_1+n_2\) going from \(20\) to \(1200\). The results are rounded to \(5\) decimal digits.
alpha | delta0 | Delta | sigma | n1 | n2 | powerSAS | |
---|---|---|---|---|---|---|---|
1 | 0.05 | 0.0 | 1 | 1 | 10 | 10 | 0.39094 |
2 | 0.05 | 0.0 | 1 | 1 | 15 | 15 | 0.69541 |
3 | 0.05 | 0.0 | 1 | 1 | 20 | 20 | 0.85580 |
4 | 0.05 | 0.0 | 1 | 1 | 25 | 25 | 0.93426 |
5 | 0.05 | 0.0 | 1 | 1 | 30 | 30 | 0.97092 |
6 | 0.05 | 0.1 | 1 | 1 | 10 | 10 | 0.38272 |
7 | 0.05 | 0.1 | 1 | 1 | 15 | 15 | 0.67836 |
8 | 0.05 | 0.1 | 1 | 1 | 20 | 20 | 0.83661 |
9 | 0.05 | 0.1 | 1 | 1 | 25 | 25 | 0.91781 |
10 | 0.05 | 0.1 | 1 | 1 | 30 | 30 | 0.95889 |
11 | 0.05 | 0.2 | 1 | 1 | 10 | 10 | 0.35908 |
12 | 0.05 | 0.2 | 1 | 1 | 15 | 15 | 0.62954 |
13 | 0.05 | 0.2 | 1 | 1 | 20 | 20 | 0.78069 |
14 | 0.05 | 0.2 | 1 | 1 | 25 | 25 | 0.86796 |
15 | 0.05 | 0.2 | 1 | 1 | 30 | 30 | 0.92017 |
16 | 0.05 | 0.3 | 1 | 1 | 10 | 10 | 0.32287 |
17 | 0.05 | 0.3 | 1 | 1 | 15 | 15 | 0.55540 |
18 | 0.05 | 0.3 | 1 | 1 | 20 | 20 | 0.69322 |
19 | 0.05 | 0.3 | 1 | 1 | 25 | 25 | 0.78471 |
20 | 0.05 | 0.3 | 1 | 1 | 30 | 30 | 0.84909 |
21 | 0.05 | 0.4 | 1 | 1 | 10 | 10 | 0.27820 |
22 | 0.05 | 0.4 | 1 | 1 | 15 | 15 | 0.46531 |
23 | 0.05 | 0.4 | 1 | 1 | 20 | 20 | 0.58306 |
24 | 0.05 | 0.4 | 1 | 1 | 25 | 25 | 0.67174 |
25 | 0.05 | 0.4 | 1 | 1 | 30 | 30 | 0.74260 |
26 | 0.05 | 0.5 | 1 | 1 | 10 | 10 | 0.22970 |
27 | 0.05 | 0.5 | 1 | 1 | 15 | 15 | 0.36967 |
28 | 0.05 | 0.5 | 1 | 1 | 20 | 20 | 0.46208 |
29 | 0.05 | 0.5 | 1 | 1 | 25 | 25 | 0.53883 |
30 | 0.05 | 0.5 | 1 | 1 | 30 | 30 | 0.60600 |
31 | 0.05 | 0.0 | 1 | 1 | 10 | 30 | 0.70373 |
32 | 0.05 | 0.0 | 1 | 1 | 15 | 30 | 0.85764 |
33 | 0.05 | 0.0 | 1 | 1 | 20 | 30 | 0.92324 |
34 | 0.05 | 0.0 | 1 | 1 | 25 | 30 | 0.95452 |
35 | 0.05 | 0.0 | 1 | 1 | 30 | 30 | 0.97092 |
36 | 0.05 | 0.1 | 1 | 1 | 10 | 30 | 0.68648 |
37 | 0.05 | 0.1 | 1 | 1 | 15 | 30 | 0.83846 |
38 | 0.05 | 0.1 | 1 | 1 | 20 | 30 | 0.90604 |
39 | 0.05 | 0.1 | 1 | 1 | 25 | 30 | 0.94003 |
40 | 0.05 | 0.1 | 1 | 1 | 30 | 30 | 0.95889 |
41 | 0.05 | 0.2 | 1 | 1 | 10 | 30 | 0.63703 |
42 | 0.05 | 0.2 | 1 | 1 | 15 | 30 | 0.78255 |
43 | 0.05 | 0.2 | 1 | 1 | 20 | 30 | 0.85439 |
44 | 0.05 | 0.2 | 1 | 1 | 25 | 30 | 0.89501 |
45 | 0.05 | 0.2 | 1 | 1 | 30 | 30 | 0.92017 |
46 | 0.05 | 0.3 | 1 | 1 | 10 | 30 | 0.56192 |
47 | 0.05 | 0.3 | 1 | 1 | 15 | 30 | 0.69503 |
48 | 0.05 | 0.3 | 1 | 1 | 20 | 30 | 0.76944 |
49 | 0.05 | 0.3 | 1 | 1 | 25 | 30 | 0.81676 |
50 | 0.05 | 0.3 | 1 | 1 | 30 | 30 | 0.84909 |
51 | 0.05 | 0.4 | 1 | 1 | 10 | 30 | 0.47061 |
52 | 0.05 | 0.4 | 1 | 1 | 15 | 30 | 0.58470 |
53 | 0.05 | 0.4 | 1 | 1 | 20 | 30 | 0.65610 |
54 | 0.05 | 0.4 | 1 | 1 | 25 | 30 | 0.70594 |
55 | 0.05 | 0.4 | 1 | 1 | 30 | 30 | 0.74260 |
56 | 0.05 | 0.5 | 1 | 1 | 10 | 30 | 0.37365 |
57 | 0.05 | 0.5 | 1 | 1 | 15 | 30 | 0.46343 |
58 | 0.05 | 0.5 | 1 | 1 | 20 | 30 | 0.52475 |
59 | 0.05 | 0.5 | 1 | 1 | 25 | 30 | 0.57052 |
60 | 0.05 | 0.5 | 1 | 1 | 30 | 30 | 0.60600 |
61 | 0.05 | 0.0 | 3 | 4 | 50 | 50 | 0.96239 |
62 | 0.05 | 1.0 | 3 | 4 | 50 | 50 | 0.79849 |
63 | 0.05 | 2.0 | 3 | 4 | 50 | 50 | 0.34329 |
64 | 0.05 | 2.5 | 3 | 4 | 50 | 50 | 0.15288 |
65 | 0.05 | 0.0 | 4 | 4 | 10 | 90 | 0.81791 |
66 | 0.05 | 1.0 | 4 | 4 | 10 | 90 | 0.70346 |
67 | 0.05 | 2.0 | 4 | 4 | 10 | 90 | 0.43595 |
68 | 0.05 | 2.5 | 4 | 4 | 10 | 90 | 0.29819 |
69 | 0.05 | 0.0 | 4 | 7 | 100 | 100 | 0.98278 |
70 | 0.05 | 1.0 | 4 | 7 | 100 | 100 | 0.91512 |
71 | 0.05 | 2.0 | 4 | 7 | 100 | 100 | 0.64376 |
72 | 0.05 | 3.0 | 4 | 7 | 100 | 100 | 0.26169 |
73 | 0.01 | 0.0 | 4 | 7 | 100 | 100 | 0.90831 |
74 | 0.01 | 1.0 | 4 | 7 | 100 | 100 | 0.74924 |
75 | 0.01 | 2.0 | 4 | 7 | 100 | 100 | 0.37443 |
76 | 0.01 | 3.0 | 4 | 7 | 100 | 100 | 0.09290 |
77 | 0.05 | 0.0 | 4 | 4 | 185 | 10 | 0.84568 |
78 | 0.05 | 1.0 | 4 | 4 | 185 | 10 | 0.73025 |
79 | 0.05 | 2.0 | 4 | 4 | 185 | 10 | 0.45459 |
80 | 0.05 | 3.0 | 4 | 4 | 185 | 10 | 0.19001 |
81 | 0.05 | 0.0 | 4 | 8 | 185 | 100 | 0.98240 |
82 | 0.05 | 1.0 | 4 | 8 | 185 | 100 | 0.91417 |
83 | 0.05 | 2.0 | 4 | 8 | 185 | 100 | 0.64226 |
84 | 0.05 | 3.0 | 4 | 8 | 185 | 100 | 0.26103 |
85 | 0.01 | 0.0 | 4 | 10 | 250 | 250 | 0.96713 |
86 | 0.01 | 1.0 | 4 | 10 | 250 | 250 | 0.84523 |
87 | 0.01 | 2.0 | 4 | 10 | 250 | 250 | 0.46161 |
88 | 0.01 | 3.0 | 4 | 10 | 250 | 250 | 0.11288 |
89 | 0.01 | 0.0 | 4 | 14 | 500 | 500 | 0.97112 |
90 | 0.01 | 1.0 | 4 | 14 | 500 | 500 | 0.85433 |
91 | 0.01 | 2.0 | 4 | 14 | 500 | 500 | 0.47184 |
92 | 0.01 | 3.0 | 4 | 14 | 500 | 500 | 0.11536 |
93 | 0.01 | 0.0 | 5 | 35 | 600 | 600 | 0.11547 |
94 | 0.01 | 4.0 | 5 | 35 | 600 | 600 | 0.01658 |
95 | 0.05 | 0.0 | 5 | 30 | 600 | 600 | 0.78512 |
96 | 0.05 | 4.0 | 5 | 50 | 600 | 600 | 0.02642 |
97 | 0.01 | 0.0 | 5 | 6 | 1190 | 10 | 0.23194 |
98 | 0.01 | 4.0 | 5 | 6 | 1190 | 10 | 0.02739 |
99 | 0.05 | 0.0 | 5 | 9 | 1190 | 10 | 0.08256 |
100 | 0.05 | 4.0 | 5 | 9 | 1190 | 10 | 0.03115 |
This table is stored in a dataframe named SAS
. We compare the SAS values to the ones obtained by our powerTOST
function.
<- numeric(nrow(SAS))
power for (i in 1:nrow(SAS)) {
<-
power[i] powerTOST(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
) }
Rounding our values to \(5\) decimal digits, we find that our results are identical to the SAS results:
identical(round(power,5), SAS$powerSAS)
## [1] TRUE
With the option algo=1
, the results are identical as well:
<- numeric(nrow(SAS))
power for (i in 1:nrow(SAS)) {
<-
power[i] powerTOST(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i],
algo = 1
)
}identical(round(power,5), SAS$powerSAS)
## [1] TRUE
The ipowen4
internal function of the OwenQ
package evaluates the fourth Owen cumulative function \(O_4\) by a powerful numerical integration implemented in C++ (with the package RcppNumerical
). Thus we have two completely different implementations of \(O_4\). The ipowerTOST
function below is obtained by replacing powen4
with ipowen4
in powerTOST
. We will compare the results of powerTOST
with the ones of ipowerTOST
.
<- function(alpha, delta0, Delta, sigma, n1, n2) {
ipowerTOST <- sqrt(1/n1 + 1/n2) * sigma
se <- (delta0 + Delta) / se
delta1 <- (delta0 - Delta) / se
delta2 <- n1 + n2 - 2
dof <- qt(1 - alpha, dof)
q :::ipowen4(dof, q, -q, delta1, delta2)
OwenQ }
powen4
powen4
function with the option algo=1
abnormally takes some negative values:Note that the discrepancy between powen4
and ipowen4
occurs only for \(\sigma > 65\).
powen4
with the option algo=1
and ipowen4
:There is no discrepancy between powen4
with the option algo=2
and ipowen4
. The irregularity of powen4
with the option algo=1
suggests that it returns wrong values.
powen4
with the option algo=1
and ipowen4
, and we still observe an irregularity of powen4
(on the second figure below):With the option algo=2
, the results of powen4
coincide with the ones of ipowen4
.
powen4
and ipowen4
:We conclude that powen4
with the option algo=1
is not reliable when the number of degrees of freedom is too large. As said before, the interest of the option algo=1
is that the evaluation is faster.
For \(n_1=n_2=2500\), the results of powerTOST
with algo=2
still coincide with the result of ipowerTOST
:
<- 0.05; delta0 <- 0; Delta <- 5
alpha <- 110
sigma <- n2 <- 2500
n1 powerTOST(alpha, delta0, Delta, sigma, n1, n2)
## [1] 4.523596e-05
ipowerTOST(alpha, delta0, Delta, sigma, n1, n2)
## [1] 4.523596e-05
## attr(,"err_est")
## [1] 5.022201e-19
## attr(,"err_code")
## [1] 0
And even for \(n_1=n_2=5000\):
<- 152
sigma <- n2 <- 5000
n1 powerTOST(alpha, delta0, Delta, sigma, n1, n2)
## [1] 0.003612374
ipowerTOST(alpha, delta0, Delta, sigma, n1, n2)
## [1] 0.003612374
## attr(,"err_est")
## [1] 4.010541e-17
## attr(,"err_code")
## [1] 0
Below we compare the results returned by powerTOST
to the ones returned by ipowerTOST
for the parameters given in the SAS
dataset.
<- ipower <- numeric(nrow(SAS))
power for (i in 1:nrow(SAS)) {
<-
power[i] powerTOST(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
)<-
ipower[i] ipowerTOST(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
)
}identical(round(power, 10), round(ipower, 10))
## [1] TRUE
Results are the same up to \(10\) digits. And also with the option algo=1
:
<- numeric(nrow(SAS))
power for (i in 1:nrow(SAS)) {
<-
power[i] powerTOST(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i],
algo = 1
)
}identical(round(power, 10), round(ipower, 10))
## [1] TRUE
The powen4
function with option algo=1
seems to return correct values for \(\nu \leq 1200\).
The powen4
function with option algo=2
allows higher values of \(\nu\).
In any case, we recommend to compare the result of powen4
with the one of ipowen4
.
We previously validated the powen4
function for the \(100\) scenarios of the dataset SAS
.
Now we test the functions powen1
, powen2
and powen3
by checking the equality \[
O_1(\nu, t_1, t_2, \delta_1, \delta_2) + O_2(\nu, t_1, t_2, \delta_1, \delta_2)
+
O_3(\nu, t_1, t_2, \delta_1, \delta_2) + O_4(\nu, t_1, t_2, \delta_1, \delta_2)
= 1.
\]
We restrict our attention to default setting algo=2
. We check the above equality for the \(100\) scenarios of the dataset SAS
.
<- function(alpha, delta0, Delta, sigma, n1, n2) {
f <- sqrt(1/n1 + 1/n2) * sigma
se <- (delta0 + Delta) / se
delta1 <- (delta0 - Delta) / se
delta2 <- n1 + n2 - 2
dof <- qt(1 - alpha, dof)
q powen1(dof, q,-q, delta1, delta2) + powen2(dof, q,-q, delta1, delta2) +
powen3(dof, q,-q, delta1, delta2) + powen4(dof, q,-q, delta1, delta2)
}<- numeric(nrow(SAS))
test for (i in 1:nrow(SAS)) {
<-
test[i] f(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
)
}all(abs(test-1) < 1e-14)
## [1] TRUE
We find that each of the \(100\) sums is equal to \(1\) up to a tolerance of \(14\) digits.
OwenQ1
)We previously validated the powen4
function (implementation of the fourth Owen cumulative function \(O_4\)) for the \(100\) scenarios of the dataset SAS
.
Now, to test OwenQ1
, we will use the following equality:
\[ O_4(\nu, t_1, t_2, \delta_1, \delta_2) = Q_1\left(\nu, t_2, \delta_2, \frac{\sqrt{\nu}(\delta_1-\delta_2)}{t_1-t_2}\right) - Q_1\left(\nu, t_1, \delta_1, \frac{\sqrt{\nu}(\delta_1-\delta_2)}{t_1-t_2}\right). \]
We use this formula to perform the power calculations with OwenQ1
instead of powen4
.
<- function(alpha, delta0, Delta, sigma, n1, n2) {
powerTOST2 <- sqrt(1/n1 + 1/n2) * sigma
se <- (delta0 + Delta) / se
delta1 <- (delta0 - Delta) / se
delta2 <- n1 + n2 - 2
dof <- qt(1 - alpha, dof)
q <- sqrt(dof)*(delta1 - delta2)/q/2
R OwenQ1(dof, -q, delta2, R) - OwenQ1(dof, q, delta1, R)
}<- numeric(nrow(SAS))
power2 for (i in 1:nrow(SAS)) {
<-
power2[i] powerTOST2(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
)
}all(abs(power - power2) < 1e-9)
## [1] TRUE
The values rounded to \(9\) digits are the same as the ones we previously obtained with powen4
.
OwenQ2
)We previously validated powen2
for the \(100\) scenarios of the dataset SAS
. Now we test the OwenQ2
function by checking the equality \[
O_2(\nu, t_1, t_2, \delta_1, \delta_2) =
Q_2\left(\nu, t_1, \delta_1,
\frac{\sqrt{\nu}(\delta_1-\delta_2)}{t_1-t_2}\right)
- Q_2\left(\nu, t_2, \delta_2,
\frac{\sqrt{\nu}(\delta_1-\delta_2)}{t_1-t_2}\right).
\]
We check this equality for the \(100\) scenarios of the dataset SAS
.
<- function(alpha, delta0, Delta, sigma, n1, n2) {
g <- sqrt(1/n1 + 1/n2) * sigma
se <- (delta0 + Delta) / se
delta1 <- (delta0 - Delta) / se
delta2 <- n1 + n2 - 2
dof <- qt(1 - alpha, dof)
q <- sqrt(dof)*(delta1 - delta2)/q/2
R <- OwenQ2(dof, q, delta1, R) - OwenQ2(dof, -q, delta2, R)
x <- powen2(dof, q, -q, delta1, delta2)
y - y
x
}<- numeric(nrow(SAS))
test for (i in 1:nrow(SAS)) {
<-
test[i] g(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
)
}all(abs(test) < 1e-15)
## [1] TRUE
We find that each of the \(100\) equalities hold true up to a tolerance of \(15\) digits.
ptOwen
)We finally test ptOwen
, the implementation of the cumulative distribution function of the noncentral Student distribution.
If \(T_1\) follows the noncentral Student distribution with number of degrees of freedom \(\nu\) and noncentrality parameter \(\delta_1\), then for any \(t_1\) the equality \[
\Pr(T_1 \leq t_1) = O_1(\nu, t_1, t_2, \delta_1, \delta_2) + O_2(\nu, t_1, t_2, \delta_1, \delta_2)
\] holds for any \(t_2\) and \(\delta_2\). We check this equality for the \(100\) scenarios of the dataset SAS
.
<- function(alpha, delta0, Delta, sigma, n1, n2) {
h <- sqrt(1/n1 + 1/n2) * sigma
se <- (delta0 + Delta) / se
delta1 <- (delta0 - Delta) / se
delta2 <- n1 + n2 - 2
dof <- qt(1 - alpha, dof)
q <- ptOwen(q, dof, delta1)
x <- powen1(dof, q, -q, delta1, delta2) + powen2(dof, q, -q, delta1, delta2)
y - y
x
}<- numeric(nrow(SAS))
test for (i in 1:nrow(SAS)) {
<-
test[i] h(
alpha = SAS$alpha[i],
delta0 = SAS$delta0[i],
Delta = SAS$Delta[i],
sigma = SAS$sigma[i],
n1 = SAS$n1[i],
n2 = SAS$n2[i]
)
}all(abs(test) < 1e-15)
## [1] TRUE
For each scenario, the equality holds up to a tolerance of \(15\) digits.
Patefield, M. (2000). Fast and Accurate Calculation of Owen’s T Function. Journal of Statistical Software 5 (5), 1-25.
Owen, D. B. (1965). A special case of a bivariate noncentral t-distribution. Biometrika 52, 437-446.
Wolfram Alpha LLC. 2017. Wolfram|Alpha. (access July 17, 2017).