4 Within-and-between partner SAM
As discussed and demonstrated in the previous chapters (2 & 3), within partner variation allows for modelling the temporal dynamics of social interactions, including intrinsic and residual trait feedback, while between partner variation can be used to partition the effects of assortment and social plasticity. Study designs providing both within and between partner measurements will, therefore, tend to be optimally informative about phenotypic interactions and their evolutionary consequences.
The formal model for a between-and-within partner SAM combines the basic latent ARMA feedback process of the within partner SAM (Ch 2) with the within-individual centering used to remove bias from the SRN slopes of the between partner SAM (Ch 3). The model for a measurement \(i\) of aggression \(z_{ijt}\) in focal individual \(j\) during a single interaction period \(t\) is given by
\[z_{ijt} = \mu_0 + \eta_{Wijt} + \beta_{B}\eta_{Bijt} + \xi_{ijt}\]
where \(\eta_{Wijt}\) is the within-individual centered plastic response to the social partner SRN trait value
\[\eta_{Wijt} = \begin{Bmatrix} \mu_j + \left( \psi_1 + \psi_j \right) \left( \mu_k' - \bar{\mu}'_K \right) & \mathrm{if} \ t = 1 \\ \mu_j + \left( \psi_1 + \psi_j \right) \left( \eta_{ikt-1}' - \bar{\eta}'_{iKt-1} \right) & \mathrm{else} \end{Bmatrix} \]
with \(\beta_{B}\eta_{Bijt}\) reflecting the association with the average partner SRN trait value
\[\eta_{Bijt} = \begin{Bmatrix} \left( \psi_1 + \psi_j \right) \bar{\mu}'_K & \mathrm{if} \ t = 1 \\ \left( \psi_1 + \psi_j \right) \bar{\eta}'_{iKt-1} & \mathrm{else} \end{Bmatrix} \]
scaled by the between partner regression coefficient \(\beta_{B}\). In addition, \(\xi_{ijt}\) captures SRN measurement error caused by residual feedback over time
\[\xi_{ijt} = \begin{Bmatrix} \epsilon_{ijt} & \mathrm{if} \ t = 1 \\ \epsilon_{ijt} + \phi\epsilon_{ikt-1}' & \mathrm{else} \end{Bmatrix} \]
Similarly, for the social partner
\[z_{ikt}' = \mu_0 + \eta_{Wikt}' + \beta_B\eta_{Bikt}' + \xi_{ikt}'\] \[\eta_{Wikt}' = \begin{Bmatrix} \mu_k' + \left( \psi_1 + \psi_k' \right)\left( \mu_j - \bar{\mu}_J \right) & \mathrm{if} \ t = 1 \\ \mu_k' + \left( \psi_1 + \psi_k' \right)\left( \eta_{ijt} - \bar{\eta}_{iJt} \right) & \mathrm{else} \end{Bmatrix} \]
\[\eta_{Bikt}' = \begin{Bmatrix} \left( \psi_1 + \psi_k' \right) \bar{\mu}_J & \mathrm{if} \ t = 1 \\ \left( \psi_1 + \psi_k' \right) \bar{\eta}_{iJt} & \mathrm{else} \end{Bmatrix} \]
\[\xi_{ikt}' = \begin{Bmatrix} \epsilon_{ikt}' & \mathrm{if} \ t = 1 \\ \epsilon_{ikt}' + \phi\epsilon_{ijt-1} & \mathrm{else} \end{Bmatrix} \]
The random effects are assumed to be well-described by multivariate normal distributions. \[\mu_j = \mu_{\mathrm{A}j} + \mu_{\mathrm{E}j}, \quad \psi_j = \psi_{\mathrm{A}j} + \psi_{\mathrm{E}j}\] \[\mu_k' = \mu_{\mathrm{A}k}' + \mu_{\mathrm{E}j}', \quad \psi_k' = \psi_{\mathrm{A}k}' + \psi_{\mathrm{E}k}'\]
\[\begin{bmatrix} \boldsymbol{\mu_{\mathrm{A}}}, \boldsymbol{\mu'_{\mathrm{A}}},\boldsymbol{\psi_{\mathrm{A}}},\boldsymbol{\psi}'_{\mathrm{A}} \end{bmatrix}^{\mathrm{T}} \sim \mathrm{MVNormal}(\boldsymbol{0}, \boldsymbol{\mathrm{G}} \otimes \boldsymbol{\mathrm{A}} ) \] \[\begin{bmatrix} \boldsymbol{\mu_{\mathrm{E}}}, \boldsymbol{\mu'_{\mathrm{E}}},\boldsymbol{\psi_{\mathrm{E}}},\boldsymbol{\psi}'_{\mathrm{E}} \end{bmatrix}^{\mathrm{T}} \sim \mathrm{MVNormal}(\boldsymbol{0}, \boldsymbol{\mathrm{E}} \otimes \boldsymbol{\mathrm{I}} ) \] \[\begin{bmatrix} \boldsymbol{\epsilon}, \boldsymbol{\epsilon}' \end{bmatrix}^{\mathrm{T}} \sim \mathrm{MVNormal}(\boldsymbol{0}, \boldsymbol{\mathrm{\Sigma}} ) \] We also assume that the social reaction norm (SRN) intercept and slope (co)variances are equivalent for focal (\(\boldsymbol{\mu},\boldsymbol{\psi}\)) and social partners (\(\boldsymbol{\mu}',\boldsymbol{\psi}'\)). The \(\boldsymbol{G}\) matrix can therefore be reduced to a 2x2 matrix for all individuals in the population
\[\boldsymbol{\mathrm{G}}= \begin{bmatrix} \mathrm{var([\boldsymbol{\mu},\boldsymbol{\mu}'])} & \mathrm{cov([\boldsymbol{\mu},\boldsymbol{\mu}'],[\boldsymbol{\psi},\boldsymbol{\psi}'])} \\ \mathrm{cov([\boldsymbol{\psi},\boldsymbol{\psi}'],[\boldsymbol{\mu},\boldsymbol{\mu}'])} & \mathrm{var([\boldsymbol{\psi},\boldsymbol{\psi}'])} \end{bmatrix}\]
The residual matrix \(\boldsymbol{\Sigma}\) estimates the association among focal and social partners’ residuals.
\[\boldsymbol{\Sigma}= \begin{bmatrix} \mathrm{var(\boldsymbol{\epsilon})} & \mathrm{cov}(\boldsymbol{\epsilon},\boldsymbol{\epsilon}') \\ \mathrm{cov}(\boldsymbol{\epsilon}',\boldsymbol{\epsilon}) & \mathrm{var(\boldsymbol{\epsilon'})} \end{bmatrix}\] This model is, therefore, appropriate for situations where the distinction between focal and partner is semi-arbitrary, e.g. when measuring within-sex interactions or when males and females exhibit similar patterns of phenotypic variation. In this case, we make the latter assumption for simplicity. To account for differences between the responses of focal individuals and social partners, the model can simply be extended with additional parameters, e.g. specifying separate \(G_M\) and \(G_F\) matrices for males and female respective genetic (co)variances and so on.
4.1 Simulate data
We can simulate data from this model using the custom pedfun()
function introduced in Ch. 1.5, as well by integrating the basic simulation approach outlined in the previous SAM chapters for repeated interactions with partners (Ch. 2) as well as across partners (Ch. 3).
We assume that interactions occur with 4 lifetime partners with two measurements per individual within each dyad. This empirical information allows us to more effectively partition within and between dyad variation.
library(mvtnorm)
#common settings
= 4 #partners/individual
I_partner = 2 #observations/individual/seasonal partner
I_obs = I_partner*I_obs #samples/individual
I_sample
#population properties
=300 #total individuals for simulation
I=400
popmin=600
popmax= 10
ngenerations <-sample(popmin:popmax, ngenerations, replace=TRUE) #N / generation
nids= sample(seq(0.15, 0.25,by=0.05),1) #extra-pair mating
epm = sample(seq(0.4,0.6,by=0.05),1) #proportion of non-breeding / generation
nonb
#relatedness matrix
<- pedfun(popmin=popmin, popmax=popmax, ngenerations=ngenerations,
A_mat epm=epm, nonb=nonb, nids=nids, I=I, missing=FALSE)
#####################################################################
#Parameter values
#####################################################################
= 0 #global intercept
alpha_0 = 0.5 #population interaction coefficient
psi_1 = 0.5 #residual feedback coefficient (epsilon_j ~ epsilon_t-1k)
phi = 0.3 #standard deviation of SRN intercepts
SD_intercept = 0.3 #SD of SRN slopes
SD_slope = 0.3 #assortment coefficient (expressed as correlation)
r_alpha = 0.3 #genetic correlation of random intercepts and slopes
r_G = 0.3 #environmental correlation
r_E = -0.3 #residual effect correlation (epsilon_tj = epsilon_tk)
r_R = 0.3 #genetic variance of REs
V_G = 0.3 #genetic variance of REs
V_E = 1
res_V
#Random effect correlations
<- matrix(c(1,r_G,r_G,1), nrow=2, ncol=2) #mu_A, beta_A
G_cor <- c(sqrt(V_G),sqrt(V_G)) #G effect sds
G_sd <- diag(G_sd) %*% G_cor %*% diag(G_sd)
G_cov
<- matrix(c(1,r_E,r_E,1), nrow=2, ncol=2) #mu_E, beta_E
E_cor <- c(sqrt(V_E),sqrt(V_E)) #E effect sds
E_sd <- diag(E_sd) %*% E_cor %*% diag(E_sd)
E_cov
#matrices
<- G_cov %x% A_mat
G_block <- E_cov %x% diag(1,I)
E_block
#generate correlated REs
<- rmvnorm(1, mean=rep(0,I*2), sigma=G_block)
Gvalues = data.frame(matrix(Gvalues, nrow=I, ncol=2))
G_val cor(G_val)
## X1 X2
## X1 1.0000000 0.3003963
## X2 0.3003963 1.0000000
<- rmvnorm(1, mean=rep(0,I*2), sigma=E_block)
Evalues = data.frame(matrix(Evalues, nrow=I, ncol=2))
E_val cor(E_val)
## X1 X2
## X1 1.0000000 0.3394947
## X2 0.3394947 1.0000000
#combine temporary object for all SRN parameters
#use shorthand mu = 0, psi = 1
= cbind(G_val,E_val)
P colnames(P) = c("A0", "A1", "E0", "E1")
#individual phenotypic REs
#use shorthand mu = 0, psi = 1
$P0 = P$A0 + P$E0
P$P1 = P$A1 + P$E1
P
#add ID
$ID = seq(1:I) P
The structure of dyads is sampled to match the expected SRN intercept correlation among individuals and their social partners. For this simulation, we assume that partners assort on their SRN slopes rather than intercepts. This is of course arbitrary but allows us to directly assess how well the model can partition within- and between-individual sources of partner covariation. After determining the dyads and organizing their trait values, the data frame is then expanded to account for multiple observations with the same social partner.
library(dplyr)
library(MASS)
= list()
pairs for (j in 1:I_partner){
#male additive genetic RN slopes (x I_partner for multiple lifetime partners)
<- data.frame(P1_m = P$P1[1:(I/2)], ID_m = (1:(I/2)) )
sort.m <-sort.m[order(sort.m[,"P1_m"]),]
sort.m#female phenotypic RN slopes
<- data.frame(P1_f = P$P1[(I/2 + 1):I], ID_f = ((I/2+1):I) )
sort.f <-sort.f[order(sort.f[,"P1_f"]),]
sort.f#generate random dataset with desired rank-order correlation
<- matrix(r_alpha, ncol = 2, nrow = 2) #cor of male and female values
temp_mat diag(temp_mat) <- 1 #cor matrix
#sim values
<-MASS::mvrnorm(n = I/2, mu = c(0, 0), Sigma = temp_mat, empirical=TRUE)
temp_data1#ranks of random data
<- rank(temp_data1[ , 1], ties.method = "first")
rm <- rank(temp_data1[ , 2], ties.method = "first")
rf #induce cor through rank-ordering of RN vectors
cor(sort.m$P1_m[rm], sort.f$P1_f[rf])
#sort partner ids into dataframe
= data.frame(ID_m = sort.m$ID_m[rm], ID_f = sort.f$ID_f[rf])
partner.id = partner.id[order(partner.id[,"ID_m"]),]
partner.id #add to list
= partner.id
pairs[[j]]
}
= bind_rows(pairs)
partner.id order(partner.id$ID_m),] partner.id[
## ID_m ID_f
## 1 1 220
## 151 1 285
## 301 1 280
## 451 1 215
## 2 2 179
## 152 2 281
## 302 2 182
## 452 2 165
## 3 3 152
## 153 3 164
## 303 3 230
## 453 3 274
## 4 4 198
## 154 4 212
## 304 4 165
## 454 4 249
## 5 5 231
## 155 5 196
## 305 5 238
## 455 5 291
## 6 6 270
## 156 6 297
## 306 6 154
## 456 6 192
## 7 7 265
## 157 7 256
## 307 7 269
## 457 7 273
## 8 8 251
## 158 8 163
## 308 8 195
## 458 8 250
## 9 9 167
## 159 9 188
## 309 9 222
## 459 9 241
## 10 10 300
## 160 10 264
## 310 10 265
## 460 10 168
## 11 11 254
## 161 11 205
## 311 11 168
## 461 11 272
## 12 12 267
## 162 12 189
## 312 12 232
## 462 12 271
## 13 13 258
## 163 13 243
## 313 13 194
## 463 13 197
## 14 14 226
## 164 14 193
## 314 14 293
## 464 14 200
## 15 15 273
## 165 15 236
## 315 15 258
## 465 15 187
## 16 16 203
## 166 16 180
## 316 16 196
## 466 16 265
## 17 17 227
## 167 17 162
## 317 17 276
## 467 17 240
## 18 18 280
## 168 18 253
## 318 18 208
## 468 18 193
## 19 19 284
## 169 19 204
## 319 19 216
## 469 19 214
## 20 20 228
## 170 20 192
## 320 20 278
## 470 20 184
## 21 21 233
## 171 21 287
## 321 21 209
## 471 21 199
## 22 22 292
## 172 22 223
## 322 22 191
## 472 22 170
## 23 23 283
## 173 23 217
## 323 23 274
## 473 23 248
## 24 24 271
## 174 24 276
## 324 24 184
## 474 24 201
## 25 25 277
## 175 25 280
## 325 25 251
## 475 25 233
## 26 26 214
## 176 26 181
## 326 26 158
## 476 26 267
## 27 27 287
## 177 27 270
## 327 27 153
## 477 27 210
## 28 28 163
## 178 28 245
## 328 28 256
## 478 28 224
## 29 29 185
## 179 29 201
## 329 29 248
## 479 29 208
## 30 30 221
## 180 30 262
## 330 30 229
## 480 30 180
## 31 31 219
## 181 31 184
## 331 31 246
## 481 31 247
## 32 32 200
## 182 32 246
## 332 32 268
## 482 32 152
## 33 33 243
## 183 33 214
## 333 33 239
## 483 33 295
## 34 34 246
## 184 34 177
## 334 34 205
## 484 34 289
## 35 35 256
## 185 35 296
## 335 35 202
## 485 35 167
## 36 36 188
## 186 36 238
## 336 36 177
## 486 36 194
## 37 37 223
## 187 37 293
## 337 37 295
## 487 37 154
## 38 38 162
## 188 38 154
## 338 38 211
## 488 38 260
## 39 39 186
## 189 39 186
## 339 39 291
## 489 39 296
## 40 40 229
## 190 40 179
## 340 40 299
## 490 40 190
## 41 41 266
## 191 41 295
## 341 41 180
## 491 41 268
## 42 42 201
## 192 42 161
## 342 42 292
## 492 42 157
## 43 43 218
## 193 43 241
## 343 43 171
## 493 43 221
## 44 44 295
## 194 44 237
## 344 44 215
## 494 44 195
## 45 45 232
## 195 45 151
## 345 45 201
## 495 45 204
## 46 46 257
## 196 46 249
## 346 46 281
## 496 46 236
## 47 47 171
## 197 47 231
## 347 47 218
## 497 47 172
## 48 48 285
## 198 48 203
## 348 48 188
## 498 48 169
## 49 49 168
## 199 49 247
## 349 49 159
## 499 49 163
## 50 50 176
## 200 50 224
## 350 50 152
## 500 50 287
## 51 51 215
## 201 51 242
## 351 51 264
## 501 51 234
## 52 52 225
## 202 52 267
## 352 52 212
## 502 52 198
## 53 53 154
## 203 53 213
## 353 53 203
## 503 53 292
## 54 54 260
## 204 54 250
## 354 54 253
## 504 54 262
## 55 55 235
## 205 55 197
## 355 55 284
## 505 55 225
## 56 56 196
## 206 56 173
## 356 56 176
## 506 56 245
## 57 57 240
## 207 57 278
## 357 57 226
## 507 57 160
## 58 58 255
## 208 58 288
## 358 58 273
## 508 58 253
## 59 59 151
## 209 59 248
## 359 59 279
## 509 59 239
## 60 60 279
## 210 60 220
## 360 60 163
## 510 60 171
## 61 61 269
## 211 61 251
## 361 61 161
## 511 61 283
## 62 62 262
## 212 62 263
## 362 62 285
## 512 62 183
## 63 63 252
## 213 63 239
## 363 63 186
## 513 63 174
## 64 64 297
## 214 64 244
## 364 64 167
## 514 64 222
## 65 65 204
## 215 65 282
## 365 65 242
## 515 65 202
## 66 66 182
## 216 66 272
## 366 66 252
## 516 66 188
## 67 67 184
## 217 67 229
## 367 67 164
## 517 67 213
## 68 68 197
## 218 68 208
## 368 68 200
## 518 68 166
## 69 69 166
## 219 69 286
## 369 69 236
## 519 69 277
## 70 70 286
## 220 70 294
## 370 70 287
## 520 70 246
## 71 71 164
## 221 71 230
## 371 71 206
## 521 71 217
## 72 72 155
## 222 72 153
## 372 72 254
## 522 72 151
## 73 73 157
## 223 73 259
## 373 73 297
## 523 73 191
## 74 74 192
## 224 74 165
## 374 74 272
## 524 74 235
## 75 75 153
## 225 75 207
## 375 75 190
## 525 75 294
## 76 76 222
## 226 76 275
## 376 76 179
## 526 76 182
## 77 77 205
## 227 77 299
## 377 77 277
## 527 77 270
## 78 78 290
## 228 78 255
## 378 78 266
## 528 78 196
## 79 79 178
## 229 79 254
## 379 79 169
## 529 79 158
## 80 80 244
## 230 80 209
## 380 80 290
## 530 80 237
## 81 81 238
## 231 81 174
## 381 81 189
## 531 81 299
## 82 82 190
## 232 82 195
## 382 82 227
## 532 82 276
## 83 83 156
## 233 83 210
## 383 83 183
## 533 83 282
## 84 84 263
## 234 84 157
## 384 84 244
## 534 84 161
## 85 85 216
## 235 85 182
## 385 85 289
## 535 85 178
## 86 86 165
## 236 86 194
## 386 86 192
## 536 86 173
## 87 87 242
## 237 87 269
## 387 87 162
## 537 87 298
## 88 88 234
## 238 88 211
## 388 88 262
## 538 88 266
## 89 89 206
## 239 89 199
## 389 89 249
## 539 89 275
## 90 90 264
## 240 90 290
## 390 90 275
## 540 90 203
## 91 91 272
## 241 91 232
## 391 91 187
## 541 91 205
## 92 92 180
## 242 92 258
## 392 92 257
## 542 92 261
## 93 93 282
## 243 93 279
## 393 93 255
## 543 93 257
## 94 94 291
## 244 94 187
## 394 94 225
## 544 94 216
## 95 95 195
## 245 95 265
## 395 95 223
## 545 95 212
## 96 96 261
## 246 96 292
## 396 96 217
## 546 96 259
## 97 97 187
## 247 97 234
## 397 97 288
## 547 97 162
## 98 98 169
## 248 98 202
## 398 98 219
## 548 98 300
## 99 99 241
## 249 99 178
## 399 99 231
## 549 99 219
## 100 100 230
## 250 100 222
## 400 100 175
## 550 100 256
## 101 101 211
## 251 101 226
## 401 101 178
## 551 101 175
## 102 102 158
## 252 102 268
## 402 102 198
## 552 102 254
## 103 103 177
## 253 103 235
## 403 103 210
## 553 103 263
## 104 104 181
## 254 104 216
## 404 104 250
## 554 104 229
## 105 105 217
## 255 105 277
## 405 105 263
## 555 105 251
## 106 106 288
## 256 106 152
## 406 106 243
## 556 106 279
## 107 107 213
## 257 107 215
## 407 107 160
## 557 107 185
## 108 108 294
## 258 108 198
## 408 108 166
## 558 108 232
## 109 109 193
## 259 109 191
## 409 109 259
## 559 109 258
## 110 110 202
## 260 110 257
## 410 110 270
## 560 110 207
## 111 111 259
## 261 111 169
## 411 111 240
## 561 111 255
## 112 112 173
## 262 112 266
## 412 112 228
## 562 112 179
## 113 113 208
## 263 113 261
## 413 113 247
## 563 113 293
## 114 114 207
## 264 114 233
## 414 114 286
## 564 114 156
## 115 115 170
## 265 115 190
## 415 115 245
## 565 115 238
## 116 116 275
## 266 116 155
## 416 116 261
## 566 116 227
## 117 117 250
## 267 117 271
## 417 117 221
## 567 117 177
## 118 118 239
## 268 118 200
## 418 118 185
## 568 118 297
## 119 119 183
## 269 119 185
## 419 119 204
## 569 119 220
## 120 120 189
## 270 120 175
## 420 120 234
## 570 120 181
## 121 121 160
## 271 121 160
## 421 121 237
## 571 121 231
## 122 122 247
## 272 122 159
## 422 122 170
## 572 122 176
## 123 123 209
## 273 123 227
## 423 123 207
## 573 123 285
## 124 124 174
## 274 124 167
## 424 124 197
## 574 124 230
## 125 125 159
## 275 125 283
## 425 125 214
## 575 125 223
## [ reached 'max' / getOption("max.print") -- omitted 100 rows ]
#put all dyads together
$dyadn = seq(1:nrow(partner.id))
partner.id
#add values back to dataframe (male and joint)
$P0m <- P$P0[match(partner.id$ID_m,P$ID)]
partner.id$P0f <- P$P0[match(partner.id$ID_f,P$ID)]
partner.id$P1m <- P$P1[match(partner.id$ID_m,P$ID)]
partner.id$P1f <- P$P1[match(partner.id$ID_f,P$ID)]
partner.id
$A0m <- P$A0[match(partner.id$ID_m,P$ID)]
partner.id$A0f <- P$A0[match(partner.id$ID_f,P$ID)]
partner.id$A1m <- P$A1[match(partner.id$ID_m,P$ID)]
partner.id$A1f <- P$A1[match(partner.id$ID_f,P$ID)]
partner.id
$E0m <- P$E0[match(partner.id$ID_m,P$ID)]
partner.id$E0f <- P$E0[match(partner.id$ID_f,P$ID)]
partner.id$E1m <- P$E1[match(partner.id$ID_m,P$ID)]
partner.id$E1f <- P$E1[match(partner.id$ID_f,P$ID)]
partner.id
#calculate mean partner phenotype for each subject
#average female for male partners
<- aggregate(P0f ~ ID_m, mean, data = partner.id)
mean_0m names(mean_0m)[2] <- "meanP0m"
<- aggregate(P1f ~ ID_m, mean, data = partner.id)
mean_1m names(mean_1m)[2] <- "meanP1m"
$meanP0m <- mean_0m$meanP0m[match(partner.id$ID_m,mean_0m$ID_m)]
partner.id$meanP1m <- mean_1m$meanP1m[match(partner.id$ID_m,mean_1m$ID_m)]
partner.id
#average male for female partners
<- aggregate(P0m ~ ID_f, mean, data = partner.id)
mean_0f names(mean_0f)[2] <- "meanP0f"
<- aggregate(P1m ~ ID_f, mean, data = partner.id)
mean_1f names(mean_1f)[2] <- "meanP1f"
$meanP0f <- mean_0f$meanP0f[match(partner.id$ID_f,mean_0f$ID_f)]
partner.id$meanP1f <- mean_1f$meanP1f[match(partner.id$ID_f,mean_1f$ID_f)]
partner.id
#number of dyads
= nrow(partner.id)
ndyad
#expand for repeated measures
$rep <- I_obs
partner.id<- partner.id[rep(row.names(partner.id), partner.id$rep),]
pair_df
#correlations
cor(partner.id$P0m, partner.id$P0f)
## [1] 0.05302799
cor(partner.id$P1m, partner.id$P0f)
## [1] -0.01685785
cor(partner.id$P0m, partner.id$P1f)
## [1] 0.11546
cor(partner.id$P1m, partner.id$P1f)
## [1] 0.3003677
The responses can now be sampled. Rather than directly within-individual centering responses and specifying the between-partner regression coefficient \(\beta_{B}\) in the simulation, we assume partners respond to the total SRN trait value of their partner. Therefore, we expect \(\beta_{B}=1\).
#####################################################################
#Additional effects
#####################################################################
#correlated residuals between male and females
<- matrix(c(1,r_R,r_R,1), nrow=2, ncol=2)
R_cor <- sqrt(res_V)
res_sd <- diag(c(res_sd,res_sd)) %*% R_cor %*% diag(c(res_sd,res_sd))
R_cov <-data.frame(rmvnorm(nrow(pair_df), c(0,0), R_cov))
res_ind$resAGm = res_ind$X1
pair_df$resAGf = res_ind$X2
pair_df
#####################################################################
#Simulate responses over t = {1,2} per partner
#####################################################################
#add interaction number
$turn = rep(c(1,2),ndyad)
pair_df
#average male social environment at time = 1
$turn==1,"meaneta_m"] = pair_df[pair_df$turn==1,"meanP0m"] +
pair_df[pair_df+ pair_df[pair_df$turn==1,"meanP1m"])*(pair_df[pair_df$turn==1,"P0m"])
(psi_1
#average female social environment at time = 1
$turn==1,"meaneta_f"] = pair_df[pair_df$turn==1,"meanP0f"] +
pair_df[pair_df+ pair_df[pair_df$turn==1,"meanP1f"])*(pair_df[pair_df$turn==1,"P0f"])
(psi_1
#individual prediction at t = 1
#males
#eta_j{t=1} = mu_j + psi_j*(mu_k - mu_meanK)
$turn==1,"eta_m"] = pair_df[pair_df$turn==1,"P0m"] +
pair_df[pair_df+ pair_df[pair_df$turn==1,"P1m"])*(pair_df[pair_df$turn==1,"P0f"])
(psi_1 #females
#eta_k{t=1} = mu_k + psi_k*(mu_j - mu_meanJ)
$turn==1,"eta_f"] = pair_df[pair_df$turn==1,"P0f"] +
pair_df[pair_df+ pair_df[pair_df$turn==1,"P1f"])*(pair_df[pair_df$turn==1,"P0m"])
(psi_1
#individual prediction at t = 2
#eta_j{t=2} = mu_j + psi_j*(eta_k{t=1} - eta_meanK{t=1})
$turn==2,"eta_m"] = pair_df[pair_df$turn==2,"P0m"] +
pair_df[pair_df+ pair_df[pair_df$turn==2,"P1m"])*(pair_df[pair_df$turn==1,"eta_f"])
(psi_1
#females
$turn==2,"eta_f"] = pair_df[pair_df$turn==2,"P0f"] +
pair_df[pair_df+ pair_df[pair_df$turn==2,"P1f"])*(pair_df[pair_df$turn==1,"eta_m"])
(psi_1
#add intercept and residual
$AG_m = alpha_0 + pair_df$eta_m + pair_df$resAGm
pair_df$AG_f = alpha_0 + pair_df$eta_f + pair_df$resAGf
pair_df
#add residual feedback
$turn==2,"AG_m"] = pair_df[pair_df$turn==2,"AG_m"] + phi * pair_df[pair_df$turn==1,"resAGf"]
pair_df[pair_df$turn==2,"AG_f"] = pair_df[pair_df$turn==2,"AG_f"] + phi * pair_df[pair_df$turn==1,"resAGm"] pair_df[pair_df
This data frame is combined with indices of male and female IDs in a list for Stan.
#####################################################################
#Prepare data for Stan
#####################################################################
#individual indices
= I/2 #number of males
Im = I/2 #number of females
If = (I/2)*2*4 #total observations per sex
N_sex <-pair_df$ID_m #male ID
idm<-pair_df$ID_f #female ID
idf<-idf - (Im) #index within female vector
idf
#partner IDs for male individuals
<-data.frame(idfocal = rep(1:(I/2)), #all partners ID
partners_mpartner1 = NA, partner2 = NA, partner3 = NA, partner4 = NA)
for(i in 1:(I/2)){partners_m[i,c(2:5)] <-partner.id[partner.id$ID_m==i,"ID_f"]}
#partner IDs for female individuals
<-data.frame(idfocal = rep((I/2+1):I), #all partners ID
partners_fpartner1 = NA, partner2 = NA, partner3 = NA, partner4 = NA)
for(i in (I/2+1):I){partners_f[i-(I/2),c(2:5)] <-partner.id[partner.id$ID_f==i,"ID_m"]}
######################
#data prep for Stan
<-
stan_data list(N_sex = N_sex, I = I, Im=Im, If = If, idm = idm, idf = idf,
partners_m = partners_m, partners_f = partners_f,
AG_m = pair_df$AG_m, AG_f = pair_df$AG_f, time = pair_df$turn, A = A_mat)
4.2 Estimate the model
The within and between partner model code extends the within individual centered, between partner model to account for longitudinal feedback effects within dyads. These changes are accomplished in the parameters
as well as the model
program blocks. In the latter, a conditional statement is added to account for the effects on \(\eta_{ijt}\) and \(\eta'_{ikt}\) at \(t=1\) and \(t>1\), and similarly for the residual feedback effects \(\xi_j\) and \(\xi'_k\).
write("
data {
//indices and scalars used for model specification
int<lower=1> N_sex; //total aggression observations per sex (I/2 * 4 lifetime partners)
int<lower=0> I; //total individuals (M + F)
int<lower=0> Im; //number of males
int<lower=0> If; //number of females
int<lower=1> idm[N_sex]; //index of male AG observations (of length N_sex)
int<lower=1> idf[N_sex]; //index of female AG observations
int<lower=1> partners_m [Im,5]; //index of male partner IDs, first column is focal ID (1 + 4 IDs)
int<lower=1> partners_f [If,5]; //index of female partner IDs, first column is focal ID (1 + 4 IDs)
//empirical data
matrix[I,I] A; //relatedness matrix
real AG_m[N_sex]; //male aggression measurements
real AG_f[N_sex]; //female aggression measurements
real time[N_sex]; //time index (=1 for all measures)
}
transformed data{
matrix[I,I] LA = cholesky_decompose(A); //lower-triangle A matrix
}
parameters {
//population effects
real alpha_0; //aggression global intercept
real psi_1; //expected interaction coefficient
real beta_B; //between partner effect
real<lower=-1,upper=1> phi; //(-1,1) ensures unique solution
//random effects (standard deviations)
vector<lower=0, upper = 1>[2] sd_P; //phenotypic SRN mu & psi SDs
vector<lower=0, upper = 1>[2] sd_R; //male & female residual SDs
cholesky_factor_corr[2] LG; //genetic SRN correlations
cholesky_factor_corr[2] LE; //permanent environmental SRN correlations
cholesky_factor_corr[2] LR; //sex-specific residual correlations
matrix[I,2] std_devG; //individual-level unscaled G SRN deviations
matrix[I,2] std_devE; //individual-level unscaled E SRN deviations
//SRN heritability parmameters, i.e. Var(G_RN) / Var(P_RN)
//see supplementary appendix SI for further explanation of this parameter
vector<lower=0,upper=1>[2] SRN_h2;
}
transformed parameters {
vector<lower=0>[2] sd_G; //SDs of G effects (derived from sd_P)
vector<lower=0>[2] sd_E; //SDs of E effects (derived from sd_P)
matrix[I,2] SRN_P; //scaled P SRN parameter deviations
matrix[I,2] SRN_G; //scaled G SRN parameter deviations
matrix[I,2] SRN_E; //scaled E SRN parameter deviations
matrix[If, 2] partner_meanm; //average SRN parameters of males' partners
matrix[Im, 2] partner_meanf; //average SRN parameters of females' partners
//standard deviations of genetic effects
//simplified from sqrt ( total RN phenotype variance * h2 )
sd_G[1] = sd_P[1] * sqrt(SRN_h2[1]); //genetic SD for RN intercepts
sd_G[2] = sd_P[2] * sqrt(SRN_h2[2]); //genetic SD for RN slopes
//standard deviations of environmental effects (total phenotype SD * proportion environment SD)
sd_E[1] = sd_P[1] * sqrt(1 - SRN_h2[1]); //environment SD for RN intercepts
sd_E[2] = sd_P[2] * sqrt(1 - SRN_h2[2]); //environment SD for RN slopes
//matrix normal parameterization of Kronecker product between G and A
SRN_G = LA * std_devG * diag_pre_multiply(sd_G, LG)' ;
//non-centered parameterization of permanent environmental effects
SRN_E = std_devE * diag_pre_multiply(sd_E, LE)';
//phenotypic RN effects (P = G + E); here G = additive genetic effects
SRN_P = SRN_G + SRN_E;
//calculate the mean SRN parameters of each male's lifetime partners
for(i in 1:Im) partner_meanm[i] = [mean(col(SRN_P[partners_m[i,2:5]],1)),
mean(col(SRN_P[partners_m[i,2:5]],2))];
//calculate the mean SRN parameters of each female's lifetime partners
for(i in 1:If) partner_meanf[i] = [mean(col(SRN_P[partners_f[i,2:5]],1)),
mean(col(SRN_P[partners_f[i,2:5]],2))];
}
model{
//separate male and female vectors for efficiency
matrix[Im,2] SRN_Pm = SRN_P[1:Im]; //male SRN phenotypic deviations
matrix[If,2] SRN_Pf = SRN_P[(Im+1):I]; //female SRN phenotypic deviations
//separate SRN intercepts and slopes (phenotypic deviations)
vector[Im] mu_m = col(SRN_Pm,1); //SRN intercepts
vector[If] mu_f = col(SRN_Pf,1);
vector[Im] psi_m = col(SRN_Pm,2); //SRN slopes
vector[If] psi_f = col(SRN_Pf,2);
//separate mean partner SRN intercepts and slopes (deviations)
vector[Im] mu_meanm = col(partner_meanm,1); //mean partner SRN intercept for males
vector[If] mu_meanf = col(partner_meanf,1); //...for females
vector[Im] psi_meanm = col(partner_meanm,2); //mean partner SRN slope for males
vector[If] psi_meanf = col(partner_meanf,2); //...for females
//initialize vectors for constructing individual-centered linear predictors
vector[N_sex] eta_Wm; //within-individual centered male SRN trait value
vector[N_sex] eta_Wf; //within-individual centered female SRN trait value
vector[N_sex] eta_Bm; //individual male SRN trait value toward average partner
vector[N_sex] eta_Bf; //individual female SRN trait toward average partner
vector[N_sex] eta_meanm; //average SRN partner values for males
vector[N_sex] eta_meanf; //average SRN partner values for females
vector[N_sex] linpred_m; //expected value for male responses
vector[N_sex] linpred_f; //expected value for female responses
vector[N_sex] epsilon_m; //residuals for male responses
vector[N_sex] epsilon_f; //residuals for male responses
//Male and female aggression response model
for (n in 1:N_sex) {
//SRN trait values
//assumes that n = 1 in the context of an ongoing social interaction
//if n = 1 prior to social context, then specify eta[t=1] = mu_j instead
if (time[n]==1)
{
//within-individual centered eta
//male eta[t=1] = mu_j + psi_j*(mu_k - mu_meanK)
eta_Wm[n] = mu_m[idm[n]] + (psi_1 + psi_m[idm[n]])*(mu_f[idf[n]] - mu_meanm[idm[n]]) ;
//female eta[t=1] = mu_k + psi_k*(mu_j - mu_meanJ)
eta_Wf[n] = mu_f[idf[n]] + (psi_1 + psi_f[idf[n]])*(mu_m[idm[n]] - mu_meanf[idf[n]]);
//average individual eta
//male eta[t=1] = mu_j + psi_j*mu_k
eta_Bm[n] = (psi_1 + psi_m[idm[n]])*mu_meanm[idm[n]];
//female eta[t=1] = mu_k + psi_k*mu_j
eta_Bf[n] = (psi_1 + psi_f[idf[n]])*mu_meanf[idf[n]];
//average partner eta[t=1]
//average eta males' partners [t=1] = mu_meanK + psi_meanK*mu_j
eta_meanm[n] = mu_meanm[idm[n]] + (psi_1 + psi_meanm[idm[n]])*mu_m[idm[n]];
//average eta females' partners [t=1] = mu_meanJ + psi_meanJ*mu_k
eta_meanf[n] = mu_meanf[idf[n]] + (psi_1 + psi_meanf[idf[n]])*mu_f[idf[n]];
}
else
{
//within-individual centered eta
//male eta[t=2] = mu_j + psi_j*(eta_k[t=1] - eta_meanK[t=1])
eta_Wm[n] = mu_m[idm[n]] + (psi_1 + psi_m[idm[n]])*(eta_Wf[n-1] - eta_meanm[n-1]);
//female eta[t=2] = mu_k + psi_k*(eta_j[t=1] - eta_meanJ[t=1])
eta_Wf[n] = mu_f[idf[n]] + (psi_1 + psi_f[idf[n]])*(eta_Wm[n-1] - eta_meanf[n-1]);
//average individual eta
//male average eta[t=2] = mu_j + psi_j*eta_meanK[t=1]
eta_Bm[n] = (psi_1 + psi_m[idm[n]])*eta_meanm[n-1];
//female average eta[t=2] = mu_k + psi_k*eta_meanJ[t=1]
eta_Bf[n] = (psi_1 + psi_f[idf[n]])*eta_meanf[n-1];
//average eta males' partners [t=1] = mu_meanK + psi_meanK*mean eta_j[t-1]
eta_meanm[n] = mu_meanm[idm[n]] + (psi_1 + psi_meanm[idm[n]])*(mu_m[idm[n]] + eta_Bm[n-1]);
//female average partner eta
eta_meanf[n] = mu_meanf[idf[n]] + (psi_1 + psi_meanf[idf[n]])*(mu_f[idf[n]] + eta_Bf[n-1]);
}
//add global intercept and between-individual parameters to linear predictor
//other fixed effects can also be added here
linpred_m[n] = alpha_0 + eta_Wm[n] + beta_B*eta_Bm[n]; //+beta_B*eta_Bm[n]
linpred_f[n] = alpha_0 + eta_Wf[n] + beta_B*eta_Bf[n]; //+beta_B*eta_Bf[n]
//residual trait values
if(time[n]==1)
{
epsilon_m [n] = AG_m[n] - linpred_m[n];
epsilon_f [n] = AG_f[n] - linpred_f[n];
}
else
{
linpred_m[n] = linpred_m[n] + phi * epsilon_f[n-1];
epsilon_m[n] = AG_m[n] - linpred_m[n];
linpred_f[n] = linpred_f[n] + phi * epsilon_m[n-1];
epsilon_f[n] = AG_f[n] - linpred_f[n];
}
//correlated residuals between partners
[epsilon_m[n],epsilon_f[n]]' ~ multi_normal_cholesky([0,0], diag_pre_multiply(sd_R, LR));
}
//model priors
//fixed effects
alpha_0 ~ std_normal();
psi_1 ~ std_normal();
beta_B ~ std_normal();
phi ~ std_normal();
//random effects
to_vector(sd_P) ~ cauchy(0,1);
to_vector(sd_R) ~ cauchy(0,1);
LG ~ lkj_corr_cholesky(2);
LE ~ lkj_corr_cholesky(2);
LR ~ lkj_corr_cholesky(2);
to_vector(std_devG) ~ std_normal();
to_vector(std_devE) ~ std_normal();
//reaction norm heritability
to_vector(SRN_h2) ~ beta(1.2,1.2);
}
generated quantities{
//cor and cov matrices of SRN parameters and residuals
matrix[2,2] Gcor = LG * LG'; //G SRN correlation matric
matrix[2,2] Ecor = LE * LE'; //E SRN correlation matric
matrix[2,2] Rcor = LR * LR'; //residual correlation matrix
matrix[2,2] Rcov = diag_matrix(sd_R)*Rcor*diag_matrix(sd_R); //residual covariance
matrix[2,2] Gcov = diag_matrix(sd_G)*Gcor*diag_matrix(sd_G); //G SRN covariance
matrix[2,2] Ecov = diag_matrix(sd_E)*Ecor*diag_matrix(sd_E); //E SRN covariance
matrix[2,2] Pcov = Gcov + Ecov; //P SRN covariance
matrix[2,2] Pcor = inverse(diag_matrix(sd_P))*Pcov*inverse(diag_matrix(sd_P)); //P SRN correlation
//variances
vector<lower=0>[2] V_P = sd_P .* sd_P;
vector<lower=0>[2] V_G = sd_G .* sd_G;
vector<lower=0>[2] V_E = sd_E .* sd_E;
vector<lower=0>[2] V_R = sd_R .* sd_R;
}", "sam3_3w.stan")
Depending on the sample size set during the simulation, this model will likely take 30+ min to finish sampling. The total number of iterations can be reduced to save time, but is set to a large value here to ensure sufficient effective sample sizes for some parameters.
library(rstan)
.3 = stan_model("sam3_3w.stan")
sam_3
.3 <- sampling(sam_3.3, data=stan_data, init = 0, warmup=1500, iter = 3000,
stan_results3chains=4, cores=4, control=list(adapt_delta=0.90) )
library(bayesplot)
mcmc_areas(stan_results3.3, pars = c( "psi_1", "beta_B", "V_P[1]", "V_P[2]", "Gcor[2,1]", "Ecor[2,1]", "Rcor[2,1]",
"Pcor[2,1]", "SRN_h2[1]", "SRN_h2[2]"), prob = 0.9 )
The model seems to be doing well overall, detecting the negative population SRN slope (-0.5) as well as approximating the locaiton of the total phenotypic variance of SRN intercepts and slopes (0.6), the phenotypic correlation between SRN parameters (0.3), the SRN heritability of intercepts and slopes (0.5), and the expected between partner regresson coefficient (1).
4.3 Estimating assortment
The mean partner intrinsic trait values calculated in the model can then be used to estimate the assortment coefficient of interest \(\beta_{{\bar{\psi}'}\psi}\), as well as the broader assortment matrix \(\boldsymbol{B_{\alpha}}\). We can directly calculate the quantities of the assortment matrix using the vectors of mean partner SRN parameters that we constructed and estimated with the Stan model. In this case, we’re also interesting in estimating the expected assortment within any particular breeding season, under the assumption that variation in assortment coefficients between seasons is random. To do this, we need to scale the (co)variances of interest appropriately for the expected variance of a single partner, rather than the mean of multiple partners. If the intrinsic SRN parameter values of social partners are independent Gaussian variables, then the expected variance for a single partner phenotype \(\alpha'_k\) can be derived from the variance of the mean phenotype of the set of \(K\) partners such that
\[\mathrm{var}\left({\alpha'_k} \right) = \mathrm{var} \left( \bar{\alpha}_K \right)*n \] Conversely, we can derive the expected variance of the mean of \(n\) partners by dividing through the expected variance of a single partner \(\mathrm{var} \left( \bar{\alpha}_K \right)=\mathrm{var}\left({\alpha'_k} \right) /n\). In this simplified simulation, individuals and their social partners’ SRN parameters are characterized by the same population variances, so we can simply use the expected variance of individual SRN intercepts and slopes, i.e. \(\mathrm{var}(\boldsymbol{\alpha})=\mathrm{var}(\boldsymbol{\alpha'})\), to calculate the expected variance of the mean of \(n\) partner phenotypes. We can then use this variance to transform the vector of mean partner trait values to a standardized scale (i.e. variance = 1, z-scores), and subsequently scale these standardized values to the expected variance of a single partner using \(\mathrm{var}\left({\alpha'_k} \right)\).
#extract posteriors
<- rstan::extract(stan_results3.3)
post
#temporary vectors for assortment coefficients
= post$V_P
SRN_PV = post$sd_P
SRN_Psd = post$V_P / I_partner #expected variance for mean of partners
SRN_PVmean = sqrt(SRN_PVmean) #expected SD for mean of partners
SRN_Psdmean <- post$SRN_P[,,1] #individual intercepts
SRN_focal1 <- post$SRN_P[,,2] #individual slopes
SRN_focal2 <- cbind(post$partner_meanm[,,1], post$partner_meanf[,,1])
SRN_partner1 <- cbind(post$partner_meanm[,,2], post$partner_meanf[,,2])
SRN_partner2
#scale mean partner variance to variance of single partner
= SRN_partner1
SRN_partner1s for(j in 1:nrow(SRN_partner1))
= ( SRN_partner1[j,] / SRN_Psdmean[j,1] ) * SRN_Psd[j,1] }
{SRN_partner1s[j,]
= SRN_partner2
SRN_partner2s for(j in 1:nrow(SRN_partner2))
= ( SRN_partner2[j,] / SRN_Psdmean[j,2] ) * SRN_Psd[j,2] }
{SRN_partner2s[j,]
#assortment matrix
= list()
Beta_alpha
#generate matrices across each posterior sample
for(j in 1:nrow(SRN_focal1))
{= matrix(NA,2,2)
Beta_mat
#mu' ~ mu
1,1] = cov(SRN_focal1[j,], SRN_partner1s[j,])/var(SRN_focal1[j,])
Beta_mat[#mu' ~ psi
2,1] = cov(SRN_focal2[j,], SRN_partner1s[j,])/var(SRN_focal2[j,])
Beta_mat[#psi' ~ mu
1,2] = cov(SRN_focal1[j,], SRN_partner2s[j,])/var(SRN_focal1[j,])
Beta_mat[#psi' ~ psi
2,2] = cov(SRN_focal2[j,], SRN_partner2s[j,])/var(SRN_focal2[j,])
Beta_mat[
= Beta_mat
Beta_alpha[[j]]
}
#extract beta_mu'mu (assortment on SRN intercepts)
= unlist(lapply(Beta_alpha, function(x) x[2,2]))
Beta_psi median(Beta_psi); sum(Beta_psi > 0)/length(Beta_psi)
## [1] 0.270885
## [1] 1
Positive assortment of moderate effect size is detected.
4.4 Phenotypic model
A phenotypic within and between partner model can also be estimated whenever quantitative genetic information is missing.
write("
data {
//indices and scalars used for model specification
int<lower=1> N_sex; //total aggression observations per sex (I/2 * 4 lifetime partners)
int<lower=0> I; //total individuals (M + F)
int<lower=0> Im; //number of males
int<lower=0> If; //number of females
int<lower=1> idm[N_sex]; //index of male AG observations (of length N_sex)
int<lower=1> idf[N_sex]; //index of female AG observations
int<lower=1> partners_m [Im,5]; //index of male partner IDs, first column is focal ID (1 + 4 IDs)
int<lower=1> partners_f [If,5]; //index of female partner IDs, first column is focal ID (1 + 4 IDs)
//empirical data
real AG_m[N_sex]; //male aggression measurements
real AG_f[N_sex]; //female aggression measurements
real time[N_sex]; //time index (=1 for all measures)
}
parameters {
//population effects
real alpha_0; //aggression global intercept
real psi_1; //expected interaction coefficient
real beta_B; //between partner effect
real<lower=-1,upper=1> phi; //(-1,1) ensures unique solution
//no way to partition feedback when t=1
//real<lower=-1,upper=1> phi; //(-1,1) ensures unique solution
//random effects (standard deviations)
vector<lower=0, upper = 1>[2] sd_P; //phenotypic SRN mu & psi SDs
vector<lower=0, upper = 1>[2] sd_R; //male & female residual SDs
cholesky_factor_corr[2] LP; //phenotypic SRN correlations
cholesky_factor_corr[2] LR; //sex-specific residual correlations
matrix[I,2] std_devP; //individual-level unscaled P SRN deviations
}
transformed parameters {
matrix[I,2] SRN_P; //scaled P SRN parameter deviations
matrix[I,2] SRN_G; //scaled G SRN parameter deviations
matrix[I,2] SRN_E; //scaled E SRN parameter deviations
matrix[If, 2] partner_meanm; //average SRN parameters of males' partners
matrix[Im, 2] partner_meanf; //average SRN parameters of females' partners
//non-centered parameterization of phenotypic effects
SRN_P = std_devP * diag_pre_multiply(sd_P, LP)';
//calculate the mean SRN parameters of each male's lifetime partners
for(i in 1:Im) partner_meanm[i] = [mean(col(SRN_P[partners_m[i,2:5]],1)),
mean(col(SRN_P[partners_m[i,2:5]],2))];
//calculate the mean SRN parameters of each female's lifetime partners
for(i in 1:If) partner_meanf[i] = [mean(col(SRN_P[partners_f[i,2:5]],1)),
mean(col(SRN_P[partners_f[i,2:5]],2))];
}
model{
//separate male and female vectors for efficiency
matrix[Im,2] SRN_Pm = SRN_P[1:Im]; //male SRN phenotypic deviations
matrix[If,2] SRN_Pf = SRN_P[(Im+1):I]; //female SRN phenotypic deviations
//separate SRN intercepts and slopes (phenotypic deviations)
vector[Im] mu_m = col(SRN_Pm,1); //SRN intercepts
vector[If] mu_f = col(SRN_Pf,1);
vector[Im] psi_m = col(SRN_Pm,2); //SRN slopes
vector[If] psi_f = col(SRN_Pf,2);
//separate mean partner SRN intercepts and slopes (deviations)
vector[Im] mu_meanm = col(partner_meanm,1); //mean partner SRN intercept for males
vector[If] mu_meanf = col(partner_meanf,1); //...for females
vector[Im] psi_meanm = col(partner_meanm,2); //mean partner SRN slope for males
vector[If] psi_meanf = col(partner_meanf,2); //...for females
//initialize vectors for constructing individual-centered linear predictors
vector[N_sex] eta_Wm; //within-individual centered male SRN trait value
vector[N_sex] eta_Wf; //within-individual centered female SRN trait value
vector[N_sex] eta_Bm; //individual male SRN trait value toward average partner
vector[N_sex] eta_Bf; //individual female SRN trait toward average partner
vector[N_sex] eta_meanm; //average SRN partner values for males
vector[N_sex] eta_meanf; //average SRN partner values for females
vector[N_sex] linpred_m; //expected value for male responses
vector[N_sex] linpred_f; //expected value for female responses
vector[N_sex] epsilon_m; //residuals for male responses
vector[N_sex] epsilon_f; //residuals for male responses
//Male and female aggression response model
for (n in 1:N_sex) {
//SRN trait values
//assumes that n = 1 in the context of an ongoing social interaction
//if n = 1 prior to social context, then specify eta[t=1] = mu_j instead
if (time[n]==1)
{
//within-individual centered eta
//male eta[t=1] = mu_j + psi_j*(mu_k - mu_meanK)
eta_Wm[n] = mu_m[idm[n]] + (psi_1 + psi_m[idm[n]])*(mu_f[idf[n]] - mu_meanm[idm[n]]) ;
//female eta[t=1] = mu_k + psi_k*(mu_j - mu_meanJ)
eta_Wf[n] = mu_f[idf[n]] + (psi_1 + psi_f[idf[n]])*(mu_m[idm[n]] - mu_meanf[idf[n]]);
//average individual eta
//male eta[t=1] = mu_j + psi_j*mu_k
eta_Bm[n] = (psi_1 + psi_m[idm[n]])*mu_meanm[idm[n]];
//female eta[t=1] = mu_k + psi_k*mu_j
eta_Bf[n] = (psi_1 + psi_f[idf[n]])*mu_meanf[idf[n]];
//average partner eta[t=1]
//average eta males' partners [t=1] = mu_meanK + psi_meanK*mu_j
eta_meanm[n] = mu_meanm[idm[n]] + (psi_1 + psi_meanm[idm[n]])*mu_m[idm[n]];
//average eta females' partners [t=1] = mu_meanJ + psi_meanJ*mu_k
eta_meanf[n] = mu_meanf[idf[n]] + (psi_1 + psi_meanf[idf[n]])*mu_f[idf[n]];
}
else
{
//within-individual centered eta
//male eta[t=2] = mu_j + psi_j*(eta_k[t=1] - eta_meanK[t=1])
eta_Wm[n] = mu_m[idm[n]] + (psi_1 + psi_m[idm[n]])*(eta_Wf[n-1] - eta_meanm[n-1]);
//female eta[t=2] = mu_k + psi_k*(eta_j[t=1] - eta_meanJ[t=1])
eta_Wf[n] = mu_f[idf[n]] + (psi_1 + psi_f[idf[n]])*(eta_Wm[n-1] - eta_meanf[n-1]);
//average individual eta
//male average eta[t=2] = mu_j + psi_j*eta_meanK[t=1]
eta_Bm[n] = (psi_1 + psi_m[idm[n]])*eta_meanm[n-1];
//female average eta[t=2] = mu_k + psi_k*eta_meanJ[t=1]
eta_Bf[n] = (psi_1 + psi_f[idf[n]])*eta_meanf[n-1];
//average eta males' partners [t=1] = mu_meanK + psi_meanK*mean eta_j[t-1]
eta_meanm[n] = mu_meanm[idm[n]] + (psi_1 + psi_meanm[idm[n]])*(mu_m[idm[n]] + eta_Bm[n-1]);
//female average partner eta
eta_meanf[n] = mu_meanf[idf[n]] + (psi_1 + psi_meanf[idf[n]])*(mu_f[idf[n]] + eta_Bf[n-1]);
}
//add global intercept and between-individual parameters to linear predictor
//other fixed effects can also be added here
linpred_m[n] = alpha_0 + eta_Wm[n] + beta_B*eta_Bm[n]; //+beta_B*eta_Bm[n]
linpred_f[n] = alpha_0 + eta_Wf[n] + beta_B*eta_Bf[n]; //+beta_B*eta_Bf[n]
//residual trait values
if(time[n]==1)
{
epsilon_m [n] = AG_m[n] - linpred_m[n];
epsilon_f [n] = AG_f[n] - linpred_f[n];
}
else
{
linpred_m[n] = linpred_m[n] + phi * epsilon_f[n-1];
epsilon_m[n] = AG_m[n] - linpred_m[n];
linpred_f[n] = linpred_f[n] + phi * epsilon_m[n-1];
epsilon_f[n] = AG_f[n] - linpred_f[n];
}
//correlated residuals between partners
[epsilon_m[n],epsilon_f[n]]' ~ multi_normal_cholesky([0,0], diag_pre_multiply(sd_R, LR));
}
//model priors
//fixed effects
alpha_0 ~ std_normal();
psi_1 ~ std_normal();
beta_B ~ std_normal();
phi ~ std_normal();
//random effects
to_vector(sd_P) ~ cauchy(0,1);
to_vector(sd_R) ~ cauchy(0,1);
LP ~ lkj_corr_cholesky(2);
LR ~ lkj_corr_cholesky(2);
to_vector(std_devP) ~ std_normal();
}
generated quantities{
//cor and cov matrices of SRN parameters and residuals
matrix[2,2] Pcor = LP * LP'; //P SRN correlation matrix
matrix[2,2] Rcor = LR * LR'; //residual correlation matrix
matrix[2,2] Pcov = diag_matrix(sd_P)*Pcor*diag_matrix(sd_P); //phenotypic covariance
matrix[2,2] Rcov = iag_matrix(sd_R)*Rcor*diag_matrix(sd_R); //residual covariance
//variances
vector<lower=0>[2] V_P = sd_P .* sd_P;
vector<lower=0>[2] V_R = sd_R .* sd_R;
}", "sam3_3p.stan")