Content Description

With multivariate data, two or more ordered sets of levels of a factor form a phenotypic trajectory in the multivariate dataspace. Such trajectories represent phenotypic changes from level to level, and may represent: sexual dimorphism (the difference between male and female levels in a species), phenotypic changes over space, or over ontogeny, or over evolutionary time.

Phenotypic trajectories have multiple attributes which may quantified and compared (see Collyer and Adams 2009; Adams and Collyer 2013). The function trajectory.analysis accomplishes this task. Currently, trajectory.analysis is found in the RRPP package, though it may be accessed through geomorph. There are two types of input: data in the form of a factorial design where the trajectory points are estimated during the analysis, or data can be input as sets of trajectories as may be found in motion trajectories (sensu Adams and Cerney 2007).

library(geomorph)
## Loading required package: RRPP
## Loading required package: rgl
## Loading required package: Matrix

1: Phenotypic Trajectories Estimated from a Linear Model

data(pupfish)
fit <- procD.lm(coords ~ Pop * Sex, data = Pupfish, iter = 999, print.progress = FALSE)
reveal.model.designs(fit)
##            Reduced                 Full                                  
## Pop              1                  Pop                                  
## Sex            Pop            Pop + Sex                                  
## Pop:Sex  Pop + Sex  Pop + Sex + Pop:Sex <- Null/Full inherent in pairwise
anova(fit)
## 
## Analysis of Variance, using Residual Randomization
## Permutation procedure: Randomization of null model residuals 
## Number of permutations: 1000 
## Estimation method: Ordinary Least Squares 
## Sums of Squares and Cross-products: Type I 
## Effect sizes (Z) based on F distributions
## 
##           Df       SS        MS     Rsq      F      Z Pr(>F)   
## Pop        1 0.008993 0.0089927 0.15964 16.076 3.9997  0.001 **
## Sex        1 0.015917 0.0159169 0.28255 28.453 4.1103  0.001 **
## Pop:Sex    1 0.003453 0.0034532 0.06130  6.173 3.7015  0.001 **
## Residuals 50 0.027970 0.0005594 0.49651                        
## Total     53 0.056333                                          
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Call: procD.lm(f1 = coords ~ Pop * Sex, iter = 999, data = Pupfish,  
##     print.progress = FALSE)
TA <- trajectory.analysis(fit, groups = Pupfish$Pop, traj.pts = Pupfish$Sex)
summary(TA, attribute = "MD") # Magnitude difference (absolute difference between path distances)
## 
## Trajectory analysis
## 
## 1000 permutations.
## 
## Points projected onto trajectory PCs
## 
## Trajectories:
## Trajectories hidden (use show.trajectories = TRUE to view)
## 
## Observed path distances by group
## 
##      Marsh   Sinkhole 
## 0.04611590 0.02568508 
## 
## Pairwise absolute differences in path distances, plus statistics
##                         d  UCL (95%)       Z Pr > d
## Marsh:Sinkhole 0.02043082 0.01270556 2.66325  0.001
summary(TA, attribute = "TC", angle.type = "deg") # Correlations (angles) between trajectories
## 
## Trajectory analysis
## 
## 1000 permutations.
## 
## Points projected onto trajectory PCs
## 
## Trajectories:
## Trajectories hidden (use show.trajectories = TRUE to view)
## 
## Pairwise correlations between trajectories, plus statistics
##                        r    angle UCL (95%)       Z Pr > angle
## Marsh:Sinkhole 0.7393716 42.32209  23.00833 3.67745      0.001
summary(TA, attribute = "SD") # No shape differences between vectors
## 
## 
## Cannot summarize trajectory shape differences for vectors.
# Retain results
TA.summary <- summary(TA, attribute = "MD")
TA.summary$summary.table
##                         d  UCL (95%)       Z Pr > d
## Marsh:Sinkhole 0.02043082 0.01270556 2.66325  0.001
# Plot results
TP <- plot(TA, pch = as.numeric(Pupfish$Pop) + 20, bg = as.numeric(Pupfish$Sex),
           cex = 0.7, col = "gray")
add.trajectories(TP, traj.pch = c(21, 22), start.bg = 1, end.bg = 2)
legend("topright", levels(Pupfish$Pop), pch =  c(21, 22), pt.bg = 1)

2: Phenotypic Trajectories Given as Input

data(motionpaths)
fit <- lm.rrpp(trajectories ~ groups, data = motionpaths, iter = 999, print.progress = FALSE)
anova(fit)
## 
## Analysis of Variance, using Residual Randomization
## Permutation procedure: Randomization of null model residuals 
## Number of permutations: 1000 
## Estimation method: Ordinary Least Squares 
## Sums of Squares and Cross-products: Type I 
## Effect sizes (Z) based on F distributions
## 
##           Df     SS      MS     Rsq      F      Z Pr(>F)   
## groups     3 6520.9 2173.63 0.98608 849.85 21.229  0.001 **
## Residuals 36   92.1    2.56 0.01392                        
## Total     39 6613.0                                        
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Call: lm.rrpp(f1 = trajectories ~ groups, iter = 999, data = motionpaths,  
##     print.progress = FALSE)
TA <- trajectory.analysis(fit, groups = motionpaths$groups, traj.pts = 5)
summary(TA, attribute = "MD") # Magnitude difference (absolute difference between path distances)
## 
## Trajectory analysis
## 
## 1000 permutations.
## 
## 
## Trajectories:
## Trajectories hidden (use show.trajectories = TRUE to view)
## 
## Observed path distances by group
## 
##         1         2         3         4 
## 10.144421  6.557011 10.949722 10.097348 
## 
## Pairwise absolute differences in path distances, plus statistics
##              d UCL (95%)          Z Pr > d
## 1:2 3.58741011  1.317461  3.8913405  0.001
## 1:3 0.80530081  1.247854  0.7320629  0.250
## 1:4 0.04707265  1.284309 -1.6674019  0.950
## 2:3 4.39271092  1.262817  4.5955836  0.001
## 2:4 3.54033746  1.333765  3.8250970  0.001
## 3:4 0.85237346  1.251712  0.8703440  0.213
summary(TA, attribute = "TC", angle.type = "deg") # Correlations (angles) between trajectories
## 
## Trajectory analysis
## 
## 1000 permutations.
## 
## 
## Trajectories:
## Trajectories hidden (use show.trajectories = TRUE to view)
## 
## Pairwise correlations between trajectories, plus statistics
##             r     angle UCL (95%)          Z Pr > angle
## 1:2 0.9989147  2.669593  20.70022 -0.8792581      0.808
## 1:3 0.6122502 52.247611  22.06576  3.5215617      0.001
## 1:4 0.9996899  1.426827  20.81629 -1.3327426      0.901
## 2:3 0.6484120 49.578018  21.87022  3.3651369      0.001
## 2:4 0.9974452  4.096420  21.08371 -0.5446100      0.700
## 3:4 0.5923727 53.674438  21.14215  3.5973574      0.001
summary(TA, attribute = "SD") # Shape differences between trajectories 
## 
## Trajectory analysis
## 
## 1000 permutations.
## 
## 
## Trajectories:
## Trajectories hidden (use show.trajectories = TRUE to view)
## 
## Pairwise trajectory shape differences, plus statistics
##              d UCL (95%)           Z Pr > d
## 1:2 0.10279471 0.1855284 -0.15347678  0.551
## 1:3 0.10686382 0.1879151 -0.04044511  0.512
## 1:4 0.28213028 0.1881749  2.98789933  0.002
## 2:3 0.07843294 0.1862637 -0.91031401  0.814
## 2:4 0.36491114 0.1877718  3.94123541  0.001
## 3:4 0.35086211 0.1859428  4.01741549  0.001
TP <- plot(TA, pch = 21, bg = as.numeric(motionpaths$groups),
           cex = 0.7, col = "gray")
add.trajectories(TP, traj.pch = 21, traj.bg = 1:4)