-
Notifications
You must be signed in to change notification settings - Fork 1
/
06-Covariations.Rmd
executable file
·344 lines (305 loc) · 18.8 KB
/
06-Covariations.Rmd
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
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
```{r setupindcov, include=FALSE}
rm(list = ls()) ; invisible(gc()) ; set.seed(42)
library(knitr)
library(tidyverse)
library(sf)
library(leaflet)
library(ggfortify)
theme_set(bayesplot::theme_default())
opts_chunk$set(
echo = F, message = F, warning = F, fig.height = 6, fig.width = 8,
cache = T, cache.lazy = F)
crs <- '+proj=longlat +datum=WGS84' # leaflet CRS
varcols <- c(species = "red", individual = "lightgreen",
sample = "lightblue", repetition = "orange", residual = "grey")
log_abs_trans <- function() {
scales::trans_new(
name = "log_abs",
transform = function(x) log(abs(x)),
inverse = function(x) exp(x));
}
```
```{r inndpcadata}
# data
ft <- googlesheets4::read_sheet("https://docs.google.com/spreadsheets/d/19eULgGa02RS6hwn2ngeEu4akF2YdaQGHS5xSac2hIYI/edit?usp=sharing",
"traits") %>%
filter(StudyLevel == "tree") %>%
dplyr::select(Genus, Species, Tree, LA, SLA, LT, CC, LDMC, FvFm, RWC, LSWC, Ptlp, gmin, DBH, TWI) %>%
mutate_at(c("gmin", "LA", "LT", "LDMC", "CC", "Ptlp", "SLA", "LSWC"), abs) %>%
mutate_at(c("gmin", "LA", "LT", "LDMC", "CC", "Ptlp", "SLA", "LSWC"), log) %>%
mutate(Ptlp = -Ptlp) %>%
na.omit() %>%
mutate(SpeciesLong = paste(Genus, Species))
# wpca
wPCA <- ade4::withinpca(select(ft, gmin, LA, LT, LDMC, CC, Ptlp, SLA, LSWC), as.factor(ft$SpeciesLong),
scannf = F, nf = 5)
class(wPCA) <- c("pca", "dudi")
# ind
ind.coord <- wPCA$li
dataind <- wPCA$tab
dataind <- t(apply(dataind, 1, function(x){x*wPCA$norm} ))
dataind <- t(apply(dataind, 1, function(x){x+wPCA$cent}))
eigenvalues <- dataind[1:ncol(ind.coord)]
pca.center <- rep(0, ncol(dataind))
pca.scale <- rep(1, ncol(dataind))
getdistance <- function(ind_row, center, scale){
return(sum(((ind_row-center)/scale)^2))
}
d2 <- apply(dataind, 1,getdistance, pca.center, pca.scale)
cos2 <- function(ind.coord, d2){return(ind.coord^2/d2)}
ind.cos2 <- apply(ind.coord, 2, cos2, d2)
contrib <- function(ind.coord, eigenvalues, n.ind){
100*(1/n.ind)*(ind.coord^2/eigenvalues)
}
ind.contrib <- t(apply(ind.coord, 1, contrib, eigenvalues, nrow(ind.coord)))
colnames(ind.coord) <- colnames(ind.cos2) <-
colnames(ind.contrib) <- paste0("Dim.", 1:ncol(ind.coord))
rnames <- rownames(ind.coord)
if(is.null(rnames)) rnames <- as.character(1:nrow(ind.coord))
rownames(ind.coord) <- rownames(ind.cos2) <- rownames(ind.contrib) <- rnames
pca.ind = list(coord = ind.coord, cos2 = ind.cos2, contrib = ind.contrib)
# ind/var prep
var <- factoextra::facto_summarize(wPCA, element = "var",
result = c("coord", "contrib", "cos2"), axes = 1:2)
colnames(var)[2:3] <- c("x", "y")
ind <- data.frame(pca.ind$coord[, 1:2, drop=FALSE])
colnames(ind)<- c("x", "y")
ind <- cbind(ind, ft)
# Daniela data
dani <- read_csv("data/211124_TraitDatabase_species_means_updatedNames.csv") %>%
dplyr::rename(
# LA = NA, SLA = NA, LT = NA, CC = NA,
# LDMC = `LDMC.mg.g_mean`,
LSWC = `LSWC_E.per_corr_mean`,
Ptlp = `ptlp_mean`, gmin = `gmin.slope_mean`) %>%
mutate(SpeciesLong = paste(Genus_CorrBota, Species_CorrBota)) %>%
dplyr::select(SpeciesLong, LSWC, Ptlp, gmin)
fg <- readxl::read_xlsx("data/Appendix_S2-6___S8-13.xlsx", "App.S6-ok", skip = 3) %>%
mutate(SpeciesLong = gsub("_", " ", Species)) %>%
dplyr::rename(LA = Leaf_Area, SLA = SLA, LT = Thickness, CC = Chlorophyll_content) %>%
dplyr::select(SpeciesLong, LA, SLA, LT, CC)
ftsp <- left_join(dani, fg) ; rm(dani, fg)
```
# Traits covariation
Subsequent analysis aimed to explore co-variations of individual traits.
Specifically, we investigated individual traits co-variation at several taxonomic scales: among species, and within species.
## Material
We used data from Vleminckx *et al,* (2021) and Krebber *et al,* (in prep) to obtain the average trait value per species in 94 to 102 species per trait species per trait in order to have a balanced sampling with respect to intra-species variation.
```{r ftspN}
ftsp %>%
reshape2::melt("SpeciesLong", variable.name = "trait") %>%
na.omit() %>%
group_by(trait) %>%
summarise(N = n()) %>%
kable(caption = "Number of species mean value per trai.")
```
## Methods
We used species mean values to calculate pairwise Pearson correlation coefficients for each pair of traits. We used individual trait values minus species mean trait values to measure intraspecific variability independent of species variation. We calculated pairwise Pearson correlation coefficients for each pair of traits using individual trait values minus the species mean. Finally, we compared the absolute values of Pearson's correlation coefficients for each pair of traits within and between species to explore the conservatism of trait coordination across scales.
## Results
We observe a strong and significant correlation of trait coordination within and among species (Pearson'$r=0645, p<10^{-6}$), with no marked differences between carbon-related and water-related traits.
```{r corspind, fig.cap="Correlation of among- and within-species trait correlations. The X-axis represents the absolute correlations of the mean trait values of the species, while the Y-axis represents the absolute correlations of the individual trait value minus the mean trait value of the corresponding species, thus revealing the coordination of traits among and within species. Points colour indicates the type of traits implicated in the trait pairs, with either carbon-related traits (green), water-related traits (blue), or carbon- and water-related traits (red). Label indicate trait pairs. The title indicate the correlation of correlations and the associated p-value. The grey line represents the expected position of the points for a correlation of 1 for trait correlations among- and within-species. Leaf traits include specific leaf area (SLA), leaf fresh thickness (LT), leaf area (LA) leaf chlorophyll content (CC), leaf saturated water content (LSWC), leaf water potential at which leaf cells lose turgor (Ptlp), and leaf minimum conductance (gmin). Within-species trait values originate from this study including 100 individuals from 10 species, while among trait values originate from Vleminckx *et al,* (2021) and Krebber *et al,* (in prep) with 94 to 102 species per trait. All trait values have been measured using the same protocol in the Paracou research station."}
corsp <- ftsp %>%
dplyr::select(-SpeciesLong) %>%
cor(use = "pairwise.complete.obs") %>%
as.data.frame() %>%
rownames_to_column("trait1") %>%
reshape2::melt("trait1", variable.name = "trait2", value.name = "cor_species") %>%
unique() %>%
filter(trait1 != trait2)
corind <- ft %>%
dplyr::select(SpeciesLong, Tree, LA, SLA, LT, CC, LSWC, Ptlp, gmin) %>%
reshape2::melt(c("SpeciesLong", "Tree"), variable.name = "trait") %>%
group_by(SpeciesLong, trait) %>%
mutate(value = value - mean(value)) %>%
reshape2::dcast(SpeciesLong + Tree ~ trait) %>%
dplyr::select(-SpeciesLong, -Tree) %>%
cor(use = "pairwise.complete.obs") %>%
as.data.frame() %>%
rownames_to_column("trait1") %>%
reshape2::melt("trait1", variable.name = "trait2", value.name = "cor_inds") %>%
unique() %>%
filter(trait1 != trait2)
cors <- left_join(corsp, corind)
rm(corsp, corind)
test <- cor.test(cors$cor_species, cors$cor_inds)
cors %>%
mutate(trait2 = as.character(trait2)) %>%
mutate(type1 = ifelse(trait1 %in% c("LSWC", "Ptlp", "gmin"), "water", "carbon")) %>%
mutate(type2 = ifelse(trait2 %in% c("LSWC", "Ptlp", "gmin"), "water", "carbon")) %>%
rowwise() %>%
mutate(type = paste(sort(unique(c(type1, type2))), collapse = " ")) %>%
dplyr::select(-type1, type2) %>%
mutate(type = recode(type, "water" = "water-related", "carbon" = "carbon-related",
"carbon water" = "carbon- and water-related")) %>%
mutate(pair = paste(sort(c(trait1, trait2)), collapse = "-")) %>%
group_by(pair) %>%
sample_n(1) %>%
ggplot(aes(abs(cor_species), abs(cor_inds), col = type, label = pair)) +
geom_abline(slope = 1, intercept = 0, col = "darkgrey") +
geom_point() +
ggrepel::geom_text_repel() +
xlab("Species absolute mean correlations (Pearson's r)") +
ylab("Individual minus species absolute mean correlations (Pearson's r)") +
ggtitle(paste0("Pearson's r = ", round(test$estimate, 3)), paste0("p = ", formatC(test$p.value, format = "e", digits = 2))) +
theme(legend.position = "bottom") + scale_x_sqrt() + scale_y_sqrt() +
scale_color_discrete("Pair type")
```
```{r cvspind, eval=F}
cv <- function(traits){
if(any(is.na(traits)))
traits=traits[!is.na(traits)]
N=length(traits)
y_bar=mean(traits)
s2_hat=var(traits)
cv_2=s2_hat/y_bar^2
cv_1=sqrt(cv_2)
gamma_1=sum(((traits-y_bar)/s2_hat^0.5)^3)/N
gamma_2=sum(((traits-y_bar)/s2_hat^0.5)^4)/N
bias=cv_2^(3/2)/N*(3*cv_2^0.5-2*gamma_1)
bias2=cv_1^3/N-cv_1/4/N-cv_1^2*gamma_1/2/N-cv_1*gamma_2/8/N
cv1=sd(traits)/mean(traits)
cv4=cv_1-bias2
re=cv4
return(re)
}
ft %>%
dplyr::select(SpeciesLong, LA, SLA, LT, CC, LSWC, Ptlp, gmin) %>%
reshape2::melt("SpeciesLong") %>%
group_by(SpeciesLong, variable) %>%
summarise(cv_ind = cv(log(abs(value)))) %>%
group_by(variable) %>%
summarise(cv_ind = median(cv_ind)) %>%
left_join(ftsp %>%
reshape2::melt("SpeciesLong") %>%
group_by(variable) %>%
summarise(cv_sp = cv(log(abs(value))))) %>%
ggplot(aes(cv_ind*100, cv_sp*100, label = variable)) +
geom_abline(slope = 1, intercept = 0, col = "darkgrey") +
geom_point() +
ggrepel::geom_text_repel()
```
## Discussion
Carbon- and water-related traits coordination into ecological strategies are consistent within and among species (see @Schmitt2020 for discussion about consistent strategies across levels).
## SIs
<!-- ### PCAs -->
We performed a Principal Component Analysis to investigate the multivariate trait covariation. Using the among PCA, a "classic" PCA, we aim to evaluate trait syndroms characterizing species strategies. For the within PCA, all the gravity centers are placed back at the origin and the individuals are being represented with a maximal variance. We eliminate the species effect to study the individual strategies. The among-PCA searches the axes at the center of gravity and emphasizes on the differences between groups (here, species) whereas the within-PCA searches for the shared-axes in each group.
```{r corrplotTraits, fig.cap="Correlation of leaf traits across individuals in 10 Neotropical tree species. Leaf traits include specific leaf area (SLA), leaf dry matter content (LDMC), leaf fresh thickness (LT), leaf area (LA) leaf chlorophyll content (CC), leaf saturated water content (LSWC), leaf water potential at which leaf cells lose turgor (Ptlp), and leaf minimum conductance (gmin)."}
dplyr::select(ft, -Genus, -Species, -Tree, -SpeciesLong, -DBH, -TWI, -FvFm, -RWC) %>%
cor() %>%
corrplot::corrplot.mixed()
```
```{r pcaArticle, fig.cap="Among (A) and Within-species (B) principal component analysis (A - PCA and B - wPCA) of leaf traits across individuals in 10 Neotropical tree species. Circle colors indicate the species. Leaf traits include specific leaf area (SLA), leaf dry matter content (LDMC), leaf fresh thickness (LT), leaf area (LA) leaf chlorophyll content (CC), leaf saturated water content (LSWC), leaf water potential at which leaf cells lose turgor (Ptlp), and leaf minimum conductance (Gmin)."}
g.among <- autoplot(princomp(~ gmin + LA + LT + LDMC + CC + Ptlp + SLA + LSWC, data = ft, cor = T),
data = ft,
colour = "SpeciesLong", alpha = 0.5, size = 2,
loadings.label.colour = 'black', loadings.label.vjust = 1.1,
loadings = T, loadings.label = T, loadings.colour = 'black', loadings.label.repel = T) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
scale_x_reverse() +
xlab(paste0("PCA 1 (25.16%)")) +
ylab(paste0("PCA 2 (16.67%)")) +
scale_color_discrete("") +
ggtitle("A - Among-species")
g.legend <- cowplot::get_legend(g.among +
theme(legend.position = "bottom", legend.text = element_text(size = rel(0.8))) +
guides(colour = guide_legend(nrow = 3)))
g.among <- g.among + scale_color_discrete(guide = "none")
g.within <- ggplot(ind, aes(x, y, colour = SpeciesLong)) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
geom_point(alpha = 0.5, size = 2) +
geom_segment(data = var, aes(x = 0, y = 0, xend = (x*5),
yend = (y*5)), arrow = arrow(length = unit(1/2, "picas")),
color = "black") +
ggrepel::geom_text_repel(data = var, aes(x = x*5, y = y*5, label = name),
box.padding = 0.8, segment.alpha = 0, color = "black") +
xlab(paste0("within PCA 1 (", round(wPCA$eig/sum(wPCA$eig)*100)[1], "%)")) +
ylab(paste0("within PCA 2 (", round(wPCA$eig/sum(wPCA$eig)*100)[2], "%)")) +
scale_color_discrete(guide = "none") +
ggtitle("B - Within-species")
g <- gridExtra::grid.arrange(g.among, g.within, g.legend, layout_matrix = rbind(c(1,2), c(3,3)), heights = c(3,1))
# ggsave(filename = "~/Téléchargements/Fig3.png", plot = g, bg = "white", height = 4, width = 6)
```
```{r indpcadbh}
autoplot(princomp(~ gmin + LA + LT + LDMC + CC + Ptlp + SLA + LSWC, data = ft, cor = T),
data = ft,
colour = "SpeciesLong", alpha = 0.5, size = "DBH",
loadings.label.size = 6,
loadings.label.colour = 'black', loadings.label.vjust = 1.1,
loadings = T, loadings.label = T, loadings.colour = 'black', loadings.label.repel = T) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
scale_size_continuous(trans = "log") +
scale_color_discrete("") +
ggtitle("Among-species PCA - DBH")
```
```{r indpcatwi}
autoplot(princomp(~ gmin + LA + LT + LDMC + CC + Ptlp + SLA + LSWC, data = ft, cor = T),
data = ft,
colour = "SpeciesLong", alpha = 0.5, size = "TWI",
loadings.label.size = 6,
loadings.label.colour = 'black', loadings.label.vjust = 1.1,
loadings = T, loadings.label = T, loadings.colour = 'black', loadings.label.repel = T) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
scale_size_continuous(trans = "log") +
scale_color_discrete("") +
ggtitle("Among-species PCA - TWI")
```
```{r indpcasp}
autoplot(princomp(~ gmin + LA + LT + LDMC + CC + Ptlp + SLA + LSWC, data = ft, cor = T),
data = ft,
colour = "SpeciesLong", alpha = 0.5,
loadings = F, loadings.label = F) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
scale_color_discrete("") +
ggtitle("Among-species PCA - Species") +
stat_ellipse(aes(group = SpeciesLong, fill = SpeciesLong, col = SpeciesLong), level = 0.5)
```
```{r indwpcadbh}
ggplot(ind, aes(x, y, colour = SpeciesLong)) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
geom_point(aes(size = DBH), alpha = 0.5) +
geom_segment(data = var, aes(x = 0, y = 0, xend = (x*5),
yend = (y*5)), arrow = arrow(length = unit(1/2, "picas")),
color = "black") +
ggrepel::geom_text_repel(data = var, aes(x = x*5, y = y*5, label = name),
box.padding = 0.8, segment.alpha = 0, color = "black") +
xlab(paste0("within PCA 1 (", round(wPCA$eig/sum(wPCA$eig)*100)[1], "%)")) +
ylab(paste0("within PCA 2 (", round(wPCA$eig/sum(wPCA$eig)*100)[2], "%)")) +
scale_size_continuous(trans = "log") +
scale_color_discrete("") +
ggtitle("Within-species PCA - DBH")
```
```{r indwpcatwi}
ggplot(ind, aes(x, y, colour = SpeciesLong)) +
geom_hline(aes(yintercept = 0), col = 'black', linetype = "dotted") +
geom_vline(aes(xintercept = 0), col = 'black', linetype = "dotted") +
geom_point(aes(size = TWI), alpha = 0.5) +
geom_segment(data = var, aes(x = 0, y = 0, xend = (x*5),
yend = (y*5)), arrow = arrow(length = unit(1/2, "picas")),
color = "black") +
ggrepel::geom_text_repel(data = var, aes(x = x*5, y = y*5, label = name),
box.padding = 0.8, segment.alpha = 0, color = "black") +
xlab(paste0("within PCA 1 (", round(wPCA$eig/sum(wPCA$eig)*100)[1], "%)")) +
ylab(paste0("within PCA 2 (", round(wPCA$eig/sum(wPCA$eig)*100)[2], "%)")) +
scale_size_continuous(trans = "log") +
scale_color_discrete("") +
ggtitle("Within-species PCA - TWI")
```
<!-- ### Old interpretations -->
<!-- **Sylvain:** -->
<!-- * We seem to have the classical conservative-acquisitive spectrum or slow-fast spectrum among and within species with SLA opposing LT, CC, LT, and LDMC less visible among than within species -->
<!-- * $g_{min}$ covary with the conservative-acquisitive or slow-fast spectrum with decreased conductance and a better conservation of water and gas for conservative slow species -->
<!-- * The second axis seems to oppose $\pi_{TLP}$ to LA among and within species but less visible among than within species, congruent with @Marechaux2020a but opposed to the result of @Guillemot2022, and might be related to the stature-recruitment spectrum described in @Guillemot2022 -->
<!-- * *I'm uncertain for the moment on how to interpret LSWC.* -->
<!-- **Marion** -->
<!-- * Among-PCA: We recognize the classic LES opposing SLA with LDMC in the first axis while Ptlp drives the second axis with LSWC. -->
<!-- * gmin contributes to both axis. A low gmin can help maintain leaf hydration status (reduced leaks). Higher gmin were observed in fast-growing species which were associated with the investment in small and numerous stomata, which allowed higher carbon assimilation rates but also increased water leaks, with negative impacts on leaf survival under -->
<!-- drought (Machado et al 2021) -->
<!-- * Ptlp is linked with LA: smaller leaves have a more negative πtlp (higher drought tolerance). -->
<!-- * LSWC: According to our analysis, high LSWC is linked to more negative Ptlp. The absolute amount of stored water would contribute to greater drought tolerance, more backed-up water? A lower gmin would be easier to maintain with less stored water. -->
<!-- * we must be careful when interpreting trait co-variation using the among-pca as a general rule of behavior for all individuals within each species when we clearly see another use of the traits for each individual (within PCA). *ex: Protium stevensonii species tend to be more conservative-type species (higer LDMC in the among-PCA) but some individuals of the P. stevensonii explore a different strategy (within-PCA). -->