Advanced climwin

Liam D. Bailey and Martijn van de Pol

2020-05-26

In our introductory vignette we described the basic features available in the climwin package. Below, we will look in more detail at more advanced features available to users. We will cover:


More complex baseline models

In our previous vignette we fitted a simple linear model to be used as our baseline and studied the linear effect of temperature; however, in many cases users may want to design more complex baseline models. We will discuss a number of examples here.

Adding interactions with climate

Until now, we have assumed that the effects of climate do not interact with any other variables. This may not always be the case. As of v1.1.0, users can build a custom model structure with the ability to include interactions between climate and other variables. In our example using the Mass dataset, we might expect the effect of temperature on chick mass to vary with the average age of the mothers.

Firstly, it is necessary to create a variable called ‘climate’ in the biological dataset. The variable ‘climate’ doesn’t need to contain any information, it is simply a placeholder to specify where climate data will be included in the model.

NOTE: It is necessary to call the new object ‘climate’ so that climwin can distinguish this variable from others. Other variable names will not work.

Mass$climate <- 1

Now that we have our ‘climate’ variable, we can add it into our baseline model. We can then specify how we want our climatic data to interact with other variables in the model.

baseline = lm(Mass ~ climate*Age, data = Mass)

In this example, climatic data from each tested climate window will be included in the model interacting with parent age.

Interaction <- slidingwin(xvar = list(Temp = MassClimate$Temp),
                          cdate = MassClimate$Date,
                          bdate = Mass$Date,
                          baseline = lm(Mass ~ climate*Age, data = Mass),
                          cinterval = "day",
                          range = c(150, 0),
                          type = "absolute", refday = c(20, 05),
                          stat = "mean",
                          func = "lin")

If we look at the best model from this analysis, we can see the interaction between temperature and age included in the model coefficients.

summary(Interaction[[1]]$BestModel)
Call:
lm(formula = yvar ~ climate + Age + climate:Age, data = modeldat)

Residuals:
    Min      1Q  Median      3Q     Max 
-5.6266 -1.5716  0.2878  1.6086  4.7510 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 170.2628     7.1678  23.754  < 2e-16 ***
climate      -5.5466     0.9200  -6.029 3.32e-07 ***
Age          -2.6046     2.6603  -0.979    0.333    
climate:Age   0.4024     0.3395   1.185    0.242    
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.449 on 43 degrees of freedom
Multiple R-squared:  0.7778,    Adjusted R-squared:  0.7623 
F-statistic: 50.17 on 3 and 43 DF,  p-value: 4.267e-14

Mixed effects models

It will often be important to fit models with random effects terms (e.g. Individual ID). climwin includes functionality for mixed effects models using both lme4 and nlme. Random effects terms can easily be added to the baseline model. We can use the ‘Offspring’ dataset in R as an example.

baseline = lmer(Offspring ~ 1 + (1|BirdID), data = Offspring, REML = F)

NOTE: Mixed effects models should be fitted using a maximum likelihood approach (i.e. REML = FALSE). If this is not specified in the baseline model, climwin* will make this adjustment internally.*

In a more specific scenario, we may want to include our climatic variable as a random effect in our model. As above, this can be done by creating a ‘climate’ variable in our dataset and including it in the baseline model.

baseline = lmer(Mass ~ 1 + (1|climate), data = Mass, REML = F)


Climate thresholds

Many studies, may be interested in testing climate windows using climatic thresholds. When testing climatic thresholds, we assume that a biological response is driven by days that surpass a particular climatic value. For example, seed germination may be influenced by the number of days over 30 degrees. Alternatively, temperature may only influence organism survival when it falls below freezing. A common example of such a climate threshold is growing degree days often used in the study of plant systems.

These can be achieved in slidingwin using the three parameters ‘upper’, ‘lower’ and, ‘binary’. When a value is provided for the parameter ‘upper’, slidingwin will create a new climate dataset where all values equal to or below this threshold are set at 0. Similarly, when a value is set for ‘lower’, all values equal to or above this threshold will be set at 0. When values are provided for both ‘upper’ and ‘lower’, all values that fall outside these two threshold will be set at 0.

upper = 30

Date Original temperature Threshold temperature
01/06/2015 25.9 0
02/06/2015 24.0 0
03/06/2015 32.5 32.5
04/06/2014 28.1 0
05/06/2014 30.5 30.5
06/06/2014 30.0 0
07/06/2014 31.2 31.2
08/06/2014 27.0 0

upper = 30 lower = 25

Date Original temperature Threshold temperature
01/06/2015 25.9 25.9
02/06/2015 24.0 0
03/06/2015 32.5 0
04/06/2014 28.1 28.1
05/06/2014 30.5 0
06/06/2014 30.0 0
07/06/2014 31.2 0
08/06/2014 27.0 27.0

In some circumstances we may assume that all values past the climatic threshold will have an equally large impact on the biological response. In this case, we would set ‘binary’ to TRUE so that all non-zero values are set at 1. By default however, ‘binary’ will be set at FALSE, so that all values past the climatic threshold keep their original value.

upper = 30 binary = TRUE

Date Original temperature Threshold temperature
01/06/2015 25.9 0
02/06/2015 24.0 0
03/06/2015 32.5 1
04/06/2014 28.1 0
05/06/2014 30.5 1
06/06/2014 30.0 0
07/06/2014 31.2 1
08/06/2014 27.0 0

A worked example

Below we will provide a worked example using the Mass and MassClimate dataset. In this example, lets imagine we are interested in testing the impact of the number of days above freezing on our mass response variable. To do this we would set both our ‘upper’ and ‘binary’ parameters.

upper = 0 binary = TRUE

As we are interested in measuring the number of days above freezing, we set our stat parameter to ‘sum’. Otherwise, we used model parameter values identical to our earlier vignette.

library(climwin)
MassWin <- slidingwin(xvar = list(Temp = MassClimate$Temp),
                      cdate = MassClimate$Date,
                      bdate = Mass$Date,
                      baseline = lm(Mass ~ 1, data = Mass),
                      cinterval = "day",
                      range = c(150, 0),
                      upper = 0, binary = TRUE,
                      type = "absolute", refday = c(20, 05),
                      stat = "sum",
                      func = "lin")

When we examine the best model data, we can see that our climate data is now count data.

head(MassWin[[1]]$BestModelData)
Yvar climate
140 0
138 0
136 1
135 2
134 0
134 0

Biological measurements grouped across two years

Many long-term datasets that will be suitable for climwin are likely to be measured during Northern hemisphere spring/summer (e.g. breeding data). These biological records are measured during the middle of the year, meaning that biological records can be easily grouped by year. Yet in other circumstances biological measurements will fall across two years, particularly in Southern hemisphere species where spring/summer falls across the new year period [e.g., 1].

This can cause issues when fitting ‘absolute’ climate windows. As described in the introductory vignette, ‘absolute’ windows will use a set reference day for all biological records. Where biological measurements cross two years however, measurements from the same breeding season can be split up. In the table below, where a reference day of November 1st is used, all those measurements taken at the start of the breeding season are given a date of November 1st 2014 while all values following the new year are set at November 1st 2015. This is obviously unrealistic, as biological measurements in January 2015 cannot be impacted by climatic conditions that will occur 11 months in the future!

Date Reference Date
05/11/2014 01/11/2014
10/11/2014 01/11/2014
01/12/2014 01/11/2014
12/12/2014 01/11/2014
01/01/2015 01/11/2015
07/01/2015 01/11/2015

As a solution, climwin includes a ‘cohort’ parameter that allows users to specify which biological measurements should be grouped together (e.g. when they are from same breeding season). Each biological record should be given a cohort level (see below), which is taken into account when setting the reference day for climate window analyses.

Date Cohort Reference Date
05/11/2014 2014 01/11/2014
10/11/2014 2014 01/11/2014
01/12/2014 2014 01/11/2014
12/12/2014 2014 01/11/2014
01/01/2015 2014 01/11/2014
07/01/2015 2014 01/11/2014

Some example code showing how the ‘cohort’ argument can be used is provided below. In this example we use data from a southern hemisphere breeding bird.

SizeWin <- slidingwin(xvar = list(Temp = SizeClimate$Temperature),
                      cdate = SizeClimate$Date,
                      bdate = Size$Date,
                      baseline = lm(Size ~ 1, data = Size),
                      cohort = Size$Cohort,
                      cinterval = "day",
                      range = c(150, 0),
                      type = "absolute", refday = c(01, 10),
                      stat = "mean",
                      func = "lin")

Spatial replication

To detect climate signals using climwin can often require large amounts of data, particularly if the relationship between climate and biological response is weak [2]. To obtain the required data through temporal replication requires the collection of data over multiple years, often decades; however, spatial replication may also allow users to expand their sample size over a shorter period by collecting data from multiple sites/populations.

Using spatial replication assumes that the relationship between the biological response and climatic predictor is consistent across the different measured populations. Where this assumption is valid, spatial replication can help expand the amount of data available for climwin analyses.

A worked example

Spatially replicated data can be analysed using the slidingwin function with the addition of the ‘spatial’ parameter. As with regular slidingwin analysis, analysis with spatial replication requires a separate biological and climate dataset. However, these datasets should now contain an additional variable which specifies the site at which biological and climate data were collected. Below, we have called this parameter ‘SiteID’.

Date Mass (g) SiteID
04/06/2015 120 A
05/06/2015 123 A
07/06/2015 110 B
07/06/2015 140 A
06/06/2015 138 B
Date Temperature SiteID
01/06/2015 15 A
02/06/2015 16 A
03/06/2015 12 A
04/06/2015 18 A
05/06/2015 20 A
06/06/2015 23 A
07/06/2015 21 A
01/06/2015 10 B
02/06/2015 12 B
03/06/2015 9 B
04/06/2015 5 B
05/06/2015 13 B
06/06/2015 10 B
07/06/2015 11 B

NOTE: The climate dataset for spatially replicated climwin analysis will often include duplicate dates. In a regular climwin analysis this will lead to errors.

With these new datasets, we can carry out a slidingwin analysis with the addition of a ‘spatial’ parameter.

MassWin <- slidingwin(xvar = list(Temp = Climate$Temp),
                      cdate = Climate$Date,
                      bdate = Biol$Date,
                      baseline = lm(Mass ~ 1, data = Biol),
                      cinterval = "day",
                      range = c(150, 0),
                      type = "absolute", refday = c(20, 05),
                      stat = "mean",
                      func = "lin", spatial = list(Biol$SiteID, Climate$SiteID))

The ‘spatial’ parameter is a list item that includes the SiteID variable for the biological and climate datasets respectively. When slidingwin fits individual climate windows, each biological record will be matched with the climate data from the corresponding site.


weightwin function

When we run regular slidingwin analyses we assume that all days within the climate window are evenly weighted (see figure below). While this is often a convenient assumption, it can be considered biologically unrealistic.

This assumption can be a problem when we are considering more complex hypotheses. For example, we may be interested in looking for climate windows where the importance of climate decays slowly over time. The function weightwin allows users to fit either Weibull (below left) and generalised extreme value (GEV; below right) weight distributions to climate data as an alternative to a uniform weight distribution, thus removing the assumption of uniformity.

Instead of varying the start and end date of climate windows like slidingwin, weightwin instead uses an optimisation function to vary the shape, scale and location of either of these weight functions. Each weight function is then applied to the climate data, which is then used to produce a climate model and \(\Delta AICc\) value. Therefore, although the method of optimising climate data is different, the ultimate output (i.e. \(\Delta AICc\) of a climate window compared to a null model) is the same.

A worked example

weightwin can often be useful to use with climate data where we have already identified a climate window using slidingwin. Here, we will use weightwin to further investigate the Mass and MassClimate data included with the climwin package.

The basic parameters in weightwin are the same as slidingwin (though note the absence of the ‘stat’ parameter). In addition however, we must designate which weight distribution we want to use. In this case we consider a Weibull function.

weightfunc = "W"

Next, we must set the location, scale and shape values for the starting distribution that will be used to begin the optimisation procedure. The default values (3, 0.2, 0) are often appropriate for fitting Weibull distributions. However, you can explore different parameter values using the explore function.

The optimisation function used in weightwin has the potential to get ‘stuck’ during the optimisation routine. With the argument ‘n’ we can run our weightwin analysis multiple times to ensure we are finding the true optimal weight distribution.

n = 5

set.seed(100)

weight <- weightwin(n = 5, xvar = list(Temp = MassClimate$Temp), cdate = MassClimate$Date, 
                    bdate = Mass$Date, 
                    baseline = lm(Mass ~ 1, data = Mass), 
                    range = c(150, 0), 
                    func = "lin", type = "absolute", 
                    refday = c(20, 5), 
                    weightfunc = "W", cinterval = "day",
                    par = c(3, 0.2, 0))

If we look at the iterations object in the weightwin output, we can see the outcome of all 5 iterations.

weight$iterations
start_shape start_scale start_location deltaAICc
3.0 0.2 0.0 -68.21592
3.1 2.7 -4.5 -68.21592
0.7 2.7 -5.1 -68.21592
8.1 3.8 -4.5 -68.21592
1.8 6.3 -1.2 -35.34690

start_shape, start_scale and start_location show the starting parameters used for each iteration of weightwin. In the deltaAICc column we can see the outcomes of the different iterations. While 4 of the iterations reached the same peak, the 5th got stuck during the optimisation routine. This is a useful demonstration of why multiple iterations are important.

It seems that there is a clear peak that our optimisation routine has been able to identify, next we can visualise that peak using the explore function.

We can use the shape, scale and location parameters of the first iteration to fit our plot.

weight[[1]]$WeightedOutput
deltaAICc start_shape start_scale start_location
-68.21592 2.17 0.35 0.00

In the above plot, we can see that the importance of temperature declines rapidly either side of the peak.

If we compare this value to the delta AICc obtained from the slidingwin function we can see that the weightwin function is better able to explain variation in our mass parameter as we have removed the assumption of a uniform weight distribution.

slidingwin weightwin
-64.81 -68.22

Pros and cons

weightwin can provide greater detail on the relationship between climate and the biological response, such as the occurrence of exponential functions. Additionally, by using more diverse weight distributions, weightwin will often generate models with better \(\Delta AICc\) values, which may be especially important when users are most interested in achieving high explanatory power. Furthermore, by using an optimisation routine weightwin often tests far fewer models than slidingwin, allowing for more rapid analysis.

Despite these benefits, weightwin will not always be the most appropriate function for all scenarios. Firstly, the nature of the fitted weight distributions means that weightwin can only detect single climate signals, which forces users to detect and compare potential climate signals with separate analyses. This is not an issue using slidingwin.

Secondly, weightwin can be a more technically complex process. While the above example works easily, in other scenarios the optimisation procedures may often get stuck on false optima or fail to converge. In these cases, users may be required to test different starting parameters and adjust optimisation characteristics such as step size. Often this procedure can be inhibitive for users with less technical knowledge.

Finally, weightwin can only be used for testing mean climate, with no capacity to consider other aggregate statistics. Therefore, whether one chooses to use weightwin or slidingwin will largely depend on the summary statistic used, the level of detail desired, and the user’s technical knowledge.


To ask additional questions or report bugs please e-mail:

or visit our google group