# Load librarys library(shapes) library(car) library(vegan) library(heplots) mshape<-function(A) { apply(A, c(1,2), mean) } # Use the gorilla skull lankmark data in the shapes pacakge # 30 females gorf.dat # 3-D array: 8 traits (landmarks), 2D coordinates, 30 individuals dim(gorf.dat) # 29 males gorm.dat dim(gorm.dat) # let's combine them, first put all the data into one vector gorilla_vector<-c(as.vector(gorf.dat),as.vector(gorm.dat)) # the new combined configuration gor_mf<-array(gorilla_vector,dim=c(8,2,59)) gor_mf # now we should have 8 landmarks for 59 dim(gor_mf) # need vector for sex factor to do later comparisons female<-rep("female",30) male<-rep("male",29) sex_factor<-as.factor(c(female,male)) # First, plot the raw data by sex plot(gor_mf[1:8,1,1:30],gor_mf[1:8,2,1:30],pch=16,col="red", xlab="X", ylab="Y") points(gor_mf[1:8,1,31:59],gor_mf[1:8,2,31:59],pch=16,col="blue") # do a generalized procrustes analysis and PCA GPA<-procGPA(gor_mf) # plot all indiviuals post-rotation plotshapes(GPA$rotated) points(GPA$mshape,pch=16,col="red") # plot post-rotation by sex plot(GPA$rotated[1:8,1,1:30],GPA$rotated[1:8,2,1:30],pch=16,col="red",cex=.5, xlab="rotated X", ylab="rotated Y") points(GPA$rotated[1:8,1,31:59],GPA$rotated[1:8,2,31:59],pch=16,col="blue",cex=.5) # Add 95% confidence ellipses for(l in 1:8) { dataEllipse(GPA$rotated[l,1,1:30],GPA$rotated[l,2,1:30],add=T, levels=0.95, col="red", center.pch=17, plot.points=FALSE) dataEllipse(GPA$rotated[l,1,31:59],GPA$rotated[l,2,31:59],add=T, levels=0.95, col="blue", center.pch=17, plot.points=FALSE) } # plot the mean shape plotshapes(GPA$mshape) # plot individuals in PCA space plot(GPA$stdscores[,1],GPA$stdscores[,2],pch=16,col=c("red","blue")[sex_factor]) # plot shape change vectors for first three PCA axes, magnifiy vectors 3x shapepca(GPA,type="v",mag=3) # To see how any individual or group shape changes, you can visualize with the tpsgrid function # Compare average male or female to overall consensis tpsgrid(GPA$mshape,mshape(GPA$rotated[,,1:30]),mag=6) tpsgrid(GPA$mshape,mshape(GPA$rotated[,,31:59]),mag=6) # Directly compare average male to average female tpsgrid(mshape(GPA$rotated[,,1:30]),mshape(GPA$rotated[,,31:59]),mag=6) # What about allometry? # Look at male and female size # centroid sizes gor_size<-GPA$size gor_size # Plot size vs. PCA axis 1 plot(gor_size, GPA$stdscores[,1],pch=16,col=c("red","blue")[sex_factor]) # Mean size by sex tapply(gor_size,sex_factor,mean) # SD in size tapply(gor_size,sex_factor,sd) # Males are bigger # In fact, the smallest male in the dataset is larger than the largest female tapply(gor_size,sex_factor,min) tapply(gor_size,sex_factor,max) # The procGPA function is very "black box", it does the Procrustes rotation and subsequent PCA # Lets extract the Procrustes part, then do a PCA as we did earlier in class # make a matrix of 16 shape variables for the 59 individuals shape_variables<-t(matrix(GPA$rotated,16,59)) # Do a PCA with the rda function pca<-rda(shape_variables) biplot(pca,type="text") # Let's make sure these are the same, plot the first axis of the two approaches, they should be identical plot(GPA$scores[,1],scores(pca)$sites[,1]) # They are...we can plot the PCA like we did before, should be identiacl to the earlier plot plot(scores(pca)$sites[,1],scores(pca)$sites[,2],pch=16, col=c("red","blue")[sex_factor]) # Let's do a MANOVA! # First, get the shape PCA scores. Note that we have 14 PCA axes (16-2). Two were dropped. There are 16 in the GPA$scores matrix, but the last two are essentially 0. # How many axes should we include? The first 10 axes explain 98% of morphological variance response_matrix<-cbind(scores(pca,choices = c(1:10))$sites[,1:10]) model<-manova(response_matrix~gor_size*sex_factor) anova(model) summary(model,test="Wilks") etasq(model)