Laughlin et al. Appendix S2. Climatic constraints on trait-based forest assembly. 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 Appendix S2. R code for evaluating the fit of MaxEnt predictions when the constraints are predicted from environmental conditions. This function will soon be available in the ‘FD’ library of R (Laliberté and Shipley 2010). In order for the example to work properly, you must install the FD package. # example with tussock data from FD package # let's assume that constraints are not observed but predicted traits <- tussock$trait[, c(2:7, 11)] # use only continuous traits traits <- na.omit(traits) # remove 2 species with NA's abun <- tussock$abun[, rownames(traits)] # abundance matrix abun <- t(apply(abun, 1, function(x) x / sum(x) )) # relative abundances agg <- functcomp(traits, abun) # community-aggregated traits traits <- t(traits) # transpose matrix # pred are the predicted relative abundances from maxent model pred <- maxent(agg, traits)$prob # obs are observed relative abundances obs <- abun ##### maxent.test.pred function maxent.test.pred <- function(pred, obs, nperm = 999, stat = c("R2", "RMSE", "RMSEsqrt") ) { # match arg for stat stat <- match.arg(stat) # get number of sites if (is.vector(pred) ) pred <- matrix(pred, nrow = 1) nsites <- nrow(pred) # get observed statistic if (stat == "R2") { obs.stat <- (cor(as.numeric(pred), as.numeric(obs) ) )^2 names(obs.stat) <- "R2" } if (stat == "RMSE") { obs.stat <- sqrt(mean((obs - pred)^2)) names(obs.stat) <- "RMSE" } if (stat == "RMSEsqrt") { obs.stat <- sqrt(mean((sqrt(obs) - sqrt(pred))^2)) names(obs.stat) <- "RMSEsqrt" } # get vector to dump results dump <- rep(NA, nperm) # permute columns of obs independently for each row # each time, compute observed stat # use nested for loop to do this # R2 1 Laughlin et al. Appendix S2. Climatic constraints on trait-based forest assembly. 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 if (stat == "R2") { for (i in 1:nperm) { obs.perm <- obs for (j in 1:nsites) { obs.perm[j, ] <- sample(obs[j, ]) } dump[i] <- (cor(as.numeric(pred), as.numeric(obs.perm) ) )^2 } # end of i for loop } # RMSE if (stat == "RMSE") { for (i in 1:nperm) { obs.perm <- obs for (j in 1:nsites) { obs.perm[j, ] <- sample(obs[j, ]) } dump[i] <- sqrt(mean((obs.perm - pred)^2)) } # end of i for loop } # RMSEsqrt if (stat == "RMSEsqrt") { for (i in 1:nperm) { obs.perm <- obs for (j in 1:nsites) { obs.perm[j, ] <- sample(obs[j, ]) } dump[i] <- sqrt(mean((sqrt(obs.perm) - sqrt(pred))^2)) } # end of i for loop } # get permutational p-value # test for R2 -> one-tailed test, upper # test is upper because P-value reflects how many times R2 is equal or greater # than observed, if null hypothesis is true if (stat == "R2") p.perm <- (length(dump[dump >= obs.stat]) + 1) / (length(dump) + 1) # test for RMSE or RMSEsqrt -> one-tailed, lower # test is upper because P-value reflects how many times RMSE or RMSEsqrt is equal or smaller # than observed, if null hypothesis is true else p.perm <- (length(dump[dump <= obs.stat]) + 1) / (length(dump) + 1) names(p.perm) <- "P-value" # return results return(c(obs.stat, p.perm) ) } # end of function ##### # examples maxent.test.pred(pred, obs, nperm = 999) maxent.test.pred(pred, obs, nperm = 999, stat = "RMSE") maxent.test.pred(pred, obs, nperm = 999, stat = "RMSEsqrt") 2 Laughlin et al. Appendix S2. Climatic constraints on trait-based forest assembly. 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 # test when obs shares no link with pred # shuffle obs to yield obs.perm obs.perm <- obs for (j in 1:nrow(obs)) { obs.perm[j, ] <- sample(obs[j, ]) } maxent.test.pred(pred, obs.perm, nperm = 999, stat = "R2") Reference for Appendix S2 Laliberté, E., & Shipley, B. (2010) FD: Measuring functional diversity from multiple traits, and other tools for functional ecology. R package in The Comprehensive R Archive Network (CRAN) URL http://cran.r-project.org/package=FD, Vienna, Austria. 3