-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path04-multivariate.Rmd
More file actions
341 lines (273 loc) · 10 KB
/
Copy path04-multivariate.Rmd
File metadata and controls
341 lines (273 loc) · 10 KB
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# Multi-response Models {#multivariate}
```{r, echo=FALSE, message=FALSE,warning=FALSE}
rm(list=ls())
library(dplyr)
library(flair)
library(lme4)
library(MCMCglmm)
library(scales)
library(squidSim)
library(knitr)
set.seed(25)
```
We can simulate multiple response variables, that covary at different hierarchical levels. For example, we might have two phenotypes, body mass and behaviour, that covary at the between individual and within individual (residual) levels. In the case of such a simple random effects model, we have a covariance matrix at each level:
<!-- Anne: perhaps add a short sentence of introduction here such as “We simulate here no longer one phenotype y varying across I individuals, but a number of phenotypes that (co)vary across individuals..”
-->
$$
\boldsymbol{y}_{ij} = \boldsymbol{\beta}_0 + \boldsymbol{u}_j + \boldsymbol{\epsilon}_{ij}
$$
$$
\boldsymbol{u}_i \sim \mathcal{N}(0, \Sigma_u)
$$
$$
\boldsymbol{\epsilon}_{i} \sim \mathcal{N}(0, \Sigma_{\epsilon})
$$
$$
\Sigma_u = \begin{bmatrix}
\sigma^2_{u_1} & \sigma_{u_1u_2} \\
\sigma_{u_1u_2} & \sigma^2_{u_2}
\end{bmatrix}
,
\Sigma_{\epsilon} = \begin{bmatrix}
\sigma^2_{\epsilon_1} & \sigma_{\epsilon_1\epsilon_2} \\
\sigma_{\epsilon_1\epsilon_2} & \sigma^2_{\epsilon_2}
\end{bmatrix}
$$
We can indicate that there are multiple phenotypes within the parameter list using the `n_response` argument. If we have $q$ response variables, `vcov` now needs to either be a vector of length $q$ (the variances, if we assume the covariances are 0) or a $q*q$ covariance matrix. So below, we simulate 2 response variables, with a covariance between them at both individual and residual levels.
```{r}
squid_data <- simulate_population(
data_structure=make_structure(structure = "individual(100)",repeat_obs=10),
n_response = 2,
parameters=list(
individual = list(
vcov = matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE)
),
residual = list(
vcov = matrix(c(1,0.5,0.5,1),nrow = 2,ncol = 2,byrow=TRUE)
)
)
)
```
We haven't specified any names (of responses or predictors). By default, `simulate_population()` will add a number to the default name to indicate which reponse variable it refers to, so here we have `y1` and `y2` for the response variable, and `individual_effect1` and `individual_effect2` etc.
```{r}
data <- get_population_data(squid_data)
head(data)
```
We can name the response variables easily, by giving the `response_name` argument a vector of names
```{r}
squid_data <- simulate_population(
data_structure=make_structure(structure = "individual(100)",repeat_obs=10),
n_response = 2,
response_name = c("body_mass","behaviour"),
parameters=list(
individual = list(
vcov = matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE)
),
residual = list(
vcov = matrix(c(1,0.5,0.5,1),nrow = 2,ncol = 2,byrow=TRUE)
)
)
)
data <- get_population_data(squid_data)
head(data)
```
## Predictors affecting multiple responses
If we look a little at what `simulate_population()` assumes underneath with the formulation above (just random effects), we can understand more how we simulate predictors that affect multiple response variable. In the above code, we are essentially simulating a predictor for each trait (`individual_effect1` and `individual_effect2`) with some covariance between them.
We can expand the equation above:
$$\boldsymbol{y}_{ij} = \boldsymbol{\beta}_0 + \boldsymbol{u}_j B_u + \boldsymbol{\epsilon}_{ij}B_{\epsilon}$$
$$
B_u = \begin{bmatrix}
1 & 0 \\
0 & 1
\end{bmatrix}
,
B_{\epsilon} = \begin{bmatrix}
1 & 0 \\
0 & 1
\end{bmatrix}
$$
to include matrices of $\beta$s, $B$, the columns of which refer to the response variable, and the rows predictors. In this case they are all identity matrices, which essentially controlling which predictors affects which response ($u_1$ affects $y_1$ but not $y_2$ and vice versa). Internally, `simulate_population()` does the same thing, and assigns `beta` as an identity matrix.
```{r}
squid_data <- simulate_population(
data_structure= make_structure(structure = "individual(100)",repeat_obs=10),
n_response=2,
response_name = c("body_mass","behaviour"),
parameters=list(
individual = list(
vcov =matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE),
beta= diag(2)
),
residual = list(
vcov =matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE),
beta= diag(2)
)
)
)
```
How is this helpful? Well now we could simulate one (or many) predictor(s) that both responses. In the form of an equation we could have
$$\boldsymbol{y}_{ij} = \boldsymbol{\beta}_0 + \boldsymbol{x}_{i} B_x + \boldsymbol{u}_j + \boldsymbol{\epsilon}_{ij}$$
$$\boldsymbol{x}_i \sim \mathcal{N}(\boldsymbol{\mu}_x, \Sigma_x)$$
$$\boldsymbol{u}_i \sim \mathcal{N}(0, \Sigma_u)$$
$$\boldsymbol{\epsilon}_{i} \sim \mathcal{N}(0, \Sigma_{\epsilon})$$
where $B$ is a $p*q$ matrix, where $p$ is number of predictors. So if we returned to our original example in Section \@ref(linearmod), we have three predictors at the observation level - temperature, rainfall and wind. So $B_x$ would be a `3*2` matrix, with 3 predictors and two responses.
<!--
https://stackoverflow.com/questions/63007496/how-to-create-an-editable-matrix-in-shiny-app
make little shiny app that allows you to enter diagonal and
-->
```{r}
Beta <- matrix(c(
0.5, -0.1,
0.2, -0.2,
0.3, -0.1
),nrow=3,ncol=2,byrow=TRUE)
Beta
```
So here, the environment variables all positively affect body mass (response 1) and negatively affect behaviour (response 2). This then slots easily into our code.
```{r, eval=TRUE}
squid_data <- simulate_population(
data_structure= make_structure(structure = "individual(100)",repeat_obs=20),
n_response=2,
parameters= list(
individual = list(
vcov =matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE)
),
observation = list(
names = c("temperature", "rainfall", "wind"),
beta= Beta
),
residual = list(
vcov= matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE)
)
)
)
data <- get_population_data(squid_data)
head(data)
# library(MCMCglmm)
# mod <- MCMCglmm(cbind(y1,y2)~1,random=~us(trait):individual, rcov=~us(trait):units,data=data,family=rep("gaussian",2),verbose=FALSE)
# summary(mod)
```
Equally if we want an interaction, we now have to expand the size of what we give to `beta`, with one $\beta$ for each response, in a matrix, with $q$ columns.
```{r, eval=TRUE}
squid_data <- simulate_population(
data_structure= make_structure(structure = "individual(100)",repeat_obs=20),
n_response=2,
parameters= list(
individual = list(
vcov =matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE)
),
observation = list(
names = c("temperature", "rainfall", "wind"),
beta= Beta
),
interactions = list(
names = c("temperature:rainfall"),
beta=matrix(c(0.1,-0.3),ncol=2,byrow=TRUE)
),
residual = list(
vcov= matrix(c(1,0.5,0.5,1),nrow=2,ncol=2,byrow=TRUE)
)
)
)
data <- get_population_data(squid_data)
head(data)
# library(MCMCglmm)
# mod <- MCMCglmm(cbind(y1,y2)~1,random=~us(trait):individual, rcov=~us(trait):units,data=data,family=rep("gaussian",2),verbose=FALSE)
# summary(mod)
```
## One response repeatedly measured, the other not
In some circumstances we might want to simulate two responses, one that varies between measurements and one that doesn't. For example we might have one fixed measurement of body size for each individual, and repeated measurements of behaviour. We can simply set the variance of the singly measured variable to 0 at that particular level. So for this example:
```{r}
squid_data <- simulate_population(
data_structure= make_structure(structure = "individual(100)",repeat_obs=20),
n_response = 2,
parameters=list(
individual = list(
vcov = matrix(c(
1,0.5,
0.5,1
),nrow=2,ncol=2,byrow=TRUE)
),
residual = list(
vcov = c(0.8,0)
)
)
)
data <- get_population_data(squid_data)
```
## Different distributions
```{r}
individual <- list(
vcov = matrix(c(
1,0.5,
0.5,1
),nrow=2,ncol=2,byrow=TRUE)
)
residual <- list(
vcov = matrix(c(
1,0.5,
0.5,1
),nrow = 2,ncol = 2,byrow=TRUE),
beta = matrix(c(
1,0,
0,0
),nrow = 2,ncol = 2,byrow=TRUE)
)
squid_data <- simulate_population(
data_structure= make_structure(structure = "individual(100)",repeat_obs=20),
n_response = 2,
parameters=list(individual = individual, residual = residual),
family=c("gaussian","binomial"), link=c("identity","logit")
)
data <- get_population_data(squid_data)
head(data,20)
data <- get_population_data(squid_data)
```
## Multivariate Random Slopes
Before reading this it is worth checking out how to simulate univariate random slopes in Section \@ref(randomslopes).
Here we have to think about the beta matrix. As we saw in an example above, in multivariate models beta can be thought of as switching on and off predictor variables for the response variables. We we can simulate 4 variables, an intercept and slope for each variable, and then use the beta matrix to tell `simulate_population` which response variable they link to
```{r}
individual <- list(
names = c("ind_int1","ind_slope1","ind_int2","ind_slope2"),
vcov = matrix(c(
1, 0.5, 0, 0,
0.5, 1, 0, 0,
0, 0, 1, 0.2,
0, 0, 0.2, 1
),nrow=4,ncol=4, byrow=TRUE),
beta = matrix(c(
1, 0,
0, 0,
0, 1,
0, 0
),nrow = 4,ncol = 2, byrow=TRUE)
)
observation <- list(
names="environment",
beta=matrix(c(0.5,-0.3), ncol=2,byrow=TRUE)
)
residual <- list(
vcov = matrix(c(
1,0.5,
0.5,1
),nrow = 2,ncol = 2,byrow=TRUE)
)
interactions <- list(
names=c("ind_slope1:environment","ind_slope2:environment"),
beta= matrix(c(
1,0,
0,1
), ncol=2,byrow=TRUE)
)
squid_data <- simulate_population(
data_structure = make_structure(structure = "individual(100)",repeat_obs=20),
n_response = 2,
parameters=list(
individual = individual,
observation = observation,
residual = residual,
interactions = interactions
)
)
data <- get_population_data(squid_data)
head(data,20)
```