Calculating community weighted means (CWM) is a useful way to calculate community trait values weighted by abundance of species in that community. Once CWMs are calculated for a datatset, you can run further analysis (ANOVAs, multivariate stats, etc.) to investigate trait patterns for entire communities rather than just individual species.
To calculate CWMs we will be using tidyr and dplyr packages which are part of tidyverse. You should start by installing tidyverse using install.packages("tidyverse") and loading the tidyr and dplyr packages as seen in the code below.
# Load packages
library(tidyr)
library(dplyr)Be sure to set your working directory! HINT -> setwd()
dplyr with summarize to calculate CWMsThere are a number of different ways this can be done, this code is specific for functions avaibale in tidyr and dplyr. First you will need to read-in your data which should consist of all your observations (plots) species names, weights (wts; which is the abundance of each species in the plot), last but not least you will need all of the trait values. Below is an example of what your dataframe should look like:
| Plot | Species | wts | Height..cm. | SLA..cm2.g. | X.N..N.mass. | N15 |
|---|---|---|---|---|---|---|
| 1 | ammophila_breviligulata | 24 | 156.0 | 70.570 | 1.03 | 1.74 |
| 1 | cyperus_esculentes | 20 | 130.0 | 66.726 | 0.87 | 0.85 |
| 1 | panicum_amarum | 7 | 127.0 | 293.776 | 1.27 | -4.14 |
| 1 | setaria_parvifolia | 10 | 77.0 | 138.056 | 0.51 | -2.92 |
| 1 | spartina_patens | 28 | 116.0 | 169.155 | 1.25 | 3.76 |
| 2 | ammophila_breviligulata | 10 | 68.5 | 51.094 | 0.88 | -0.54 |
| 2 | andropogon_virginicus | 3 | 102.5 | 78.732 | 0.86 | 0.70 |
| 2 | conyza_canadensis | 10 | 58.0 | 141.304 | 1.63 | -2.61 |
Once your data is loaded as a new dataframe, we can start coding for the CWM calculations. Like mentioned before, we will be using different functions in tidyr and dplyr. First, we are going to want to direct the result to a new dataframe so that we can check the result is correct (I’m naming the new df summarize.nutnet.cwm). If you look at the code chunk below you will notice an operator that may be new to you (%>%) this is called “piping”. All it does is takes the output of one statement and makes it the input of the next statement. It is a commonly used operator in dplyr.
In the example below, we are taking the nutnet.cwm.traits (whose output is just the dataframe) and using it as an input for the group_by() function. Grouping by ‘Plot’ tells R that the communities are coded by plot numbers, this way plots stay separated and are all properly aggregated in the result dataframe. This is important in this dataset because plots have different treatments. We then use the output of group_by(Plot) as the input of summarize function. The summarize function is how we can pull together different statistical functions. We can use the weighted.mean() function to code for how trait averages should be weighted.
Within the summarize() statement you have to first identify how you want you summarization organized ( here I use; Height_cwm, SLA_cwm, Nmass_cwm, etc.). Then you will define the statistical function you want R to perform, we want weighted.mean. In the weighted.mean function you have to identify the column of the trait you are calculating and the column where R can find you weight values (wts).
# Calculating CWM using dplyr and tidyr functions
summarize.nutnet.cwm <- # New dataframe where we can inspect the result
nutnet.cwm.trait %>% # First step in the next string of statements
group_by(Plot) %>% # Groups the summary file by Plot number
summarize( # Coding for how we want our CWMs summarized
Height_cwm = weighted.mean(Height..cm., wts), # Actual calculation of CWMs
SLA_cwm = weighted.mean(SLA..cm2.g., wts),
Nmass_cwm = weighted.mean(X.N..N.mass., wts),
N15_cwm = weighted.mean(N15, wts),
Cmass_cwm = weighted.mean(X.C..Cmass., wts),
C13_cwm = weighted.mean(C13, wts),
CNratio_cwm = weighted.mean(C.N..ratio., wts)
)Your new summarize.nutnet.cwm dataframe should be added to the data environment. It should look something like this:
| Plot | Height_cwm | SLA_cwm | Nmass_cwm | N15_cwm | Cmass_cwm | C13_cwm |
|---|---|---|---|---|---|---|
| 1 | 126.41573 | 125.8599 | 1.0237079 | 1.189438 | 47.32360 | -16.44775 |
| 2 | 69.59302 | 141.8836 | 1.2111628 | -1.539535 | 47.04233 | -19.99930 |
| 3 | 70.21974 | 172.8762 | 0.8438184 | -1.069107 | 46.33399 | -15.35991 |
| 4 | 101.78113 | 145.0338 | 0.8855969 | 1.372054 | 47.67410 | -20.22375 |
| 5 | 97.72666 | 130.7514 | 0.8432070 | 2.198539 | 46.49345 | -15.74620 |
You should notice that you no longer have repeating plot numbers because we grouped by plot number. You should also notice that species have been removed, they are no longer relevant because our trait values have been community weighted.
As a final step you should write your result datafrome as a .csv and save it so that it can be easily read into R or other statistical software if you are interested in running statistical tests on the data.
write.csv(summarize.nutnet.cwm, "nutnet_trait_cwm.csv")# Load packages
library(tidyr)
library(dplyr)
# SET WORKING DIRECTORY!
# Calculating community weighted means and summarizing by plot - using dplyr
nutnet.traits.wts <- read.csv("fnxl.trait.nutnet_wts.csv")
summarize.nutnet.cwm <-
nutnet.traits.wts %>%
group_by(Plot) %>%
summarize(SLA_cwm = weighted.mean(SLA..cm2.g., wts),
Nmass_cwm = weighted.mean(X.N..N.mass.,wts),
N15_cwm = weighted.mean(N15,wts),
Cmass_cwm = weighted.mean(X.C..Cmass.,wts),
C13_cwm = weighted.mean(C13,wts),
CNratio_cwm = weighted.mean(C.N..ratio.,wts)
)
write.csv(summarize.nutnet.cwm, "nutnet_trait_cwm.csv")