This tutorial follows from our introduction to multivariate linear models, extending it by using multivariate linear mixed models.
Useful packages:
library(MCMCglmm)
library(lme4)
library(brms)
library(tidyr)
library(dplyr)
library(corrplot)
library(broom.mixed)
library(dotwhisker)
library(ggplot2); theme_set(theme_bw())
This is an old Drosophila melanogaster data set from Ian Dworkin’s PhD work (Dworkin 2005). This was from a study that was meant to test predictions of a model on how mutational and environmental variation can influence the overall structure of phenotypic variation. For this study Dworkin measured several traits (lengths) on the first leg as well as the number of sex comb teeth (a structure used to clasp females during copulation) for different wild type strains (line) reared at different developmental temperatures (temp), with and without a mutation that effects proximal-distal axis development in limbs (genotype).
Get data from https://doi.org/10.5061/dryad.8376 or this repo:
dll_data <- read.csv("../data/dll.csv")
## make temp a factor (25 vs 30 degrees)
dll_data$temp <- factor(dll_data$temp)
## scale relevant variables (fancier but less repetition than previously)
morph_vars <- c("femur","tibia","tarsus","SCT")
morph_vars_sc <- paste(morph_vars,"s",sep="_")
dll_data2 <- dll_data
## c() drops unwanted structure from the results of scale()
for (i in 1:length(morph_vars)) {
dll_data2[[morph_vars_sc[i]]] <- c(scale(dll_data[[morph_vars[i]]]))
}
The previous expression for the multivariate model was
\[ \mathbf{Y} = \mathbf{XB} + \mathbf{E} \]
In contrast, the expression for the mixed model is
\[ y = \mathbf{X\beta} + \mathbf{Zb} + \epsilon \]
where \(\mathbf{b}\) is a set of Gaussian variables with a variance-covariance matrix \(\mathbf{\Sigma}\) which we estimate.
Suppose we have observations of \(m\) individuals, with \(p\) different observations (traits, or time points, or types of measurement, or …) for each individual. The way we’re going to make this work is to expand (“melt”, or gather()
or pivot_longer()
if we’re using tidyr
) the data set to be \(mp\) observations long, then treat each individual (which was previously a single row of the data set but now comprises \(p\) rows) as a group (we’ll call this units
):
lme4 does not (currently) have a natural syntax for multivariate responses, however, as I eluded to in class, there is an important relationship between multivariate response models and so called “repeated” measures (or longitudinal) models. As such we can use a few tricks to estimate the model in lme4. Below this, I will go through the same model using MCMCglmm, which is a library which has a more natural syntax for such multivariate responses, but is explicitly Bayesian, so you need to provide prior distributions.
What we need to first do (for lme4) is to generate a single column that represents the numeric values for our response traits, and then a second variable that stores the trait type.
dll_melt <- (dll_data2
%>% select(-c(femur,tibia,tarsus,SCT)) ## drop unscaled vars
%>% mutate(units=factor(1:n()))
%>% gather(trait,value, -c(units,replicate,line,genotype,temp))
%>% drop_na()
%>% arrange(units)
)
## saveRDS(dll_melt, file="dll_melt.rds")
(in case you’re familiar with current-day tidyverse: gather()
is an earlier version of pivot_longer()
, which is now recommended).
Look at how this has changed the structure of the data from a wide format:
head(dll_data) # original wide
## replicate line genotype temp femur tibia tarsus SCT
## 1 1 line-1 Dll 25 0.590 0.499 0.219 9
## 2 1 line-1 Dll 25 0.550 0.501 0.214 13
## 3 1 line-1 Dll 25 0.588 0.488 0.211 11
## 4 1 line-1 Dll 25 0.588 0.515 0.211 NA
## 5 1 line-1 Dll 25 0.596 0.502 0.207 12
## 6 1 line-1 Dll 25 0.577 0.499 0.207 14
to a long format:
head(dll_melt)
## replicate line genotype temp units trait value
## 1 1 line-1 Dll 25 1 femur_s 1.514
## 2 1 line-1 Dll 25 1 tibia_s 0.597
## 3 1 line-1 Dll 25 1 tarsus_s 1.751
## 4 1 line-1 Dll 25 1 SCT_s -1.222
## 5 1 line-1 Dll 25 2 femur_s 0.138
## 6 1 line-1 Dll 25 2 tibia_s 0.654
We can now go ahead and fit the model where we need to include trait as a predictor variable (where each trait is now a “repeated measure” from a particular subject/individual)
t1 <- system.time(
lmer1 <- lmer(value ~ trait:(genotype*temp) - 1 +
(trait-1|line) + (trait-1|units),
data=dll_melt,
control=lmerControl(
optimizer="bobyqa",
check.nobs.vs.nlev="ignore",
check.nobs.vs.nRE="ignore"))
)
system.time()
business is just to keep track of how long the command takes to run (we could have kept the HTML output clean by hiding this in the .Rmd
file, at the cost of making the .Rmd
more complicated/confusing for those who were following along there)-1
to drop intercepttrait:(1+genotype+temp+genotype:temp)
trait + trait:genotype + trait:temp + trait:genotype:temp
(trait-1|line)
means “variance/covariances of traits among lines”-1
so we consider traits, not differences among traits(trait-1|units)
specifies “var/cov of traits among units (individuals)”lmer
always includes a residual variance term. This is redundant because we have only one data point per individual per trait: lmerControl(...)
tells lmer
not complainoptimizer="bobyqa"
is the only choice of optimizers that does not give a convergence warning (ask about this if you feel like going down a rabbit hole)print(lmer1)
, summary(lmer1)
useful but awkward (16 fixed effect coefficients, we’ll look at graphical summaries insteadfixef()
(fixed effects), ranef()
(line/indiv deviations from pop mean), coef()
(line/indiv-level estimates), VarCorr
(random effects var/cov)getME(fit,"theta")
extracts them if you need them for something.isSingular(lmer1)
## [1] FALSE
VarCorr(lmer1)
## Groups Name Std.Dev. Corr
## units traitfemur_s 0.649
## traitSCT_s 0.724 0.06
## traittarsus_s 0.559 0.59 0.21
## traittibia_s 0.665 0.93 0.12 0.48
## line traitfemur_s 0.489
## traitSCT_s 0.392 0.14
## traittarsus_s 0.462 0.81 0.37
## traittibia_s 0.473 0.87 0.22 0.83
## Residual 0.470
par(mfrow=c(1,2))
vv1 <- VarCorr(lmer1)
## fix unit variance-covariance by adding residual variance:
diag(vv1$units) <- diag(vv1$units)+sigma(lmer1)^2
corrplot.mixed(cov2cor(vv1$line),upper="ellipse")
corrplot.mixed(cov2cor(vv1$units),upper="ellipse")
Correlations of traits across lines are stronger than correlations within individuals. In both cases correlations are all positive (i.e. first axis of variation is size variation?)
cc1 <- tidy(lmer1,effect="fixed") %>%
tidyr::separate(term,into=c("trait","fixeff"),extra="merge",
remove=FALSE)
dwplot(cc1)+facet_wrap(~fixeff,scale="free",ncol=2)+
geom_vline(xintercept=0,lty=2)
These results tell approximately the same story (coefficients are consistent across traits within a fixed effect, e.g. effect of higher temperature is to reduce scores on all traits).
This is very slow, you probably don’t want to evaluate it on your computer
t1_CI <- system.time(cc2 <- tidy(lmer1,
effect = "ran_pars",
conf.int = TRUE,
conf.method = "profile",
parallel="multicore",
ncpus=8))
saveRDS(cc2, file="../data/cc2.rds")
(about 40 minutes to run on 8 cores on a fast machine)
Another option is the MCMCglmm
package, which has a natural interface for general multivariate mixed models. It takes a while to get used to the interface, but here is an example. Please check out here for more information about the package, and here for an overview of how to use it.
First I find it easier (given the interface of MCMCglmm) to create a formula with the response variables and predictors. This is only for the fixed effects part of the model.
fmla.MMLM1 <- cbind(femur_s, tibia_s, tarsus_s, SCT_s) ~
trait:(genotype*temp) - 1
Now we need to let MCMCglmm
know which family (i.e. distribution) the response variables are. Since all are normal (Gaussian), we can specify it the following way.
fam.test <- rep("gaussian", 4 )
Since MCMCglmm
is fundamentally a Bayesian approach, it needs a prior. If you provide no prior by default, it tries a “flat” prior, although this rarely works. In this case we provide not-quite-flat priors only for the random effects of line and for the residual variances (could also provide them for the fixed effects). Choosing priors for variances and covariances is tricky (and too technical for right now), so we will use the default prior distributions (inverse-Wishart). Ian Dworkin has some simple tutorials where he draws out the effects of various common priors for variances and covariances.
prior.model.1 <- list( R = list(V=diag(4)/4, nu=0.004),
G = list(G1=list(V=diag(4)/4, nu=0.004)))
Let’s take a quick look at the prior
prior.model.1
## $R
## $R$V
## [,1] [,2] [,3] [,4]
## [1,] 0.25 0.00 0.00 0.00
## [2,] 0.00 0.25 0.00 0.00
## [3,] 0.00 0.00 0.25 0.00
## [4,] 0.00 0.00 0.00 0.25
##
## $R$nu
## [1] 0.004
##
##
## $G
## $G$G1
## $G$G1$V
## [,1] [,2] [,3] [,4]
## [1,] 0.25 0.00 0.00 0.00
## [2,] 0.00 0.25 0.00 0.00
## [3,] 0.00 0.00 0.25 0.00
## [4,] 0.00 0.00 0.00 0.25
##
## $G$G1$nu
## [1] 0.004
The R
matrix prior is for the residuals. This is \(\mathbf{R}_{4,4}\) as we have 4 traits in the VCV matrix. We have have non-zero variances for each trait as the mode for the prior, and 0 for covariances. However this is a weak prior, so even small amounts of data will largely overcome the pull of the prior. Another sensible approach we have used is to make the prior proportional to the overall observed VCV, as there is a large literature on the proportionality of covariance matrices for morphology. This may not be sensible for other types of multivariate response measures.
##,depends.on=c("prior","mod_fm","get_data")}
t2 <- system.time(
MMLM1.fit <- MCMCglmm(fmla.MMLM1,
random=~ us(trait):line,
rcov=~ us(trait):units,
prior= prior.model.1,
data= dll_data2,
family = fam.test,
nitt= 10000, burnin= 2000, thin=10)
)
fmla.MMLM1
is the formula object we created abovelmer
formulatrait
term is a reserved word in MCMCglmm
, letting it know we want to fit a multivariate mixed modelMCMCglmm
automatically melts the data for us (and assigns the name trait
the same way we did manually above)random=~us(trait):line
asks MCMCglmm
to fit an unstructured covariance matrix for the line term (i.e the different wild type genotypes we are examining).- “Unstructured” means we are estimating the complete 4 x 4 matrix of covariances (= 4*5/2 = 10 elements total)(trait-1|line)
in lmer
modelMCMCglmm
also automatically adds a units
rcov=~us(trait):units
= (trait-1|units)
MCMCglmm
offers a few other options for variance-covariance structuresThe nitt
is how many iterations for the MCMC we want to perform, and the burnin
is how many should be ignored at the beginning of the random walk.
The fit takes 12 seconds.
Normally we would spend a fair bit of time on diagnostics of the MCMC, but for now we will just quickly check the trace plots and autocorrelation.
In the fitted object $Sol
is for solution, which is the term used for fixed effects in MCMCglmm. $VCV
is for the variance-covariance matrix.
library(lattice)
xyplot(MMLM1.fit$Sol[,1:4])
xyplot(MMLM1.fit$Sol[,13:16])
acf(MMLM1.fit$Sol[,1:2])
xyplot(MMLM1.fit$VCV[,1:4])
acf(MMLM1.fit$VCV[,1:3])
Nothing terribly worrying.
summary(MMLM1.fit)
##
## Iterations = 2001:9991
## Thinning interval = 10
## Sample size = 800
##
## DIC: 17450
##
## G-structure: ~us(trait):line
##
## post.mean l-95% CI u-95% CI eff.samp
## traitfemur_s:traitfemur_s.line 0.2976 0.1433 0.496 864
## traittibia_s:traitfemur_s.line 0.2487 0.1035 0.418 923
## traittarsus_s:traitfemur_s.line 0.2272 0.0947 0.389 940
## traitSCT_s:traitfemur_s.line 0.0318 -0.0891 0.148 800
## traitfemur_s:traittibia_s.line 0.2487 0.1035 0.418 923
## traittibia_s:traittibia_s.line 0.2739 0.1379 0.461 932
## traittarsus_s:traittibia_s.line 0.2227 0.0974 0.391 969
## traitSCT_s:traittibia_s.line 0.0493 -0.0414 0.174 800
## traitfemur_s:traittarsus_s.line 0.2272 0.0947 0.389 940
## traittibia_s:traittarsus_s.line 0.2227 0.0974 0.391 969
## traittarsus_s:traittarsus_s.line 0.2644 0.1159 0.443 959
## traitSCT_s:traittarsus_s.line 0.0824 -0.0232 0.213 800
## traitfemur_s:traitSCT_s.line 0.0318 -0.0891 0.148 800
## traittibia_s:traitSCT_s.line 0.0493 -0.0414 0.174 800
## traittarsus_s:traitSCT_s.line 0.0824 -0.0232 0.213 800
## traitSCT_s:traitSCT_s.line 0.1866 0.0891 0.313 800
##
## R-structure: ~us(trait):units
##
## post.mean l-95% CI u-95% CI eff.samp
## traitfemur_s:traitfemur_s.units 0.6448 0.60283 0.6818 800
## traittibia_s:traitfemur_s.units 0.4017 0.37158 0.4364 800
## traittarsus_s:traitfemur_s.units 0.2155 0.18867 0.2439 715
## traitSCT_s:traitfemur_s.units 0.0261 -0.00694 0.0561 800
## traitfemur_s:traittibia_s.units 0.4017 0.37158 0.4364 800
## traittibia_s:traittibia_s.units 0.6643 0.62163 0.7062 800
## traittarsus_s:traittibia_s.units 0.1797 0.15021 0.2059 800
## traitSCT_s:traittibia_s.units 0.0604 0.02658 0.0910 800
## traitfemur_s:traittarsus_s.units 0.2155 0.18867 0.2439 715
## traittibia_s:traittarsus_s.units 0.1797 0.15021 0.2059 800
## traittarsus_s:traittarsus_s.units 0.5355 0.50492 0.5696 1108
## traitSCT_s:traittarsus_s.units 0.0840 0.05372 0.1133 800
## traitfemur_s:traitSCT_s.units 0.0261 -0.00694 0.0561 800
## traittibia_s:traitSCT_s.units 0.0604 0.02658 0.0910 800
## traittarsus_s:traitSCT_s.units 0.0840 0.05372 0.1133 800
## traitSCT_s:traitSCT_s.units 0.7457 0.69798 0.7884 1156
##
## Location effects: cbind(femur_s, tibia_s, tarsus_s, SCT_s) ~ trait:(genotype * temp) - 1
##
## post.mean l-95% CI u-95% CI eff.samp pMCMC
## traitfemur_s:genotypeDll 0.49979 0.28116 0.71626 800 <0.001 **
## traittibia_s:genotypeDll 0.63199 0.42890 0.86094 874 <0.001 **
## traittarsus_s:genotypeDll 0.60341 0.42113 0.83665 779 <0.001 **
## traitSCT_s:genotypeDll 0.67562 0.47546 0.85978 800 <0.001 **
## traitfemur_s:genotypewt 0.16897 -0.03813 0.38846 960 0.1225
## traittibia_s:genotypewt 0.00838 -0.18883 0.22347 800 0.9350
## traittarsus_s:genotypewt 0.43649 0.24563 0.63703 796 0.0025 **
## traitSCT_s:genotypewt -0.08833 -0.28673 0.07674 800 0.3050
## traitfemur_s:temp30 -0.83506 -0.94664 -0.72345 800 <0.001 **
## traittibia_s:temp30 -0.81013 -0.92652 -0.71148 674 <0.001 **
## traittarsus_s:temp30 -1.23443 -1.33083 -1.14002 800 <0.001 **
## traitSCT_s:temp30 -0.84197 -0.97720 -0.73130 800 <0.001 **
## traitfemur_s:genotypewt:temp30 0.36022 0.21096 0.49195 800 <0.001 **
## traittibia_s:genotypewt:temp30 0.47518 0.33737 0.61969 714 <0.001 **
## traittarsus_s:genotypewt:temp30 0.51164 0.37837 0.63692 905 <0.001 **
## traitSCT_s:genotypewt:temp30 0.73084 0.57630 0.90538 800 <0.001 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Sometimes it is easier to look at the fixed and random effects separately.
summary(MMLM1.fit$Sol)
##
## Iterations = 2001:9991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 800
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## traitfemur_s:genotypeDll 0.49979 0.1131 0.00400 0.00400
## traittibia_s:genotypeDll 0.63199 0.1120 0.00396 0.00379
## traittarsus_s:genotypeDll 0.60341 0.1061 0.00375 0.00380
## traitSCT_s:genotypeDll 0.67562 0.0975 0.00345 0.00345
## traitfemur_s:genotypewt 0.16897 0.1109 0.00392 0.00358
## traittibia_s:genotypewt 0.00838 0.1085 0.00384 0.00384
## traittarsus_s:genotypewt 0.43649 0.1030 0.00364 0.00365
## traitSCT_s:genotypewt -0.08833 0.0909 0.00321 0.00321
## traitfemur_s:temp30 -0.83506 0.0571 0.00202 0.00202
## traittibia_s:temp30 -0.81013 0.0566 0.00200 0.00218
## traittarsus_s:temp30 -1.23443 0.0513 0.00181 0.00181
## traitSCT_s:temp30 -0.84197 0.0629 0.00222 0.00222
## traitfemur_s:genotypewt:temp30 0.36022 0.0748 0.00264 0.00264
## traittibia_s:genotypewt:temp30 0.47518 0.0736 0.00260 0.00275
## traittarsus_s:genotypewt:temp30 0.51164 0.0667 0.00236 0.00222
## traitSCT_s:genotypewt:temp30 0.73084 0.0822 0.00290 0.00290
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## traitfemur_s:genotypeDll 0.2807 0.4217 0.50215 0.5751 0.7148
## traittibia_s:genotypeDll 0.3970 0.5556 0.63697 0.7069 0.8385
## traittarsus_s:genotypeDll 0.3974 0.5338 0.60326 0.6711 0.8178
## traitSCT_s:genotypeDll 0.4860 0.6108 0.67354 0.7383 0.8741
## traitfemur_s:genotypewt -0.0383 0.0941 0.17282 0.2422 0.3884
## traittibia_s:genotypewt -0.2054 -0.0618 0.00912 0.0826 0.2133
## traittarsus_s:genotypewt 0.2315 0.3725 0.43521 0.5043 0.6334
## traitSCT_s:genotypewt -0.2732 -0.1475 -0.08866 -0.0313 0.0908
## traitfemur_s:temp30 -0.9451 -0.8755 -0.83602 -0.7953 -0.7214
## traittibia_s:temp30 -0.9201 -0.8474 -0.81226 -0.7731 -0.6979
## traittarsus_s:temp30 -1.3361 -1.2698 -1.23478 -1.1973 -1.1439
## traitSCT_s:temp30 -0.9683 -0.8820 -0.84183 -0.7999 -0.7183
## traitfemur_s:genotypewt:temp30 0.2117 0.3112 0.36177 0.4157 0.4920
## traittibia_s:genotypewt:temp30 0.3296 0.4233 0.47515 0.5253 0.6151
## traittarsus_s:genotypewt:temp30 0.3796 0.4673 0.51155 0.5585 0.6385
## traitSCT_s:genotypewt:temp30 0.5664 0.6789 0.72766 0.7836 0.9006
And for the random effects.
summary(MMLM1.fit$VCV)
##
## Iterations = 2001:9991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 800
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## traitfemur_s:traitfemur_s.line 0.2976 0.1044 0.003690 0.003550
## traittibia_s:traitfemur_s.line 0.2487 0.0951 0.003362 0.003130
## traittarsus_s:traitfemur_s.line 0.2272 0.0847 0.002994 0.002762
## traitSCT_s:traitfemur_s.line 0.0318 0.0597 0.002112 0.002112
## traitfemur_s:traittibia_s.line 0.2487 0.0951 0.003362 0.003130
## traittibia_s:traittibia_s.line 0.2739 0.0965 0.003412 0.003162
## traittarsus_s:traittibia_s.line 0.2227 0.0824 0.002912 0.002646
## traitSCT_s:traittibia_s.line 0.0493 0.0566 0.002001 0.002001
## traitfemur_s:traittarsus_s.line 0.2272 0.0847 0.002994 0.002762
## traittibia_s:traittarsus_s.line 0.2227 0.0824 0.002912 0.002646
## traittarsus_s:traittarsus_s.line 0.2644 0.0889 0.003144 0.002870
## traitSCT_s:traittarsus_s.line 0.0824 0.0611 0.002159 0.002159
## traitfemur_s:traitSCT_s.line 0.0318 0.0597 0.002112 0.002112
## traittibia_s:traitSCT_s.line 0.0493 0.0566 0.002001 0.002001
## traittarsus_s:traitSCT_s.line 0.0824 0.0611 0.002159 0.002159
## traitSCT_s:traitSCT_s.line 0.1866 0.0644 0.002276 0.002276
## traitfemur_s:traitfemur_s.units 0.6448 0.0204 0.000722 0.000722
## traittibia_s:traitfemur_s.units 0.4017 0.0173 0.000612 0.000612
## traittarsus_s:traitfemur_s.units 0.2155 0.0145 0.000514 0.000543
## traitSCT_s:traitfemur_s.units 0.0261 0.0165 0.000582 0.000582
## traitfemur_s:traittibia_s.units 0.4017 0.0173 0.000612 0.000612
## traittibia_s:traittibia_s.units 0.6643 0.0215 0.000760 0.000760
## traittarsus_s:traittibia_s.units 0.1797 0.0146 0.000518 0.000518
## traitSCT_s:traittibia_s.units 0.0604 0.0168 0.000593 0.000593
## traitfemur_s:traittarsus_s.units 0.2155 0.0145 0.000514 0.000543
## traittibia_s:traittarsus_s.units 0.1797 0.0146 0.000518 0.000518
## traittarsus_s:traittarsus_s.units 0.5355 0.0173 0.000612 0.000520
## traitSCT_s:traittarsus_s.units 0.0840 0.0154 0.000543 0.000543
## traitfemur_s:traitSCT_s.units 0.0261 0.0165 0.000582 0.000582
## traittibia_s:traitSCT_s.units 0.0604 0.0168 0.000593 0.000593
## traittarsus_s:traitSCT_s.units 0.0840 0.0154 0.000543 0.000543
## traitSCT_s:traitSCT_s.units 0.7457 0.0236 0.000836 0.000695
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## traitfemur_s:traitfemur_s.line 0.16084 0.22444 0.2783 0.3495 0.5441
## traittibia_s:traitfemur_s.line 0.13011 0.18500 0.2276 0.2909 0.4706
## traittarsus_s:traitfemur_s.line 0.10966 0.16958 0.2098 0.2671 0.4273
## traitSCT_s:traitfemur_s.line -0.08423 -0.00196 0.0287 0.0628 0.1582
## traitfemur_s:traittibia_s.line 0.13011 0.18500 0.2276 0.2909 0.4706
## traittibia_s:traittibia_s.line 0.15258 0.20873 0.2533 0.3196 0.5144
## traittarsus_s:traittibia_s.line 0.11239 0.16613 0.2073 0.2640 0.4292
## traitSCT_s:traittibia_s.line -0.05043 0.01582 0.0431 0.0793 0.1719
## traitfemur_s:traittarsus_s.line 0.10966 0.16958 0.2098 0.2671 0.4273
## traittibia_s:traittarsus_s.line 0.11239 0.16613 0.2073 0.2640 0.4292
## traittarsus_s:traittarsus_s.line 0.14260 0.20440 0.2471 0.3077 0.4784
## traitSCT_s:traittarsus_s.line -0.01906 0.04329 0.0727 0.1120 0.2304
## traitfemur_s:traitSCT_s.line -0.08423 -0.00196 0.0287 0.0628 0.1582
## traittibia_s:traitSCT_s.line -0.05043 0.01582 0.0431 0.0793 0.1719
## traittarsus_s:traitSCT_s.line -0.01906 0.04329 0.0727 0.1120 0.2304
## traitSCT_s:traitSCT_s.line 0.09856 0.13910 0.1763 0.2180 0.3360
## traitfemur_s:traitfemur_s.units 0.60552 0.63101 0.6448 0.6584 0.6856
## traittibia_s:traitfemur_s.units 0.37126 0.38921 0.4004 0.4138 0.4362
## traittarsus_s:traitfemur_s.units 0.18928 0.20537 0.2145 0.2259 0.2448
## traitSCT_s:traitfemur_s.units -0.00598 0.01570 0.0269 0.0368 0.0577
## traitfemur_s:traittibia_s.units 0.37126 0.38921 0.4004 0.4138 0.4362
## traittibia_s:traittibia_s.units 0.62251 0.64904 0.6638 0.6781 0.7074
## traittarsus_s:traittibia_s.units 0.15242 0.16924 0.1793 0.1896 0.2089
## traitSCT_s:traittibia_s.units 0.02892 0.04872 0.0601 0.0716 0.0944
## traitfemur_s:traittarsus_s.units 0.18928 0.20537 0.2145 0.2259 0.2448
## traittibia_s:traittarsus_s.units 0.15242 0.16924 0.1793 0.1896 0.2089
## traittarsus_s:traittarsus_s.units 0.50489 0.52336 0.5354 0.5472 0.5694
## traitSCT_s:traittarsus_s.units 0.05500 0.07349 0.0837 0.0944 0.1146
## traitfemur_s:traitSCT_s.units -0.00598 0.01570 0.0269 0.0368 0.0577
## traittibia_s:traitSCT_s.units 0.02892 0.04872 0.0601 0.0716 0.0944
## traittarsus_s:traitSCT_s.units 0.05500 0.07349 0.0837 0.0944 0.1146
## traitSCT_s:traitSCT_s.units 0.70056 0.72938 0.7457 0.7632 0.7920
This is not the most friendly output, and it takes a while to get used to. However, we can see that we still have evidence for something interesting going, and we could extract the vectors of effects as we did above.
let’s look at the VCV matrix for the random effects of line in a slightly clearer way (as a matrix)
##' extract variance-covariance matrices for MCMCglmm objects
##' does not (yet) set cor, stddev, residual-var attributes
##' may be fragile: depends on group vars not having dots in them?
VarCorr.MCMCglmm <- function(object, ...) {
s <- summary(object$VCV)$statistics[,"Mean"]
grps <- gsub("^[^.]+\\.([[:alnum:]]+)$","\\1",names(s))
ss <- split(s,grps)
getVC <- function(x) {
nms <- gsub("^([^.]+)\\.[[:alnum:]]+$","\\1",names(x))
n <- length(nms)
L <- round(sqrt(n))
dimnms <- gsub("^([^:]+):.*$","\\1",nms[1:L])
return(matrix(x,dimnames=list(dimnms,dimnms),
nrow=L))
}
r <- setNames(lapply(ss,getVC),unique(grps))
return(r)
}
vv <- VarCorr(MMLM1.fit)
par(mfrow=c(1,2))
corrplot.mixed(cov2cor(vv$line),upper="ellipse")
corrplot.mixed(cov2cor(vv$units),upper="ellipse")
lme4
estimates (variables are in a different order)This is only a taste of what to do, and after this we could start asking questions about this genetic covariance matrix.
Compare fixed effects:
tt <- tidy(MMLM1.fit)
tt2 <- tidy(lmer1)
tt_comb <- bind_rows(lmer=tt,MCMCglmm=tt2,.id="model") %>%
filter(effect=="fixed")
dwplot(tt_comb)+geom_vline(xintercept=0,lty=2)
see vignette("brms_multivariate")
SLOW
library(brms)
t3 <- system.time(
brmsfit <- brm(
mvbind(femur_s, tibia_s, tarsus_s, SCT_s) ~ genotype*temp + (1|p|line) + (1|q|replicate),
data = dll_data2, chains = 4, cores = 4)
)
saveRDS(brmsfit,file="../data/multiv_brmsfit.rda")
This takes a long time! (\(\approx 40\) minutes, even computing the chains in parallel)
glmmTMB
, brms
…FIXME:
allFit
not working?)Dworkin, Ian. 2005. “Evidence for Canalization of Distal-Less Function in the Leg of Drosophila Melanogaster.” Evolution & Development 7 (2): 89–100. https://doi.org/10.1111/j.1525-142X.2005.05010.x.