Title: | Functions for Generating Restricted Permutations of Data |
---|---|
Description: | A set of restricted permutation designs for freely exchangeable, line transects (time series), and spatial grid designs plus permutation of blocks (groups of samples) is provided. 'permute' also allows split-plot designs, in which the whole-plots or split-plots or both can be freely-exchangeable or one of the restricted designs. The 'permute' package is modelled after the permutation schemes of 'Canoco 3.1' (and later) by Cajo ter Braak. |
Authors: | Gavin L. Simpson [aut, cph, cre] , R Core Team [cph], Douglas M. Bates [ctb], Jari Oksanen [ctb] |
Maintainer: | Gavin L. Simpson <[email protected]> |
License: | GPL-2 |
Version: | 0.9-8 |
Built: | 2024-11-10 03:14:07 UTC |
Source: | https://github.com/gavinsimpson/permute |
allPerms
is a utility function to return the set of
permutations for a given R object and a specified permutation design.
allPerms(n, control = how(), check = TRUE) ## S3 method for class 'allPerms' summary(object, ...) ## S3 method for class 'allPerms' as.matrix(x, ...) as.allPerms(object, control)
allPerms(n, control = how(), check = TRUE) ## S3 method for class 'allPerms' summary(object, ...) ## S3 method for class 'allPerms' as.matrix(x, ...) as.allPerms(object, control)
n |
the number of observations or an 'object' from which the
number of observations can be determined via |
control |
a list of control values describing properties of the
permutation design, as returned by a call to
|
check |
logical; should |
object |
for |
... |
arguments to other methods. |
x |
an object of class |
Function allPerms
enumerates all possible permutations for the
number of observations and the selected permutation scheme. It has
print
and summary
methods. allPerms
returns a matrix containing all possible permutations, possibly
containing the observed ordering (if argument observed
is
TRUE
). The rows of this matrix are the various permutations and
the columns reflect the number of samples.
With free permutation designs, and restricted permutation schemes with
large numbers of observations, there are a potentially huge number of
possible permutations of the samples. It would be inefficient, not to
mention incredibly time consuming, to enumerate them all. Storing all
possible permutations would also become problematic in such cases. To
control this and guard against trying to evaluate too large a number
of permutations, if the number of possible permutations is larger than
getMaxperm(control)
, allPerms
exits with an error.
The as.matrix
method sets the control
and seed
attributes to NULL
and removes the "permutationMatrix"
class, resulting in a standard matrix object.
For allPerms
, and object of class "allPerms"
, a matrix
whose rows are the set of all possible permutations for the supplies
number of observations and permutation scheme selected. The matrix has
two additional attributes control
and
observed
. Attribute control
contains the argument
control
(possibly updated via check
). Attribute
observed
contains argument observed
.
If permuting the strata themselves, a balanced design is required (the
same number of observations in each level of strata
. This is
common to all functions in the package.
Gavin Simpson
## allPerms can work with a vector vec <- c(3,4,5) allPerms(vec) ## free permutation ## enumerate all possible permutations for a more complicated ## design fac <- gl(2,6) ctrl <- how(within = Within(type = "grid", mirror = FALSE, constant = TRUE, nrow = 3, ncol = 2), plots = Plots(strata = fac)) Nobs <- length(fac) numPerms(seq_len(Nobs), control = ctrl) ## 6 (tmp <- allPerms(Nobs, control = update(ctrl, observed = TRUE))) (tmp2 <- allPerms(Nobs, control = ctrl)) ## turn on mirroring ##ctrl$within$mirror <- TRUE ctrl <- update(ctrl, within = update(getWithin(ctrl), mirror = TRUE)) numPerms(seq_len(Nobs), control = ctrl) (tmp3 <- allPerms(Nobs, control = update(ctrl, observed = TRUE))) (tmp4 <- allPerms(Nobs, control = ctrl)) ## prints out details of the permutation scheme as ## well as the matrix of permutations summary(tmp3) summary(tmp4)
## allPerms can work with a vector vec <- c(3,4,5) allPerms(vec) ## free permutation ## enumerate all possible permutations for a more complicated ## design fac <- gl(2,6) ctrl <- how(within = Within(type = "grid", mirror = FALSE, constant = TRUE, nrow = 3, ncol = 2), plots = Plots(strata = fac)) Nobs <- length(fac) numPerms(seq_len(Nobs), control = ctrl) ## 6 (tmp <- allPerms(Nobs, control = update(ctrl, observed = TRUE))) (tmp2 <- allPerms(Nobs, control = ctrl)) ## turn on mirroring ##ctrl$within$mirror <- TRUE ctrl <- update(ctrl, within = update(getWithin(ctrl), mirror = TRUE)) numPerms(seq_len(Nobs), control = ctrl) (tmp3 <- allPerms(Nobs, control = update(ctrl, observed = TRUE))) (tmp4 <- allPerms(Nobs, control = ctrl)) ## prints out details of the permutation scheme as ## well as the matrix of permutations summary(tmp3) summary(tmp4)
Utility functions to return the set of all permutations under
different designs. For most practical applications, i.e. to combine
designs permuting blocks and/or within blocks function
allPerms
will be required.
allFree(n, v = seq_len(n)) allSeries(n, nperms, mirror = FALSE) allGrid(n, nperms, nr, nc, mirror, constant) allStrata(n, control)
allFree(n, v = seq_len(n)) allSeries(n, nperms, mirror = FALSE) allGrid(n, nperms, nr, nc, mirror, constant) allStrata(n, control)
n |
the number of observations. |
v |
numeric; vector of indices. Default is |
nperms |
numeric; number of possible permutations. |
mirror |
logical; mirroring of permutations allowed? |
nr , nc
|
integer; number of rows and columns of grid designs. |
constant |
logical; same permutation within each block? |
control |
a list of control values describing properties of the
permutation design, as returned by a call to |
These are utility functions and aren't designed for casual
use. allPerms
should be used instead.
Details on usage of these functions can be found in
allPerms
.
A matrix of all possible permutations of n
observations or of
v
, given the provided options.
Gavin Simpson
check
provides checking of permutation schemes for
validity. permuplot
produces a graphical representation of the
selected permutation design.
check(object, control = how(), quietly = FALSE) ## S3 method for class 'check' summary(object, ...)
check(object, control = how(), quietly = FALSE) ## S3 method for class 'check' summary(object, ...)
object |
an R object. See Details for a complete description,
especially for |
control |
a list of control values describing properties of the
permutation design, as returned by a call to |
quietly |
logical; should messages by suppressed? |
... |
arguments to other methods. |
check
is a utility functions for working with the new
permutation schemes available in shuffle
.
check
is used to check the current permutation schemes
against the object to which it will be applied. It calculates the
maximum number of possible permutations for the number of observations
in object
and the permutation scheme described by
control
. The returned object contains component control
,
an object of class "how"
suitably modified if
check
identifies a problem.
The main problem is requesting more permutations than is possible with
the number of observations and the permutation design. In such cases,
nperm
is reduced to equal the number of possible permutations,
and complete enumeration of all permutations is turned on
(control$complete
is set to TRUE
).
Alternatively, if the number of possible permutations is low, and
less than control$minperm
, it is better to enumerate all
possible permutations, and as such complete enumeration of all
permutations is turned on (control$complete
is set to
TRUE
). This guarantees that permutations are all unique and
there are no duplicates.
For check
a list containing the maximum number of
permutations possible and an object of class "how"
.
Gavin L. Simpson
## only run this example if vegan is available if (suppressPackageStartupMessages(require("vegan"))) { ## use example data from ?pyrifos in package vegan example(pyrifos) ## Demonstrate the maximum number of permutations for the pyrifos data ## under a series of permutation schemes ## no restrictions - lots of perms CONTROL <- how(within = Within(type = "free")) (check1 <- check(pyrifos, CONTROL)) ## summary(check1) ## no strata but data are series with no mirroring, so 132 permutations CONTROL <- how(within = Within(type = "series", mirror = FALSE)) check(pyrifos, CONTROL) ## no strata but data are series with mirroring, so 264 permutations CONTROL <- how(within = Within(type = "series", mirror = TRUE)) check(pyrifos, control = CONTROL) ## unrestricted within strata check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "free"))) ## time series within strata, no mirroring check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", mirror = FALSE))) ## time series within strata, with mirroring check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", mirror = TRUE))) ## time series within strata, no mirroring, same permutation ## within strata check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", constant = TRUE))) ## time series within strata, with mirroring, same permutation ## within strata check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", mirror = TRUE, constant = TRUE))) ## permute strata check(pyrifos, how(plots = Plots(strata = ditch, type = "free"), within = Within(type = "none"))) } ## this should also also for arbitrary vectors vec1 <- check(1:100) vec2 <- check(1:100, how()) all.equal(vec1, vec2) vec3 <- check(1:100, how(within = Within(type = "series"))) all.equal(100, vec3$n) vec4 <- check(1:100, how(within = Within(type= "series", mirror = TRUE))) all.equal(vec4$n, 200) ## enumerate all possible permutations fac <- gl(2,6) ctrl <- how(plots = Plots(strata = fac), within = Within(type = "grid", mirror = FALSE, constant = TRUE, nrow = 3, ncol = 2)) check(1:12, ctrl) numPerms(1:12, control = ctrl) (tmp <- allPerms(12, control = update(ctrl, observed = TRUE))) (tmp2 <- allPerms(12, control = ctrl)) ## turn on mirroring ctrl <- update(ctrl, within = update(getWithin(ctrl), mirror = TRUE)) numPerms(1:12, control = ctrl) (tmp3 <- allPerms(12, control = update(ctrl, observed = TRUE))) (tmp4 <- allPerms(12, control = ctrl)) ## prints out details of the permutation scheme as ## well as the matrix of permutations summary(tmp) summary(tmp2) ## different numbers of observations per level of strata fac <- factor(rep(1:3, times = c(3,2,2))) ## free permutations in levels of strata numPerms(7, how(within = Within(type = "free"), plots = Plots(strata = fac, type = "none"))) allPerms(7, how(within = Within(type = "free"), plots = Plots(strata = fac))) ## series permutations in levels of strata ctrl <- how(within = Within(type = "series"), plots = Plots(strata = fac)) numPerms(7, control = ctrl) allPerms(7, control = ctrl)
## only run this example if vegan is available if (suppressPackageStartupMessages(require("vegan"))) { ## use example data from ?pyrifos in package vegan example(pyrifos) ## Demonstrate the maximum number of permutations for the pyrifos data ## under a series of permutation schemes ## no restrictions - lots of perms CONTROL <- how(within = Within(type = "free")) (check1 <- check(pyrifos, CONTROL)) ## summary(check1) ## no strata but data are series with no mirroring, so 132 permutations CONTROL <- how(within = Within(type = "series", mirror = FALSE)) check(pyrifos, CONTROL) ## no strata but data are series with mirroring, so 264 permutations CONTROL <- how(within = Within(type = "series", mirror = TRUE)) check(pyrifos, control = CONTROL) ## unrestricted within strata check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "free"))) ## time series within strata, no mirroring check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", mirror = FALSE))) ## time series within strata, with mirroring check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", mirror = TRUE))) ## time series within strata, no mirroring, same permutation ## within strata check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", constant = TRUE))) ## time series within strata, with mirroring, same permutation ## within strata check(pyrifos, control = how(plots = Plots(strata = ditch), within = Within(type = "series", mirror = TRUE, constant = TRUE))) ## permute strata check(pyrifos, how(plots = Plots(strata = ditch, type = "free"), within = Within(type = "none"))) } ## this should also also for arbitrary vectors vec1 <- check(1:100) vec2 <- check(1:100, how()) all.equal(vec1, vec2) vec3 <- check(1:100, how(within = Within(type = "series"))) all.equal(100, vec3$n) vec4 <- check(1:100, how(within = Within(type= "series", mirror = TRUE))) all.equal(vec4$n, 200) ## enumerate all possible permutations fac <- gl(2,6) ctrl <- how(plots = Plots(strata = fac), within = Within(type = "grid", mirror = FALSE, constant = TRUE, nrow = 3, ncol = 2)) check(1:12, ctrl) numPerms(1:12, control = ctrl) (tmp <- allPerms(12, control = update(ctrl, observed = TRUE))) (tmp2 <- allPerms(12, control = ctrl)) ## turn on mirroring ctrl <- update(ctrl, within = update(getWithin(ctrl), mirror = TRUE)) numPerms(1:12, control = ctrl) (tmp3 <- allPerms(12, control = update(ctrl, observed = TRUE))) (tmp4 <- allPerms(12, control = ctrl)) ## prints out details of the permutation scheme as ## well as the matrix of permutations summary(tmp) summary(tmp2) ## different numbers of observations per level of strata fac <- factor(rep(1:3, times = c(3,2,2))) ## free permutations in levels of strata numPerms(7, how(within = Within(type = "free"), plots = Plots(strata = fac, type = "none"))) allPerms(7, how(within = Within(type = "free"), plots = Plots(strata = fac))) ## series permutations in levels of strata ctrl <- how(within = Within(type = "series"), plots = Plots(strata = fac)) numPerms(7, control = ctrl) allPerms(7, control = ctrl)
Simple functions to allow abstracted access to components of a
permutation design, for example as returned by
how
. Whilst many of these are very simple index
opertations on a list, using these rather than directly accessing that
list allows the internal representation of the permutation design to
change without breaking code.
getAllperms(object, ...) getBlocks(object, ...) getComplete(object, ...) getConstant(object, ...) getCol(object, ...) getDim(object, ...) getMake(object, ...) getMaxperm(object, ...) getMinperm(object, ...) getMirror(object, ...) getNperm(object, ...) getObserved(object, ...) getPlots(object, ...) getRow(object, ...) getStrata(object, ...) getType(object, ...) getWithin(object, ...) getControl(object, ...) getHow(object, ...) ## S3 method for class 'how' getAllperms(object, ...) ## S3 method for class 'how' getBlocks(object, ...) ## S3 method for class 'how' getCol(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getCol(object, ...) ## S3 method for class 'Within' getCol(object, ...) ## S3 method for class 'how' getComplete(object, ...) ## S3 method for class 'how' getConstant(object, ...) ## S3 method for class 'Within' getConstant(object, ...) ## S3 method for class 'how' getDim(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getDim(object, ...) ## S3 method for class 'Within' getDim(object, ...) ## S3 method for class 'how' getMake(object, ...) ## S3 method for class 'how' getMaxperm(object, ...) ## S3 method for class 'how' getMinperm(object, ...) ## S3 method for class 'how' getMirror(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getMirror(object, ...) ## S3 method for class 'Within' getMirror(object, ...) ## S3 method for class 'how' getNperm(object, ...) ## S3 method for class 'how' getObserved(object, ...) ## S3 method for class 'how' getPlots(object, ...) ## S3 method for class 'how' getRow(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getRow(object, ...) ## S3 method for class 'Within' getRow(object, ...) ## S3 method for class 'how' getStrata(object, which = c("plots", "blocks"), drop = TRUE, ...) ## S3 method for class 'Plots' getStrata(object, drop = TRUE, ...) ## S3 method for class 'how' getType(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getType(object, ...) ## S3 method for class 'Within' getType(object, ...) ## S3 method for class 'how' getWithin(object, ...) ## S3 method for class 'allPerms' getControl(object, ...)
getAllperms(object, ...) getBlocks(object, ...) getComplete(object, ...) getConstant(object, ...) getCol(object, ...) getDim(object, ...) getMake(object, ...) getMaxperm(object, ...) getMinperm(object, ...) getMirror(object, ...) getNperm(object, ...) getObserved(object, ...) getPlots(object, ...) getRow(object, ...) getStrata(object, ...) getType(object, ...) getWithin(object, ...) getControl(object, ...) getHow(object, ...) ## S3 method for class 'how' getAllperms(object, ...) ## S3 method for class 'how' getBlocks(object, ...) ## S3 method for class 'how' getCol(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getCol(object, ...) ## S3 method for class 'Within' getCol(object, ...) ## S3 method for class 'how' getComplete(object, ...) ## S3 method for class 'how' getConstant(object, ...) ## S3 method for class 'Within' getConstant(object, ...) ## S3 method for class 'how' getDim(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getDim(object, ...) ## S3 method for class 'Within' getDim(object, ...) ## S3 method for class 'how' getMake(object, ...) ## S3 method for class 'how' getMaxperm(object, ...) ## S3 method for class 'how' getMinperm(object, ...) ## S3 method for class 'how' getMirror(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getMirror(object, ...) ## S3 method for class 'Within' getMirror(object, ...) ## S3 method for class 'how' getNperm(object, ...) ## S3 method for class 'how' getObserved(object, ...) ## S3 method for class 'how' getPlots(object, ...) ## S3 method for class 'how' getRow(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getRow(object, ...) ## S3 method for class 'Within' getRow(object, ...) ## S3 method for class 'how' getStrata(object, which = c("plots", "blocks"), drop = TRUE, ...) ## S3 method for class 'Plots' getStrata(object, drop = TRUE, ...) ## S3 method for class 'how' getType(object, which = c("plots", "within"), ...) ## S3 method for class 'Plots' getType(object, ...) ## S3 method for class 'Within' getType(object, ...) ## S3 method for class 'how' getWithin(object, ...) ## S3 method for class 'allPerms' getControl(object, ...)
object |
An R object to dispatch on. |
which |
character; which level of restriction to extract information for. |
drop |
logical; should un-used factor levels be dropped? |
... |
Arguments passed on to other methods. |
These are extractor functions for working with permutation design
objects created by how
. They should be used in
preference to directly subsetting the permutation design in case the
internal structure of object changes as permute is developed.
getHow
is an alias for getControl
; specific methods are
implemented for getControl
if you are debugging.
These are simple extractor functions and return the contents of the
corresponding components of object
.
Gavin Simpson
check
, a utility function for checking
permutation scheme described by how
.
## extract components from a "how" object hh <- how() getWithin(hh) getNperm(hh)
## extract components from a "how" object hh <- how() getWithin(hh) getNperm(hh)
Utility functions to describe unrestricted and restricted permutation designs for time series, line transects, spatial grids and blocking factors.
how(within = Within(), plots = Plots(), blocks = NULL, nperm = 199, complete = FALSE, maxperm = 9999, minperm = 5040, all.perms = NULL, make = TRUE, observed = FALSE) Within(type = c("free","series","grid","none"), constant = FALSE, mirror = FALSE, ncol = NULL, nrow = NULL) Plots(strata = NULL, type = c("none","free","series","grid"), mirror = FALSE, ncol = NULL, nrow = NULL)
how(within = Within(), plots = Plots(), blocks = NULL, nperm = 199, complete = FALSE, maxperm = 9999, minperm = 5040, all.perms = NULL, make = TRUE, observed = FALSE) Within(type = c("free","series","grid","none"), constant = FALSE, mirror = FALSE, ncol = NULL, nrow = NULL) Plots(strata = NULL, type = c("none","free","series","grid"), mirror = FALSE, ncol = NULL, nrow = NULL)
within , plots , blocks
|
Permutation designs for samples within the
levels of |
nperm |
numeric; the number of permutations. |
complete |
logical; should complete enumeration of all permutations be performed? |
type |
character; the type of permutations required. One of
|
maxperm |
numeric; the maximum number of permutations to perform. Currently unused. |
minperm |
numeric; the lower limit to the number of possible
permutations at which complete enumeration is performed. When
|
all.perms |
an object of class |
make |
logical; should |
observed |
logical; should the observed permutation be returned
as part of the set of all permutations? Default is |
constant |
logical; should the same permutation be used within
each level of strata? If |
mirror |
logical; should mirroring of sequences be allowed? |
ncol , nrow
|
numeric; the number of columns and rows of samples in the spatial grid respectively. |
strata |
A factor, or an object that can be coerced to a factor
via |
shuffle
can generate permutations for a wide range of
restricted permutation schemes. A small selection of the available
combinations of options is provided in the Examples section below.
Argument type controls how samples are actually permuted;
"free"
indicates randomization, "series"
indicates
permutation via cyclic shifts (suitable for evenly-spaced line
transect or time series data), "grid"
indicates permutation via
toroidal shifts (suitable for samples on a regular grid), and
"none"
indicates no permutation of samples. See the package
vignette (browseVignettes("permute")
) for additional
information on each of these types of permutation.
Argument mirror
determines whether grid or series permutations
can be mirrored. Consider the sequence 1,2,3,4. The relationship
between consecutive observations is preserved if we reverse the
sequence to 4,3,2,1. If there is no inherent direction in your
experimental design, mirrored permutations can be considered
part of the Null model, and as such increase the number of possible
permutations. The default is to not use mirroring so you must
explicitly turn this on using mirror = TRUE
in how
.
To permute plots rather than the observations within plots (the
levels of strata
), use Within(type = "none")
and
Plots(type = foo)
, where foo
is how you want the plots
to be permuted. However, note that the number of observations within
each plot must be equal!
For some experiments, such as BACI designs, one might wish to use the
same permutation within each plot. This is controlled by
argument constant
. If constant = TRUE
then the same
permutation will be generated for each level of strata
. The
default is constant = FALSE
.
For how
a list with components for each of the possible arguments.
Gavin Simpson
shuffle()
is modelled after the permutation schemes of Canoco
3.1 (ter Braak, 1990); see also Besag & Clifford (1989).
Besag, J. and Clifford, P. (1989) Generalized Monte Carlo significance tests. Biometrika 76; 633–642.
ter Braak, C. J. F. (1990). Update notes: CANOCO version 3.1. Wageningen: Agricultural Mathematics Group. (UR).
shuffle
and shuffleSet
for
permuting from a design, and check
, a utility function
for checking permutation design described by how
.
## Set up factors for the Plots and Blocks plts <- gl(4, 10) ## 4 Plots of 10 samples each blks <- gl(2, 20) ## 2 Blocks of 20 samples each ## permutation design h1 <- how(within = Within(type = "series", mirror = TRUE), plots = Plots(strata = plts, type = "series"), blocks = blks) ## The design can be updated... ## ... remove the blocking: update(h1, blocks = NULL) ## ... or switch the type of shuffling at a level: #update(h1, plots = update(getPlots(h1), type = "none")) plots2 <- update(getPlots(h1), type = "none") update(h1, plots = plots2)
## Set up factors for the Plots and Blocks plts <- gl(4, 10) ## 4 Plots of 10 samples each blks <- gl(2, 20) ## 2 Blocks of 20 samples each ## permutation design h1 <- how(within = Within(type = "series", mirror = TRUE), plots = Plots(strata = plts, type = "series"), blocks = blks) ## The design can be updated... ## ... remove the blocking: update(h1, blocks = NULL) ## ... or switch the type of shuffling at a level: #update(h1, plots = update(getPlots(h1), type = "none")) plots2 <- update(getPlots(h1), type = "none") update(h1, plots = plots2)
Mandible lengths (in mm) for male and female golden jackals (Canis aureus) from a collection of specimens in the British Museum of Natural History, London, UK.
data(jackal)
data(jackal)
A data frame with 20 observations on the following 2 variables.
Length
a numeric vector
Sex
a factor with levels Male
Female
The data were manually transcribed from Manly (2007).
Higham, C.F.W., Kijngam, A., and Manly, B.F.J. (1980) An analysis of prehistoric canid remains from Thailand. Journal of Archaeological Science 7:149-165.
Manly, B.F.J. (2007) Randomization, bootstrap and Monte Carlo methods in biology. Third Edition. Chapman \& Hall/CRC, Boca Raton.
data(jackal) str(jackal) ## boxplot of mandible length vs sex plot(Length ~ Sex, data = jackal)
data(jackal) str(jackal) ## boxplot of mandible length vs sex plot(Length ~ Sex, data = jackal)
nobs
is a generic function to return the number of
observations from a model. shuffle
provides a few methods for
other types of data object in R.
## S3 method for class 'numeric' nobs(object, ...) ## S3 method for class 'integer' nobs(object, ...) ## S3 method for class 'matrix' nobs(object, ...) ## S3 method for class 'data.frame' nobs(object, ...) ## S3 method for class 'character' nobs(object, ...) ## S3 method for class 'factor' nobs(object, ...)
## S3 method for class 'numeric' nobs(object, ...) ## S3 method for class 'integer' nobs(object, ...) ## S3 method for class 'matrix' nobs(object, ...) ## S3 method for class 'data.frame' nobs(object, ...) ## S3 method for class 'character' nobs(object, ...) ## S3 method for class 'factor' nobs(object, ...)
object |
a data frame or matrix, or a numeric, integer, character, or factor vector. |
... |
arguments to other methods. |
Function nobs
is a simple generic function to return the
number of observations in a range of R model objects. Methods are
provided to work with a variety of R objects.
The (numeric) number of observations in object
.
Gavin Simpson
set.seed(1) ## numeric vector len <- sample(1:10, 1) v <- as.numeric(sample(1:100, len)) len obs <- nobs(v) isTRUE(all.equal(len, obs)) ## integer len <- sample(1L:10L, 1) obs <- nobs(len) isTRUE(all.equal(len, obs))
set.seed(1) ## numeric vector len <- sample(1:10, 1) v <- as.numeric(sample(1:100, len)) len obs <- nobs(v) isTRUE(all.equal(len, obs)) ## integer len <- sample(1L:10L, 1) obs <- nobs(len) isTRUE(all.equal(len, obs))
numPerms
calculates the maximum number of permutations possible
under the current permutation scheme.
numPerms(object, control = how())
numPerms(object, control = how())
object |
any object handled by |
control |
a list of control values describing properties of the
permutation design, as returned by a call to
|
Function numPerms
returns the number of permutations for the
passed object
and the selected permutation
scheme. object
can be one of a data frame, matrix, an object
for which a scores method exists, or a numeric or integer vector. In
the case of a numeric or integer vector, a vector of length 1 can be
used and it will be expanded to a vector of length object
(i.e., 1:object
) before computing the number of
permutations. As such, object
can be the number of observations
not just the object containing the observations.
The (numeric) number of possible permutations of observations in
object
.
In general, mirroring "series"
or "grid"
designs doubles
or quadruples, respectively, the number of permutations without
mirroring (within levels of strata if present). This is not
true in two special cases:
In "grid"
designs where the number of columns is equal
to 2, and
In "series"
designs where the number of observations in
a series is equal to 2.
For example, with 2 observations there are 2 permutations for
"series"
designs:
1-2, and
2-1.
If these two permutations were mirrored, we would have:
2-1, and
1-2.
It is immediately clear that this is the same set of permutations
without mirroring (if one reorders the rows). A similar situation
arises in "grid"
designs where the number of columns
per grid is equal to 2. Note that the number of rows per
grid is not an issue here.
Gavin Simpson
shuffle
and
how
. Additional nobs
methods are
provide, see nobs-methods
.
## permutation design --- see ?how ctrl <- how() ## defaults to freely exchangeable ## vector input v <- 1:10 (obs <- nobs(v)) numPerms(v, control = ctrl) ## integer input len <- length(v) (obs <- nobs(len)) numPerms(len, control = ctrl) ## new design, objects are a time series ctrl <- how(within = Within(type = "series")) numPerms(v, control = ctrl) ## number of permutations possible drastically reduced... ## ...turn on mirroring ctrl <- how(within = Within(type = "series", mirror = TRUE)) numPerms(v, control = ctrl) ## Try blocking --- 2 groups of 5 bl <- numPerms(v, control = how(blocks = gl(2,5))) bl ## should be same as pl <- numPerms(v, control = how(plots = Plots(strata = gl(2,5)))) pl stopifnot(all.equal(bl, pl))
## permutation design --- see ?how ctrl <- how() ## defaults to freely exchangeable ## vector input v <- 1:10 (obs <- nobs(v)) numPerms(v, control = ctrl) ## integer input len <- length(v) (obs <- nobs(len)) numPerms(len, control = ctrl) ## new design, objects are a time series ctrl <- how(within = Within(type = "series")) numPerms(v, control = ctrl) ## number of permutations possible drastically reduced... ## ...turn on mirroring ctrl <- how(within = Within(type = "series", mirror = TRUE)) numPerms(v, control = ctrl) ## Try blocking --- 2 groups of 5 bl <- numPerms(v, control = how(blocks = gl(2,5))) bl ## should be same as pl <- numPerms(v, control = how(plots = Plots(strata = gl(2,5)))) pl stopifnot(all.equal(bl, pl))
Simple functions to allow abstracted replacement of components of a
permutation design, for example as returned by how
. In
addition to performing replacement of components of the list returned
by how
, these replacement function also update the
matched calls stored within the list to facilitate the use of
update
by users.
setBlocks(object) <- value setPlots(object) <- value setWithin(object) <- value setStrata(object) <- value setNperm(object) <- value setAllperms(object) <- value setMaxperm(object) <- value setMinperm(object) <- value setComplete(object) <- value setMake(object) <- value setObserved(object) <- value setRow(object) <- value setCol(object) <- value setDim(object) <- value setType(object) <- value setMirror(object) <- value setConstant(object) <- value
setBlocks(object) <- value setPlots(object) <- value setWithin(object) <- value setStrata(object) <- value setNperm(object) <- value setAllperms(object) <- value setMaxperm(object) <- value setMinperm(object) <- value setComplete(object) <- value setMake(object) <- value setObserved(object) <- value setRow(object) <- value setCol(object) <- value setDim(object) <- value setType(object) <- value setMirror(object) <- value setConstant(object) <- value
object |
An R object to dispatch on. |
value |
The replacement value/object. |
These are replacement functions for working with permutation design
objects created by how
. They should be used in
preference to directly updating the permutation design in case the
internal structure of object changes as permute is developed and
because the matched call also needs to be updated to facilitate use of
update
on the how
object.
These replacement functions return object
suitably modified.
setStrata<-
has methods for objects of class "how"
and
"Plots"
. The former sets the blocks
component of the
how
object, whilst the latter sets the strata
component of the Plots
object.
setDim<-
, setRow<-
, and setCol<-
cannot be used
on an object of class "how"
. Instead, extract the Plots
or Within
components with getPlots
or
getWithin
and alter those components, then use the
resulting object to replace the plots
or within
components using setPlots
or setWithin
.
Gavin Simpson
check
, a utility function for checking
permutation scheme described by how
. Comparable
extractor functions are also available; see
get-methods
.
## extract components from a "how" object hh <- how() getNperm(hh) setNperm(hh) <- 999 getNperm(hh)
## extract components from a "how" object hh <- how() getNperm(hh) setNperm(hh) <- 999 getNperm(hh)
Unrestricted and restricted permutation designs for time series, line transects, spatial grids and blocking factors.
shuffle(n, control = how()) permute(i, n, control)
shuffle(n, control = how()) permute(i, n, control)
n |
numeric; the length of the returned vector of permuted
values. Usually the number of observations under consideration. May
also be any object that |
control |
a list of control values describing properties of the
permutation design, as returned by a call to |
i |
integer; row of |
shuffle
can generate permutations for a wide range of
restricted permutation schemes. A small selection of the available
combinations of options is provided in the Examples section below.
permute
is a higher level utility function for use in a loop
within a function implementing a permutation test. The main purpose of
permute
is to return the correct permutation in each iteration
of the loop, either a random permutation from the current design or
the next permutation from control$all.perms
if it is not
NULL
and control$complete
is TRUE
.
For shuffle
a vector of length n
containing a
permutation of the observations 1, ..., n using the permutation
scheme described by argument control
.
For permute
the i
th permutation from the set of all
permutations, or a random permutation from the design.
Gavin Simpson
shuffle()
is modelled after the permutation schemes of Canoco
3.1 (ter Braak, 1990); see also Besag & Clifford (1989).
Besag, J. and Clifford, P. (1989) Generalized Monte Carlo significance tests. Biometrika 76; 633–642.
ter Braak, C. J. F. (1990). Update notes: CANOCO version 3.1. Wageningen: Agricultural Mathematics Group. (UR).
check
, a utility function for checking
permutation scheme described by how
.
set.seed(1234) ## unrestricted permutations shuffle(20) ## observations represent a time series of line transect CTRL <- how(within = Within(type = "series")) shuffle(20, control = CTRL) ## observations represent a time series of line transect ## but with mirroring allowed CTRL <- how(within = Within(type = "series", mirror = TRUE)) shuffle(20, control = CTRL) ## observations represent a spatial grid, 5rx4c nr <- 5 nc <- 4 CTRL <- how(within = Within(type = "grid", ncol = nc, nrow = nr)) perms <- shuffle(20, control = CTRL) ## view the permutation as a grid matrix(matrix(1:20, nrow = nr, ncol = nc)[perms], ncol = nc, nrow = nr) ## random permutations in presence of strata plots <- Plots(strata = gl(4, 5)) CTRL <- how(plots = plots, within = Within(type = "free")) shuffle(20, CTRL) ## as above but same random permutation within strata CTRL <- how(plots = plots, within = Within(type = "free", constant = TRUE)) shuffle(20, CTRL) ## time series within each level of block CTRL <- how(plots = plots, within = Within(type = "series")) shuffle(20, CTRL) ## as above, but with same permutation for each level CTRL <- how(plots = plots, within = Within(type = "series", constant = TRUE)) shuffle(20, CTRL) ## spatial grids within each level of block, 4 x (5r x 5c) nr <- 5 nc <- 5 nb <- 4 ## number of blocks plots <- Plots(gl(nb, 25)) CTRL <- how(plots = plots, within = Within(type = "grid", ncol = nc, nrow = nr)) shuffle(100, CTRL) ## as above, but with same permutation for each level CTRL <- how(plots = plots, within = Within(type = "grid", ncol = nc, nrow = nr, constant = TRUE)) shuffle(100, CTRL) ## permuting levels of plots instead of observations CTRL <- how(plots = Plots(gl(4, 5), type = "free"), within = Within(type = "none")) shuffle(20, CTRL) ## permuting levels of plots instead of observations ## but plots represent a time series CTRL <- how(plots = Plots(gl(4, 5), type = "series"), within = Within(type = "none")) shuffle(20, CTRL) ## permuting levels of plots but plots represent a time series ## free permutation within plots CTRL <- how(plots = Plots(gl(4, 5), type = "series"), within = Within(type = "free")) shuffle(20, CTRL) ## permuting within blocks grp <- gl(2, 10) # 2 groups of 10 samples each CTRL <- how(blocks = grp) shuffle(length(grp), control = CTRL) ## Simple function using permute() to assess significance ## of a t.test pt.test <- function(x, group, control) { ## function to calculate t t.statistic <- function(x, y) { m <- length(x) n <- length(y) ## means and variances, but for speed xbar <- mean(x) ybar <- mean(y) xvar <- var(x) yvar <- var(y) pooled <- sqrt(((m-1)*xvar + (n-1)*yvar) / (m+n-2)) (xbar - ybar) / (pooled * sqrt(1/m + 1/n)) } ## check the control object #control <- check(x, control)$control ## FIXME ## number of observations Nobs <- nobs(x) ## group names lev <- names(table(group)) ## vector to hold results, +1 because of observed t t.permu <- numeric(length = control$nperm) + 1 ## calculate observed t t.permu[1] <- t.statistic(x[group == lev[1]], x[group == lev[2]]) ## generate randomisation distribution of t for(i in seq_along(t.permu)) { ## return a permutation want <- permute(i, Nobs, control) ## calculate permuted t t.permu[i+1] <- t.statistic(x[want][group == lev[1]], x[want][group == lev[2]]) } ## pval from permutation test pval <- sum(abs(t.permu) >= abs(t.permu[1])) / (control$nperm + 1) ## return value return(list(t.stat = t.permu[1], pval = pval)) } ## generate some data with slightly different means set.seed(1234) gr1 <- rnorm(20, mean = 9) gr2 <- rnorm(20, mean = 10) dat <- c(gr1, gr2) ## grouping variable grp <- gl(2, 20, labels = paste("Group", 1:2)) ## create the permutation design control <- how(nperm = 999, within = Within(type = "free")) ## perform permutation t test perm.val <- pt.test(dat, grp, control) perm.val ## compare perm.val with the p-value from t.test() t.test(dat ~ grp, var.equal = TRUE)
set.seed(1234) ## unrestricted permutations shuffle(20) ## observations represent a time series of line transect CTRL <- how(within = Within(type = "series")) shuffle(20, control = CTRL) ## observations represent a time series of line transect ## but with mirroring allowed CTRL <- how(within = Within(type = "series", mirror = TRUE)) shuffle(20, control = CTRL) ## observations represent a spatial grid, 5rx4c nr <- 5 nc <- 4 CTRL <- how(within = Within(type = "grid", ncol = nc, nrow = nr)) perms <- shuffle(20, control = CTRL) ## view the permutation as a grid matrix(matrix(1:20, nrow = nr, ncol = nc)[perms], ncol = nc, nrow = nr) ## random permutations in presence of strata plots <- Plots(strata = gl(4, 5)) CTRL <- how(plots = plots, within = Within(type = "free")) shuffle(20, CTRL) ## as above but same random permutation within strata CTRL <- how(plots = plots, within = Within(type = "free", constant = TRUE)) shuffle(20, CTRL) ## time series within each level of block CTRL <- how(plots = plots, within = Within(type = "series")) shuffle(20, CTRL) ## as above, but with same permutation for each level CTRL <- how(plots = plots, within = Within(type = "series", constant = TRUE)) shuffle(20, CTRL) ## spatial grids within each level of block, 4 x (5r x 5c) nr <- 5 nc <- 5 nb <- 4 ## number of blocks plots <- Plots(gl(nb, 25)) CTRL <- how(plots = plots, within = Within(type = "grid", ncol = nc, nrow = nr)) shuffle(100, CTRL) ## as above, but with same permutation for each level CTRL <- how(plots = plots, within = Within(type = "grid", ncol = nc, nrow = nr, constant = TRUE)) shuffle(100, CTRL) ## permuting levels of plots instead of observations CTRL <- how(plots = Plots(gl(4, 5), type = "free"), within = Within(type = "none")) shuffle(20, CTRL) ## permuting levels of plots instead of observations ## but plots represent a time series CTRL <- how(plots = Plots(gl(4, 5), type = "series"), within = Within(type = "none")) shuffle(20, CTRL) ## permuting levels of plots but plots represent a time series ## free permutation within plots CTRL <- how(plots = Plots(gl(4, 5), type = "series"), within = Within(type = "free")) shuffle(20, CTRL) ## permuting within blocks grp <- gl(2, 10) # 2 groups of 10 samples each CTRL <- how(blocks = grp) shuffle(length(grp), control = CTRL) ## Simple function using permute() to assess significance ## of a t.test pt.test <- function(x, group, control) { ## function to calculate t t.statistic <- function(x, y) { m <- length(x) n <- length(y) ## means and variances, but for speed xbar <- mean(x) ybar <- mean(y) xvar <- var(x) yvar <- var(y) pooled <- sqrt(((m-1)*xvar + (n-1)*yvar) / (m+n-2)) (xbar - ybar) / (pooled * sqrt(1/m + 1/n)) } ## check the control object #control <- check(x, control)$control ## FIXME ## number of observations Nobs <- nobs(x) ## group names lev <- names(table(group)) ## vector to hold results, +1 because of observed t t.permu <- numeric(length = control$nperm) + 1 ## calculate observed t t.permu[1] <- t.statistic(x[group == lev[1]], x[group == lev[2]]) ## generate randomisation distribution of t for(i in seq_along(t.permu)) { ## return a permutation want <- permute(i, Nobs, control) ## calculate permuted t t.permu[i+1] <- t.statistic(x[want][group == lev[1]], x[want][group == lev[2]]) } ## pval from permutation test pval <- sum(abs(t.permu) >= abs(t.permu[1])) / (control$nperm + 1) ## return value return(list(t.stat = t.permu[1], pval = pval)) } ## generate some data with slightly different means set.seed(1234) gr1 <- rnorm(20, mean = 9) gr2 <- rnorm(20, mean = 10) dat <- c(gr1, gr2) ## grouping variable grp <- gl(2, 20, labels = paste("Group", 1:2)) ## create the permutation design control <- how(nperm = 999, within = Within(type = "free")) ## perform permutation t test perm.val <- pt.test(dat, grp, control) perm.val ## compare perm.val with the p-value from t.test() t.test(dat ~ grp, var.equal = TRUE)
Unrestricted and restricted permutations for time series, line transects, spatial grids and blocking factors.
shuffleFree(x, size) shuffleSeries(x, mirror = FALSE, start = NULL, flip = NULL) shuffleGrid(nrow, ncol, mirror = FALSE, start.row = NULL, start.col = NULL, flip = NULL) shuffleStrata(strata, type, mirror = FALSE, start = NULL, flip = NULL, nrow, ncol, start.row = NULL, start.col = NULL)
shuffleFree(x, size) shuffleSeries(x, mirror = FALSE, start = NULL, flip = NULL) shuffleGrid(nrow, ncol, mirror = FALSE, start.row = NULL, start.col = NULL, flip = NULL) shuffleStrata(strata, type, mirror = FALSE, start = NULL, flip = NULL, nrow, ncol, start.row = NULL, start.col = NULL)
x |
vector of indices to permute. |
size |
number of random permutations required |
mirror |
logical; should mirroring of sequences be allowed? |
start |
integer; the starting point for time series permutations. If missing, a random starting point is determined. |
flip |
logical, length 1 ( |
nrow , ncol
|
numeric; the number of rows and columns in the grid. |
start.row , start.col
|
numeric; the starting row and column for the shifted grid permutation. If non supplied, a random starting row and column will be selected. |
strata |
factor; the blocks to permute. |
type |
character; the type of permutation used to shuffle the
|
These are developer-level functions for generating permuted indexes from one of several restricted and unrestricted designs.
shuffleFree
is a wrapper to code underlying
sample
, but without the extra over head of sanity
checks. It is defined as sample.int(x, size, replace = FALSE)
.
You must arrange for the correct values to be supplied, where
x
is a vector of indices to sample from, and size
is the
number of indices to sample. Sampling is done without replacement and
without regard to prior probabilities. Argument size
is allowed
so that one can draw a single observation at random from the indices
x
. In general use, size
would be set equal to
length{x}
.
A integer vector of permuted indices.
Gavin Simpson
check
, a utility function for checking
permutation scheme described by
how
. shuffle
as a user-oriented
wrapper to these functions.
set.seed(3) ## draw 1 value at random from the set 1:10 shuffleFree(1:10, 1) ## permute the series 1:10 x <- 1:10 shuffleSeries(x) ## with random starting point shuffleSeries(x, start = 5L) ## known starting point shuffleSeries(x, flip = TRUE) ## random start, forced mirror shuffleSeries(x, mirror = TRUE) ## random start, possibly mirror ## permute a grid of size 3x3 shuffleGrid(3, 3) ## random starting row/col shuffleGrid(3, 3, start.row = 2, start.col = 3) ## with known row/col shuffleGrid(3, 3, flip = rep(TRUE, 2)) ## random start, forced mirror
set.seed(3) ## draw 1 value at random from the set 1:10 shuffleFree(1:10, 1) ## permute the series 1:10 x <- 1:10 shuffleSeries(x) ## with random starting point shuffleSeries(x, start = 5L) ## known starting point shuffleSeries(x, flip = TRUE) ## random start, forced mirror shuffleSeries(x, mirror = TRUE) ## random start, possibly mirror ## permute a grid of size 3x3 shuffleGrid(3, 3) ## random starting row/col shuffleGrid(3, 3, start.row = 2, start.col = 3) ## with known row/col shuffleGrid(3, 3, flip = rep(TRUE, 2)) ## random start, forced mirror
shuffleSet
returns a set of nset
permutations from the
specified design. The main purpose of the function is to circumvent
the overhead of repeatedly calling shuffle
to generate a
set of permutations.
shuffleSet(n, nset, control = how(), check = TRUE, quietly = FALSE) ## S3 method for class 'permutationMatrix' as.matrix(x, ...)
shuffleSet(n, nset, control = how(), check = TRUE, quietly = FALSE) ## S3 method for class 'permutationMatrix' as.matrix(x, ...)
n |
numeric; the number of observations in the sample set. May also be
any object that |
nset |
numeric; the number of permutations to generate for the set. Can be
missing, the default, in which case |
control |
an object of class |
check |
logical; should the design be checked for various problems via
function |
quietly |
logical; should messages by suppressed? |
x |
an object of class |
... |
arguments passed to other methods. For the |
shuffleSet
is designed to generate a set of nset
permutation indices over which a function can iterate as part of a
permutation test. It is only slightly more efficient than calling
shuffle
nset
times, but it is far more practical
than the simpler function because a set of permutations can be worked
on by applying a function to the rows of the returned object. This
simplifies the function applied, and facilitates the use of parallel
processing functions, thus enabling a larger number of permutations to
be evaluated in reasonable time.
By default, shuffleSet
will check the permutations design
following a few simple heuristics. See check
for details
of these. Whether some of the heuristics are activiated or not can be
controlled via how
, essentialy via its argument
minperm
. In particular, if there are fewer than minperm
permutations, shuffleSet
will generate and return all
possible permutations, which may differ from the number requested via
argument nset
.
The check
argument to shuffleSet
controls whether
checking is performed in the permutation design. If you set
check = FALSE
then exactly nset
permutations will be
returned. However, do be aware that there is no guarantee that the set
of permutations returned will be unique, especially so for designs and
data sets where there are few possible permutations relative to the
number requested.
The as.matrix
method sets the control
and seed
attributes to NULL
and removes the "permutationMatrix"
class, resulting in a standard matrix object.
Returns a matrix of permutations, where each row is a separate
permutation. As such, the returned matrix has nset
rows and
n
columns.
Gavin L. Simpson
shuffleSet()
is modelled after the permutation schemes of Canoco
3.1 (ter Braak, 1990); see also Besag & Clifford (1989).
Besag, J. and Clifford, P. (1989) Generalized Monte Carlo significance tests. Biometrika 76; 633–642.
ter Braak, C. J. F. (1990). Update notes: CANOCO version 3.1. Wageningen: Agricultural Mathematics Group. (UR).
See shuffle
for generating a single permutation, and
how
for setting up permutation designs.
set.seed(1) ## simple random permutations, 5 permutations in set shuffleSet(n = 10, nset = 5) ## series random permutations, 5 permutations in set shuffleSet(10, 5, how(within = Within(type = "series"))) ## series random permutations, 10 permutations in set, ## with possible mirroring CTRL <- how(within = Within(type = "series", mirror = TRUE)) shuffleSet(10, 10, CTRL) ## Permuting strata ## 4 groups of 5 observations CTRL <- how(within = Within(type = "none"), plots = Plots(strata = gl(4,5), type = "free")) shuffleSet(20, 10, control = CTRL) ## 10 random permutations in presence of Plot-level strata plotStrata <- Plots(strata = gl(4,5)) CTRL <- how(plots = plotStrata, within = Within(type = "free")) numPerms(20, control = CTRL) shuffleSet(20, 10, control = CTRL) ## as above but same random permutation within Plot-level strata CTRL <- how(plots = plotStrata, within = Within(type = "free", constant = TRUE)) numPerms(20, control = CTRL) shuffleSet(20, 10, CTRL) ## check this. ## time series within each level of Plot strata CTRL <- how(plots = plotStrata, within = Within(type = "series")) shuffleSet(20, 10, CTRL) ## as above, but with same permutation for each Plot-level stratum CTRL <- how(plots = plotStrata, within = Within(type = "series", constant = TRUE)) shuffleSet(20, 10, CTRL)
set.seed(1) ## simple random permutations, 5 permutations in set shuffleSet(n = 10, nset = 5) ## series random permutations, 5 permutations in set shuffleSet(10, 5, how(within = Within(type = "series"))) ## series random permutations, 10 permutations in set, ## with possible mirroring CTRL <- how(within = Within(type = "series", mirror = TRUE)) shuffleSet(10, 10, CTRL) ## Permuting strata ## 4 groups of 5 observations CTRL <- how(within = Within(type = "none"), plots = Plots(strata = gl(4,5), type = "free")) shuffleSet(20, 10, control = CTRL) ## 10 random permutations in presence of Plot-level strata plotStrata <- Plots(strata = gl(4,5)) CTRL <- how(plots = plotStrata, within = Within(type = "free")) numPerms(20, control = CTRL) shuffleSet(20, 10, control = CTRL) ## as above but same random permutation within Plot-level strata CTRL <- how(plots = plotStrata, within = Within(type = "free", constant = TRUE)) numPerms(20, control = CTRL) shuffleSet(20, 10, CTRL) ## check this. ## time series within each level of Plot strata CTRL <- how(plots = plotStrata, within = Within(type = "series")) shuffleSet(20, 10, CTRL) ## as above, but with same permutation for each Plot-level stratum CTRL <- how(plots = plotStrata, within = Within(type = "series", constant = TRUE)) shuffleSet(20, 10, CTRL)