Skip to content

Problem with contour(): typo

11 messages · Duncan Murdoch, Helmut Schütz, Puetz, Benno

#
Dear all,

sorry, my last message contained a typo. Correct:

library(PowerTOST)
x??? <- 0.90
y??? <- 0.35
res? <- as.numeric(sampleN.TOST(theta0 = x, CV = y, design = "2x2x4",
  ??????????????????????????????? method = "central", details = FALSE,
  ??????????????????????????????? print = FALSE)[7:8])
mesh <- 28
ys?? <- unique(sort(c(y, seq(y*.8, y*1.2, length.out = mesh))))
xs?? <- unique(sort(c(x, seq(x*0.95, 1, length.out = mesh))))
z??? <- matrix(nrow = length(ys), ncol = length(xs),
  ?????????????? dimnames = list(paste0("y.", signif(ys, 5)),
  ?????????????????????????????? paste0("x.", signif(xs, 5))))
for (i in seq_along(ys)) {
  ? for (j in seq_along(xs)) {
  ??? z[i, j] <- suppressMessages(
  ???????????????? power.TOST(CV = ys[i], theta0 = xs[j], design = "2x2x4",
  ??????????????????????????? method = "central", n = res[1]))
  ? }
}
z??? <- z[nrow(z):1, ncol(z):1]?????????      # reverse rows & columns
z[paste0("y.", y), paste0("x.", x)] == res[2] # should be TRUE
contour(xs, ys, z, nlevels = 20, las = 1, labcex = 1,
  ??????? xlab = "x", ylab = "y", main = paste("n =", res[1]))
abline(h = y, v = x, lty = 2)
points(x, y, col = "red", cex = 1.5)
text(x, y, labels = signif(z[paste0("y.", y), paste0("x.", x)], 6),
  ???? col = "red", adj = c(-0.1, 1.5))


Helmut
#
You're doing a lot of manipulation of the z matrix; I haven't followed 
all of it, but that's where I'd look for problems.  Generally if you 
keep your calculation of the z matrix very simple you are better off. 
For example, once you have xs and ys in the form you want, calculate z as

z <- outer(x,y, function(x,y) ...)

and then plot it using contour(x, y, z, ...)

The only tricky issue here is that the function needs to be vectorized, 
so if your power.TOST function doesn't accept vectors for CV and theta0,
you'll need to put it in a wrapper that does (perhaps using the 
Vectorize function).

Duncan Murdoch
On 28/09/2020 3:08 p.m., Helmut Sch?tz wrote:
#
Dear Duncan,

Duncan Murdoch wrote on 2020-09-28 21:47:
Here I'm lost. power.TOST(theta0, CV, ...) vectorizes properly for 
theta0 _or_ CV but no _both_. Hence
library(PowerTOST)
power.TOST(theta0 = c(0.9, 0.95, 1), CV = 0.25, n = 28)
and
power.TOST(theta0 = 0.95, CV = c(0.2, 0.25, 0.3), n = 28)
work, whereas
power.TOST(theta0 = c(0.9, 0.95, 1), 0.95, CV = c(0.2, 0.25, 0.3), n = 28)
not. Of note, we will throw an error in the next release if both 
arguments are vectors.
I tried
f <- function(x, y) {
 ? power.TOST(theta0 = x, CV = y, n = 28)
}
x <- unique(sort(c(0.95, seq(0.95*0.95, 1, length.out = 28))))
y <- unique(sort(c(0.25, seq(0.25*0.8, 0.25*1.2, length.out = 28))))
Vectorize(f, c("x, y"), SIMPLIFY = "array")
which is obviously not correct.

Helmut
#
On 29/09/2020 5:37 a.m., Helmut Sch?tz wrote:
>>
 >> and then plot it using contour(x, y, z, ...)

Sorry, that was a typo, should have been

   z <- outer(xs,ys, function(x,y) ...)
   contour(xs, ys, z)
I wouldn't do that, because it doesn't fit the usual R style.  It's very 
common for functions to allow vector inputs in several arguments, and 
match up corresponding values to form a vector result.
If you want to use Vectorize, the command would be

   power.TOST.vectorized <- Vectorize(power.TOST, c("theta0", "CV"))

A roughly equivalent version (without the recycling that Vectorize does) 
would be

   power.TOST.vectorized <- function(theta0, CV, ...) {
     result <- length(theta0)
     for (i in seq_along(theta0))
       result[i] <- power.TOST(theta0[i], CV[i], ...)
     result
   }

Duncan Murdoch
#
Dear Duncan,

Duncan Murdoch wrote on 2020-09-29 11:57:
I see. Here it would require to give the result as a matrix, 
data.frame,... Substantial change in the code though doable.
library(PowerTOST)
theta0 <- unique(sort(c(0.95, seq(0.95*0.95, 1, length.out = 10))))
CV???? <- unique(sort(c(0.25, seq(0.25*0.8, 0.25*1.2, length.out = 10))))
power.TOST.vectorized <- Vectorize(power.TOST, c("theta0", "CV", "n"))
and
power.TOST.vectorized(theta0 = theta0, CV = CV, n = 28)
gives the diagonal elements of the desired 11*11 matrix:
z <- matrix(ncol = length(theta0), nrow = length(CV))
for (i in seq_along(CV)) {
 ? z[i, ] <- power.TOST(theta0 = theta0, CV = CV[i], n = 28)
}

Helmut
#
I would assume the following snippet does what you want - note the use of outer with anonymous function wrapping powerTOST:

z <- outer(xs, ys, function(x, y)power.TOST(CV = y, theta0 = x, design = "2x2x4", method = "central", n = res[1]))
contour(xs, ys, z)

	Benno
#
Dear Benno,

THX, you made my day! Case closed.

Helmut

Puetz, Benno wrote on 2020-09-29 13:14:

  
    
#
That won't work unless power.TOST is vectorized.  outer() will pass it 
vectors of x and y values.

Duncan Murdoch
On 29/09/2020 8:11 a.m., Helmut Sch?tz wrote:
#
As I noted in my earlier post, it does - had checked that ;-)
It works by taking corresponding pair fo the input vectors (after possible recycling, as eluded by Helmut in his remark on working on only one vector) as needed for outer.

Thanks for the reminder, though,

	Benno
#
On 29/09/2020 9:16 a.m., Puetz, Benno wrote:
Great!

Duncan Murdoch
#
Dear Duncan and Benno,

Duncan Murdoch wrote on 2020-09-29 15:21:
The result in all of its "beauty": 
https://forum.bebac.at/mix_entry.php?id=21930#top21939

THX again!

Helmut