Reputation: 9018
I'd like to do a surface plot where z is a call to the pwr.t.test function evaluated at x an y
d = rep( seq(.05,.1,.01), length(seq(.2,.26,.01)) )
s = rep(seq(.2,.26,.01), length(seq(.05,.1,.01)))
M =mesh(d,s)
surf3D(x = M$x,
y = M$y,
z = pwr.t.test(d=M$x/M$y,power=.8,sig.level=.1,type="two.sample",alternative="two.sided")$n ,
colkey=FALSE,
bty="b2",
main="test")
how can that be done?
Upvotes: 1
Views: 383
Reputation: 9570
If you are just trying to plot required sample sizes, a 3D plot may be a bit of overkill. So, here first is an approach to just making a 2D heatmap.
First, set your X and Y values. Note that these do not have to be entered multiple times (e.g. with rep
)
x <- seq(.05,.1,.01)
y <- seq(.2,.26,.01)
Then, we can create a custom function to calculate the needed sample size for each combination (using outer
). Of note: the effect size you had calculated before is not correct. Effect size is {mean(y) - mean(x) } / {sd(x)}
(the sd
should/could include y; see here for more on effect sizes). So, here, I am assuming that your standard deviation is 1, though I noted where you can put that. The pwr
functions also don't appear to like playing with vectors, so I am looping over each value individually.
getN <- function(x,y){
sapply(1:length(x), function(idx){
pwr::pwr.t.test(d= (y[idx] - x[idx] ) # / SD???
, power=.8, sig.level=.1
, type="two.sample", alternative="two.sided"
)$n
})
}
Then, use outer
to calculate the sample sizes for each combination. I also like to set the row/column names to help keep track of things
z <- outer(x, y, getN)
row.names(z) <- x
colnames(z) <- y
gives
0.2 0.21 0.22 0.23 0.24 0.25 0.26
0.05 550.2098 483.6650 428.5144 382.2977 343.1846 309.7905 281.0524
0.06 631.5180 550.2098 483.6650 428.5144 382.2977 343.1846 309.7905
0.07 732.3030 631.5180 550.2098 483.6650 428.5144 382.2977 343.1846
0.08 859.3212 732.3030 631.5180 550.2098 483.6650 428.5144 382.2977
0.09 1022.5344 859.3212 732.3030 631.5180 550.2098 483.6650 428.5144
0.1 1237.1243 1022.5344 859.3212 732.3030 631.5180 550.2098 483.6650
Which is the matrix that I believe you want to plot.
Here, I am using dplyr
to turn it into long format and pass it in to ggplot
(and using viridis
for a nice color palette, though others work fine as well)
data.frame(z, check.names = FALSE) %>%
mutate(xVal = row.names(.)) %>%
gather(yVal, `Sample Size`, -xVal) %>%
ggplot(
aes(x = xVal
, y = yVal
, fill = `Sample Size`)) +
geom_tile() +
viridis::scale_fill_viridis()
gives
Now, if you really want a 3D version, you can use plotly
to accomplish that:
plot_ly(
x = x
, y = y
, z = z
, type = 'surface')
gives
And note that the produced version is interactive.
Or with plot3D
:
M <- mesh(x,y)
surf3D(
x = M$x
, y = M$y
, z = z
)
gives
And note that M
is now much smaller because it is not unneccesarily duplicated.
Upvotes: 2