Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
---
title: "Lab-8-T-tests-with-Code"
date: "9/14/2019"
output:
html_document:
toc: TRUE
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## Overall Progression for Lab 8:
1. Load Packages and Data
a. Overview of the Data
2. Independent T-test
a. Assumptions
i. Outcomes are continuous
ii. Normality
iii. Variances are equal across groups (independent t-test only)
iv. Outcome independence (independent t-test only)
b. Running it
c. Reporting Results
2. Dependent T-test
a. Assumptions
i. Outcomes are continuous
ii. Normality
b. Running it
c. Reporting Results
## Load Data and Packages
For this lab, we will be using the tidyverse for data manipulation and graphing as well as car for leveneTest
```{r Load Packages}
library(pastecs)
library(car)
library(tidyverse)
theme_set(theme_bw())
```
The data we will be using is stored in "T-test.RData" and has 2 dataframes, sniff.ind and sniff.dep. These have 2 columns in each, group and time.
- `group` (factor, 2 levels): which group the mouse is a part of. Either control or anesthetic treatment (Sevo) for sniff.ind, or familiar or novel for sniff.dep
- `time` (numeric): time spent sniffing another mouse
This would be a couple examples of different socialization experiments. Does an anaesthetic cause a difference in sniff time of another mouse (independent t-test in this case)? Also, does sniff time depend on familiarity with another mouse (dependent in this case)?
```{r Load the Data}
load("/Users/Matt/Google Drive/Grad School/GR 770 Statistics/R Labs/Data/T-test.RData")
```
## Independent Student T-test
An independent t-test tests a single variable across between-subjects groups. For our purposes here, we want to see whether time spent sniffing novel mice differed across groups
### Independent T-Test Assumptions
Like all of our statistical tests, there are assumptions we should cover for t-tests. Some only apply to independent t-tests while others apply to both paired and independent tests.
#### Continuous Outcome
The first assumption is the easiest to test: is our outcome continuous? We measured time, time is continuous, we measured it in a continuous fashion, so it's continuous. Done
#### Normality
We are going to test normality in the same way as before with both graphs and statistical tests. Remember that we are looking at normality within groups, not on the whole
##### Histograms
We will create histograms of `time` split by `group` in `sniff.ind` and look to see if there is obvious skew anywhere.
```{r hist time ind}
ggplot(sniff.ind, aes(x = time, fill = group)) +
geom_histogram(bins = 7, color = "black") +
facet_wrap(~group, scales = "free")
```
Both groups looks fairly normal overall.
##### Q-Q Plots
We will now do the same thing with Q-Q plots
```{r qq time ind}
ggplot(sniff.ind,aes(sample = time)) +
geom_qq() +
geom_qq_line() +
facet_wrap(~group, scales = "free")
```
Everything looks great, the data are pretty much all on the diagonal
##### Boxplots
```{r boxplot novel ind}
ggplot(sniff.ind, aes(x = group, y = time)) +
geom_boxplot()
```
Both boxplots look very evenly distributed. Nothing to worry about from any of the graphs
##### Statistical Test
Remembering we need to test normality across groups, we can use the function `tapply` to calculate the normality metrics with `stat.desc` across our two groups. `tapply` has the following form:
`tapply(data, group_var,func, ...)`
- `data`: vector of data to apply the function to
- `group_var`: a factor variable that describes which group each element in `data` belongs to
- `func`: name of the function to apply to each group
- `...`: options to pass to `func`
We can calculate the normality stats for `time` in each group using `tapply` like so:
```{r tapply time ind}
tapply(sniff.ind$time, sniff.ind$group, stat.desc, norm = TRUE, basic = FALSE)
```
Skewness metrics for both groups are within the -0.5 to 0.5 boundary, skew.2SE does not approach our small sample size rule of thumb of 1.58 in either group. The SW tests came out non-significant for both groups as well.
Overall there is no reason to worry about the normality of our data, everything came out as we wanted it to.
#### Homogeneity of Variance
We only need to do Levene's Test for independent samples, so we will do that here just to make sure variances are equal across both of our groups
```{r levene time ind}
leveneTest(time ~ group, sniff.ind)
```
The test came out non-significant so there is not a significant difference in variance between Control and Sevo groups
#### Independence of Outcomes
The mice were different, therefore our outcomes are independent. There we go
### Doing the T-Test
The simplest test is the independent t-test. It tests if two independent groups have different means. It is performed using the `t.test` function from the `stats` package. A two-sample t.test has a couple of forms:
Form 1:
`t.test(formula, data, paired = FALSE, var.equal = FALSE)`
- `formula`: formula describing the independent variable being tested as a function of a grouping variable
- `data`: the dataset containing the variables
- `paired`: a binary value saying whether it is a paired t-test (FALSE by default)
- `var.equal`: says whether the variances of the group should be treated as equal (FALSE by default).
Form 2:
`t.test(x, y = NULL, paired = FALSE, var.equal = FALSE)`
- `x`: data corresponding to the distribution being tested
- `y`: second sample to test `x` against if it is a two-sample t-test. NULL by default, so `t.test` is a one sample test by default
As a reminder, a Student's t-test assumes equal variances across groups whereas a Welch's t-test assumes unequal variances. So `t.test` is a Welch's t-test by default. Since we previously tested for equal variances using Levene's test, we will need to set the `var.equal` option to `TRUE`
So first, let's use the first form to test whether the control and sevo groups had different sniff times overall
```{r two-sample independent}
t.test(time ~ group, data = sniff.ind, var.equal = TRUE)
```
You get a nice table out with the t-statistic, degrees of freedom, and p-value as well as the 95% conf. interval and the means of each group. We see a highly significant difference in sniff times between the Control and Sevo groups
### Reporting a t-test result
You can report this t-test in the following manner:
On average, the control mice had longer sniff times ($\bar{x}$ = 49.7) than mice in the Sevo group ($\bar{x}$ = 34.1). This difference between the means was significant (t(58) = 11.587, p < 2.2e-16); this represents a large effect of 2.99
**NOTE**: do not worry about how to calculate effect size just yet, that will be done later in the semester
## Dependent T-test
We are now going to be switching to the `sniff.dep` dataframe for the next test. The second type of t-test is within-subject, or paired. It is performed in almost the exact same fashion as an independent-sample t-test, except paired is set to TRUE. For this t-test, each sample has to have the exact same number of data points and they need to be in the same order. The way this works is that the samples will be subtracted and then compared to a normal distribution. So data cannot be mixed up in the same way it could for an independent t-test.
### Assumptions of Dependent T-tests
There are fewer assumptions we need to care about for the dependent T-test, just continuous outcomes and normality
#### Continuous Outcomes
Our outcome is still time, therefore still continuous.
#### Normality
To test normality in the dependent t-test, the differences between the distributions are going to be tested, not the original distributions themselves. In order to easily create a difference variable, we should first spread the data to get `familiar` and `novel` into different columns. Then we can do a straight subtraction of the columns from there.
We will need to create an ID number for each mouse beforehand for `spread` to work, but that's ok. We can do that easily, knowing that the mice were ordered 1:30
```{r spread sniff.dep}
sniff.dep$ID <- as.factor(c(seq(1,30),seq(1,30)))
sniff.dep.s <- spread(sniff.dep, key = group, value = time)
```
From here, we can make a new column, `time.diff`, equal to `novel` - `familiar`.
```{r time.diff}
sniff.dep.s$time.diff <- sniff.dep.s$novel - sniff.dep.s$familiar
```
##### Histograms
Now we just need to make a single histogram of `time.diff`
```{r hist time dep}
ggplot(sniff.dep.s, aes(x = time.diff)) +
geom_histogram(bins = 15, color = "black")
```
There is a single outlier, but the distribution looks normal enough otherwise
##### Q-Q Plots
We will now do the same thing with Q-Q plots
```{r qq time dep}
ggplot(sniff.dep.s ,aes(sample = time.diff)) +
geom_qq() +
geom_qq_line()
```
Most everything looks great, the data are pretty much all on the diagonal other than that single huge outlier at the top. A single outlier isn't a cause for concern here considering the other points are nicely aligned
##### Boxplots
```{r boxplot novel dep}
ggplot(sniff.dep.s, aes(y = time.diff)) +
geom_boxplot()
```
The boxplot looks fairly even. The median is square in the center of the IQR and the whiskers are equal enough, although the 1st quartile whisker is definitely longer. The outlier is still there, but there isn't much to do about it.
##### Statistical Test
We just need to use stat.desc to run our tests of normality on time.diff like normal
```{r tapply time dep}
stat.desc(sniff.dep.s$time.diff, norm = TRUE, basic = FALSE)
```
So immediately, we notice that skewness is > 1 and the SW test is significant indicating significantly skewed data. However, these metrics can both be influenced by large outliers. In this situation, given the presence of that single huge outlier, I put more stock in the graphs than the statistical tests. The graphs, outside of that single outlier all point towards having a normal distribution.
### Running the Dependent T-test
Using the original dataframe, we have within subject variable of `group`. So using form 1 of t-test, we can test `time` as a function of `group`
#### Form 1
```{r dependent 1}
t.test(time ~ group, data = sniff.dep, paired = TRUE, var.equal = TRUE)
```
So we can see that the difference in time sniffed between the types of mice being sniffed is significantly different.
#### Form 2
We now have separate columns for `familiar` and `novel` we can pass directly into the t.test function
```{r dependent 2}
t.test(x = sniff.dep.s$novel, y = sniff.dep.s$familiar, paired = TRUE, var.equal = TRUE)
```
We could also just pass in the `time.diff` column to the x variable and compare to a standard normal distribution since that is what is happening anyway
```{r dependent 3}
t.test(x = sniff.dep.s$time.diff)
```
You can see that the stats are exactly the same, except multiplied by -1, which is good. The reason that all the numbers have been multiplied by -1 is because Form 1 subtracted novel from familiar as opposed to the other way around that we did both when creating `time.diff` and putting `novel` in x and `familiar` in y. Knowing your contrast is extremely important for interpreting the result. In this case, we have a positive significant difference from Form 2 where we are using the formula `novel-familiar`. Since our t value is positive, it indicates that novel is significantly larger than familiar.
In general, form 1 is easier when the group designation is in a single column and form 2 is better when the samples are either in different columns of a dataframe or in different variables altogether.
### Reporting the Result
We can report the result in the following way:
On average, ssniff times for familiar mice ($\bar{x}$ = 28.3 seconds, SD = 4.97) were shorter than for novel mice ($\bar{x}$ = 44.9 seconds, SD = 4.97). This difference, -16.57, was significant (t(29) = -11.438, p = 2.876e-12); this represents a large effect of 2.088.