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.

Installing and loading packages

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()

Using dplyr with summarize to calculate CWMs

There 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:

Ex. Dataframe
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)
)

Checking out your result dataframe

Your new summarize.nutnet.cwm dataframe should be added to the data environment. It should look something like this:

Ex. Result Dataframe
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.

Writing .csv of new CWMs

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")

Now try with your own data!

# 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")