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).