A hypothesis test for a population mean when the population standard deviation, \(\sigma\), is unknown is conducted in the same way as if the population standard deviation is known. The only difference is that the ** t-distribution** is invoked, instead of the standard normal distribution (\(z\)-distribution).

For a test with null hypothesis \(H_0:\; \mu = \mu_0\), the test statistic, \(t\), is calculated as

\[t = \frac{\bar x - \mu_0}{s/\sqrt{n}}\]

This hypothesis testing procedure is called **one-mean t-test** or simply

Similar to the proceeding section we showcase the **critical value approach** first, and then, in a second step we repeat the analysis for the ** p-value approach**. However, this time we wrap up the critical value approach within a self-build function. For the

`t.test()`

.Let us build a function called `simple.ttest()`

. The function takes as input arguments a vector `x`

(sample data), `mu0`

, which corresponds to \(\mu_0\), the population average to test against, the specified significance level \(\alpha\), denominated as `alpha`

, and the method of the *t*-test, `left`

, `right`

, or the default value `two-sided`

, with the function argument named `method`

. The output of the function is a Boolean, `TRUE`

or `FALSE`

. If `TRUE`

, \(H_0\) is rejected , if `FALSE`

, \(H_0\) is not rejected.

```
simple.ttest <- function(x, mu0, alpha, method='two-sided'){
n <- length(x)
xbar <- mean(x)
s <- sd(x)
# calculate test statistic
tstat <- (xbar-mu0)/(s/sqrt(n))
# calculate critical value
df <- n-1
# for left-tailed test
if (method=='left'){
crit.val <- qt(p = 0.05, df = df, lower.tail = TRUE)
#evaluate rejection region
if (tstat < crit.val){
reject = TRUE
} else{
reject = FALSE
}
}
# for right-tailed test
else if (method=='right'){
crit.val <- qt(p = alpha, df = df, lower.tail = FALSE)
#evaluate rejection region
if (tstat > crit.val){
reject = TRUE
} else {
reject = FALSE
}
}
# for two-sided test (default)
else {
crit.val <- qt(p = alpha/2, df = df, lower.tail = FALSE)
#evaluate rejection region
if (abs(tstat) > abs(crit.val) | -abs(tstat) < -abs(crit.val)){
reject = TRUE
} else{
reject = FALSE
}
}
# print out summary and evaluation
print(paste('Significance level:',alpha))
print(paste('Degrees of freedom:',df))
print(paste('Test statistic:',round(tstat,4)))
print(paste('Critical value:',round(crit.val,4)))
print(paste('Reject H0:',reject))
}
```

A great piece of code :-)

Now it is time to test our `simple.ttest()`

function. Therefore we redo the example of the previous section. We use the *students* data set. You may download the `students.csv`

file here. Import the data set and assign a proper name to it.

`students <- read.csv("https://userpage.fu-berlin.de/soga/200/2010_data_sets/students.csv")`

The *students* data set consists of 8239 rows, each of them representing a particular student, and 16 columns, each of them corresponding to a variable/feature related to that particular student. These self-explaining variables are: *stud.id, name, gender, age, height, weight, religion, nc.score, semester, major, minor, score1, score2, online.tutorial, graduated, salary*.

We examine the average weight of a random sample of students from the *students* data set and compare it to the average weight of all Europeans adults. Walpole et al. (2012) published data on the average body mass (kg) per region, including Europe. They report the average body mass for the European adult population to be 70.8 kg. We therefore set \(\mu_0\), the population mean accordingly (\(\mu_0 = 70.8\)). Further, we take a random sample (`x`

) with a sample size of \(n=9\). The sample consists of the weights in kg of 9 randomly picked students from the *students* data set.

```
mu0 <- 70.8
n <- 9
x <- sample(x = students$weight, size = n)
```

**Step 1: State the null hypothesis \(H_0\) and alternative hypothesis \(H_A\)**

The null hypothesis states that the average weight of students equals the average weight of European adults as reported by Walpole et al. (2012). In other words there is no difference in the mean weight of students and the mean weight of European adults.

\[H_0: \quad \mu = 70.8 \]

Recall, that the formulation of the alternative hypothesis dictates if we apply a two-sided, a left tailed or a right tailed hypothesis test.

**Alternative hypothesis 1** \[H_{A_1}: \quad \mu \ne 70.8 \] results in a two-sided hypothesis test.

**Alternative hypothesis 2** \[H_{A_2}: \quad \mu < 70.8 \] results in a left tailed hypothesis test, and

**Alternative hypothesis 3** \[H_{A_3}: \quad \mu > 70.8 \] results in a right tailed hypothesis test.

**Step 2: Decide on the significance level, \(\alpha\)**

\[\alpha = 0.05\]

`alpha <- 0.05`

**Step 3, 4 and 5: Compute the value of the test statistic, determine the critical value, and evaluate the value of the test statistic. If it falls in the rejection region, reject \(H_0\); otherwise, do not reject \(H_0\)**

Now our self-build function `simple.ttest()`

comes into play. We feed to the function a random sample, in form of a vector, a value for \(\mu_0\), a significance level, \(\alpha\), and the method (`two-sided`

, `left`

or `right`

). Recall that `two-sided`

is the default value, thus if we do not specify any method, the function will apply the two-sided hypothesis test.

`simple.ttest(x, mu0, alpha)`

```
## [1] "Significance level: 0.05"
## [1] "Degrees of freedom: 8"
## [1] "Test statistic: 0.8706"
## [1] "Critical value: 2.306"
## [1] "Reject H0: FALSE"
```

Cool! ;-)

A right-tailed *t*-test

`simple.ttest(x, mu0, alpha, method = 'right')`

```
## [1] "Significance level: 0.05"
## [1] "Degrees of freedom: 8"
## [1] "Test statistic: 0.8706"
## [1] "Critical value: 1.8595"
## [1] "Reject H0: FALSE"
```

A left-tailed *t*-test

`simple.ttest(x, mu0, alpha, method = 'left')`

```
## [1] "Significance level: 0.05"
## [1] "Degrees of freedom: 8"
## [1] "Test statistic: 0.8706"
## [1] "Critical value: -1.8595"
## [1] "Reject H0: FALSE"
```

**Step 6: Interpret the result of the hypothesis test.**

If the test statistic and thus the sample mean is that extreme, so that it falls beyond the critical value, and thus falls into the rejection region we conclude that at the 5% significance level, the data does provide sufficient evidence to reject \(H_0\). In contrast, if the test statistic and thus the sample mean falls in the non-rejection region we conclude that the data does not provide evidence to reject \(H_0\).

The second approach is based on the assignment of a probability to the value of the test statistic. If the test statistic is very extreme, given the null hypothesis is true, a low probability will be assigned to the test statistic. In contrast if the test statistic is not extreme at all, the probability assigned to it will be much higher. That probability is called ** p-value**.

In order to calculate the exact *p*-value for a given numeric value we rely on software, as the “look-up-in-table-method” is somehow tedious, as not all numerical values of the test statistic are given in such a table. This causes rounding errors. However, the R programming language provides a very powerful machinery to perform *t*-tests. The generic function is called `t.test()`

. You may go for more details by typing `help(t.test)`

into your console. Although the function provides various arguments, that particular *t*-test in which we are interest right now, **testing one population mean when \(\sigma\) is unknown**, is quite straight forward.

Let us redo the same problem as in the previous section, using the already defined variables. Recall, the sample is a vector of weights (`x`

), \(\mu_0 = 70.8\), given as `mu0`

, \(n = 9\), given as `n`

, and \(\alpha= 0.05\), given as `alpha`

. Using this information we apply the `t.test()`

function for a two-sided *t*-test by typing `t.test(x = x, mu = mu0, alpha = alpha, alternative = 'two.sided')`

into the R console.

```
# set parameter
mu0 <- 70.8
alpha <- 0.05
n <- 9
x <- sample(x = students$weight, size = n)
# call t.test() function
t.test(x = x, mu = mu0, alpha = alpha, alternative = 'two.sided')
```

```
##
## One Sample t-test
##
## data: x
## t = 0.23959, df = 8, p-value = 0.8167
## alternative hypothesis: true mean is not equal to 70.8
## 95 percent confidence interval:
## 63.90017 79.29983
## sample estimates:
## mean of x
## 71.6
```

Wow! R conducts a hypothesis test in one line of code and gives additional information for free! Let us go through the output of the `t.test()`

function.

- The first line is the header, reminding us of the method we used:
*One Sample t-test*.

- The second line tells us which sample data was used:
*x*.

- The third line lists the results of the calculations for the test statistic
*t*, the degrees or freedom*df*, and the*p-value*:*t*= 0.2395901,*df*= 8,*p-value*= 0.8166726.

- The fourth line reminds us on the alternative hypothesis we used. In our case it was
*two.sided*. Try by your own to change the attribute to “greater” or “less”, in order to implement different alternative hypothesis.

- The fifth and sixth line contain the \(100(1-0.05)\)% confidence interval.

- The last three lines contain information about the sample, in this case the sample mean is given: 71.6.

It is worth noting that the `t.test()`

function creates an object, a `list`

, containing the results of the *t*-test. Thus, if we store the results of the `t.test()`

function in a variable, we can access the result by regular indexing.

```
out <- t.test(x = x, mu = mu0, alpha = alpha, alternative = 'two.sided')
str(out)
```

```
## List of 9
## $ statistic : Named num 0.24
## ..- attr(*, "names")= chr "t"
## $ parameter : Named num 8
## ..- attr(*, "names")= chr "df"
## $ p.value : num 0.817
## $ conf.int : num [1:2] 63.9 79.3
## ..- attr(*, "conf.level")= num 0.95
## $ estimate : Named num 71.6
## ..- attr(*, "names")= chr "mean of x"
## $ null.value : Named num 70.8
## ..- attr(*, "names")= chr "mean"
## $ alternative: chr "two.sided"
## $ method : chr "One Sample t-test"
## $ data.name : chr "x"
## - attr(*, "class")= chr "htest"
```

To retrieve the *p*-value we type

`out$p.value`

`## [1] 0.8166726`