We will use the Sepal.Length column from the iris dataset in R.

x = iris$Sepal.Length 
print(c(mean(x), sd(x)))
## [1] 5.8433333 0.8280661

The sample mean is 5.84 and the sample standard deviation is 0.828.

Two-sided Z-test

We suppose the population distribution for the sepal length is normal with unknown mean \(\mu\) and known standard deviation \(0.8\) for simplicity.

Consider the hypothesis testing: \[H_0: \mu = 6\quad\text{ v.s. }\quad H_a:\mu\neq 6\]

Manual Implementation

We first compute the Z statistic, whose value is computed as -2.398 below.

sigma = 0.8 #known population s.d. 
xbar = mean(x) # sample mean
n = length(x) # sample size
mu0 = 6 # null hypothesis 

z = (xbar - mu0) / (sigma / sqrt(n)) # z statistic
print(z)
## [1] -2.398459

Then we compute the p-value, which is 0.016 < 0.05.

p.value = 2 * (1 - pnorm(abs(z)))
print(p.value)
## [1] 0.01646423

Therefore, we reject the null with significance level 0.05.

Use z.test function

The z.test function is from BSDA library.

library(BSDA)
## Loading required package: lattice
## 
## Attaching package: 'BSDA'
## The following object is masked from 'package:datasets':
## 
##     Orange
test = z.test(x, alternative="two.sided", mu=6,sigma.x = sigma, conf.level=0.95)
print(test)
## 
##  One-sample z-Test
## 
## data:  x
## z = -2.3985, p-value = 0.01646
## alternative hypothesis: true mean is not equal to 6
## 95 percent confidence interval:
##  5.715309 5.971358
## sample estimates:
## mean of x 
##  5.843333

The output of the Z test gives the confidence interval of the population mean, which dose not include the null hypothesis. Also, the p-value is computed. So we reject the null.

Sample size determination

We first define the power function for the two-sided Z-test for true mean 5.8

z.power <- function(n){
  z.quan = qnorm(0.975) #1.96
  z = (5.8 - 6) / (sigma / sqrt(n))
  return(pnorm(-z.quan-z) + pnorm(-z.quan+z))
}

For example, the power with 100 samples is

z.power(100)
## [1] 0.705418

To find the minimum sample size to ensure a power of 0.8 at \(\mu=5.8\), we compute

obj <- function(n){ z.power(n) - 0.8}
out = uniroot(obj, c(1, 1000))
print(out)
## $root
## [1] 125.5818
## 
## $f.root
## [1] 1.054094e-09
## 
## $iter
## [1] 10
## 
## $init.it
## [1] NA
## 
## $estim.prec
## [1] 6.103516e-05

Therefore, the minimum sample size is 126.

Or, we can compute it by the approximated value below.

n.size = ceiling((sigma * (qnorm(0.025) - qnorm(0.8)) / (5.8 - 6) ) ** 2)
print(n.size)
## [1] 126

One-sided Z-test

Now we consider the following test: \[H_0: \mu = 6\quad\text{ v.s. }\quad H_a:\mu < 6\]

Manual Implementation

We will reuse the Z-statistic we computed before. We adjust the p-value to the new hypothesis testing.

p.value.new = pnorm(z)
print(p.value.new)
## [1] 0.008232116

The p-value is 0.008 < 0.05. So we reject the null.

Use z.test function

We call the z.test function from BSDA library.

test.new = z.test(x, alternative="less", mu=6,sigma.x = sigma, conf.level=0.95)
print(test.new)
## 
##  One-sample z-Test
## 
## data:  x
## z = -2.3985, p-value = 0.008232
## alternative hypothesis: true mean is less than 6
## 95 percent confidence interval:
##        NA 5.950775
## sample estimates:
## mean of x 
##  5.843333

It gives the same p-value and same conclusion — reject null.

Power function

Now we define the power function for one-sided Z-test.

z.power.oneside <- function(n){
  return(pnorm(-qnorm(0.95) - (5.8-6)/(sigma/sqrt(n))))
}
z.power.oneside(100)
## [1] 0.8037649

The power of 100 samples at \(\mu=5.8\) is 0.803.

Sample Size Determination

We use the closed-form to find the minimum sample size for a true mean of \(5.8\) to be tested with power 0.8.

n.oneside = ceiling((sigma * (qnorm(0.95) - qnorm(0.2)) / (5.8 - 6.0))**2)
print(n.oneside)
## [1] 99

The minimum sample size for one-sided Z-test is 99.