rveganrda

Repeated measures in RDA (aka "fixed" or "random" effects): why does Condition remove the contraints?


I'm running an RDA on a set of measures that have been taken in a landscape. For each landscape window, we've some parameters that describe the landscape there, and we've conducted, say, 10 measures in each window. The window just has an ID.

vegan's way to add fixed or random effect is with Condition. I have to admit I do not understand the implementation. If I add the window label as a Condition, the constrained part of the RDA disappeares, and all I seem to get is a PCA.

By chance, I realised that if I added the window labels as numbers, I do get a constrained part in the output.

My questions are:

  1. Can this design be analysed with an RDA, taking repeated measures into account? Or would I just have to average over the 10 measures in each window and analyse 8 instead of 80 rows?
  2. If an RDA can analyse the model with repeated measures, should I use the window ID's as factors (characters) or would it be OK to treat them as integers? The value of the integer doesn't have any signification other than a label.

Reproducible code:

#simulate the measures
traits <- as.data.frame(matrix(runif(n=800, min=0, max=1), nrow=80))

#simulate the landscape
A=c(array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10))
B=c(array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10))
C=c(array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10), array(runif(n=1, min=0, max=1), dim = 10))
window=c(array(sample(200,1), dim = 10), array(sample(200,1), dim = 10), array(sample(200,1), dim = 10), array(sample(200,1), dim = 10), array(sample(200,1), dim = 10), array(sample(200,1), dim = 10), array(sample(200,1), dim = 10), array(sample(200,1), dim = 10))
landscape = cbind.data.frame(A, B, C, window=as.character(window))

If I analyse the measures with an RDA ( rda(traits ~ A + B + C, data=landscape) ), I get the following, as expected:

Call: rda(formula = traits ~ A + B + C, data = landscape)

-- Model Summary --

              Inertia Proportion Rank
Total         0.79506    1.00000     
Constrained   0.03243    0.04079    3
Unconstrained 0.76263    0.95921   10

...

When I run the model (rda(traits ~ A + B + C + Condition(window), data=landscape)), the constraints are not reported:

Call: rda(formula = traits ~ A + B + C + Condition(window), data =
landscape)

-- Model Summary --

              Inertia Proportion Rank
Total         0.85687    1.00000     
Conditional   0.06926    0.08083    7
Unconstrained 0.78762    0.91917   10

...

And I only get PCA axes (no RDA).

When the "conditioning" variable is an integer, the constrained part reappears :

landscape = cbind.data.frame(A, B, C, as.integer(window))
rda(traits ~ A + B + C + Condition(window), data=landscape)
Call: rda(formula = traits ~ A + B + C + Condition(window), data =
landscape)

-- Model Summary --

               Inertia Proportion Rank
Total         0.856874   1.000000     
Conditional   0.009466   0.011047    1
Constrained   0.029108   0.033970    3
Unconstrained 0.818300   0.954983   10

...

Solution

  • In your model traits are constant within levels of factor window. If you know the window, you know all traits. Therefore traits do not add any independent information to window. When you first remove ("partial out", "condition on") the effect of window, nothing is left to explain by traits, and therefore the constrained component does not exist. We should issue a loud warning in this case, but it seems that we forgot to do so.

    The reason why you got different results with as.integer(window) is that this model is wrong: it does not treat window as a factor with levels, but as an ordered continuous numerical variable.