Skip to content

Commit

Permalink
version 0.1.9
Browse files Browse the repository at this point in the history
  • Loading branch information
mmrabe authored and cran-robot committed Dec 4, 2019
1 parent 82c377c commit 809b93c
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 131 deletions.
9 changes: 4 additions & 5 deletions DESCRIPTION
@@ -1,8 +1,7 @@
Package: designr
Type: Package
Title: Balanced Factorial Designs
Version: 0.1.8
Date: 2019-10-30
Version: 0.1.9
URL: https://maxrabe.com/designr
BugReports: https://github.com/mmrabe/designr/issues
Authors@R: c(person("Maximilian", "Rabe", email = "maximilian.rabe@uni-potsdam.de", role = c("aut", "cre")), person("Reinhold", "Kliegl", email = "kliegl@uni-potsdam.de", role = c("aut")), person("Schad", "Daniel", email = "schad@uni-potsdam.de", role = c("aut")))
Expand All @@ -12,13 +11,13 @@ Encoding: UTF-8
LazyData: true
RoxygenNote: 6.1.1
Imports: MASS, tibble, crossdes, methods, dplyr
Suggests: knitr, rmarkdown, tidyverse, jsonlite, writexl
Suggests: knitr, rmarkdown, jsonlite, writexl
VignetteBuilder: knitr
NeedsCompilation: no
Packaged: 2019-10-30 21:41:47 UTC; max
Packaged: 2019-12-04 13:53:56 UTC; max
Author: Maximilian Rabe [aut, cre],
Reinhold Kliegl [aut],
Schad Daniel [aut]
Maintainer: Maximilian Rabe <maximilian.rabe@uni-potsdam.de>
Repository: CRAN
Date/Publication: 2019-11-05 09:20:02 UTC
Date/Publication: 2019-12-04 14:30:02 UTC
20 changes: 10 additions & 10 deletions MD5
@@ -1,14 +1,14 @@
91aa65cb1d013cc596dfefa6eb4be8c9 *DESCRIPTION
9c9db9c51442c56e50bef90cf967f06c *DESCRIPTION
3c8b882137f412dde8d0ee9a5f0a618b *NAMESPACE
83f29244c95900ad2c9c1950acf5f017 *R/classes.R
82ca15fd877ae19113a3a9c3d4826dbb *R/classes.R
67a2822b7a191273e8a3699b46c301ac *R/helpers.R
191977bc029e54fc9792dc12cb0709a0 *R/methods.R
05f6251fa32bbe524f2e6f5fdc0525bb *R/methods.R
12fd950740fc49d794915c66baa7b2e2 *R/toolbox.R
36bf025817e74611b1a1de3cf9cb074b *README.md
fd6e5409e9849b8f0da718178816c3d6 *README.md
147f858e187bb645a6377eb5889d5cda *build/vignette.rds
9fc4aefb8de6921a3b70af153e4fb693 *inst/doc/design-to-dataframe.R
87a34022e793d118912165eaa4595f7b *inst/doc/design-to-dataframe.Rmd
e5f784a4b9e40c1a250cc7ac00cf177b *inst/doc/design-to-dataframe.html
a5f01b99cd7d9521b635e01fb23b6580 *inst/doc/design-to-dataframe.R
73a58c322b4ff038ac67271391045fd8 *inst/doc/design-to-dataframe.Rmd
27ef0b63dcf3706b04ecc6d9b4f4f75f *inst/doc/design-to-dataframe.html
a72539d0541a5ea3fdae65bfe53ef38d *man/design.contrasts.Rd
85e5d339855a82c6c99d6450a1139e22 *man/factor.design.Rd
cde4f69fb703f90209c5e056d22c3192 *man/factorContainer-class.Rd
Expand All @@ -17,10 +17,10 @@ cde4f69fb703f90209c5e056d22c3192 *man/factorContainer-class.Rd
41d2920a5f09034d58e030f816fd29a2 *man/fixed.factors.Rd
9b7660693d80603137219ec0a1ce53e8 *man/is.designFactor.Rd
618f30f14153cbc6523c156a09bdc3df *man/nobs-factorDesign-method.Rd
1823d8e7698ec553b48aedfbf4fbd156 *man/output.design.Rd
fc69a2bb3a3de2b1c6e11d117631eb37 *man/output.design.Rd
a8817273873ef49c1a8cf5ea42a15802 *man/plus-factorContainer-factorContainer-method.Rd
fced1aaf957d5d20a393fa6de3b68612 *man/random.factor.Rd
898ff9eec1664dc09a07dd30ecf31d32 *man/random.factor.Rd
e037427b940137ea5f7eeec4f16aaddc *man/show.factorContainer.Rd
73fd7882c6b139512144ed0c339abe8f *man/subset-factorDesign-method.Rd
52f3c68aac9718d3cf0758816bd3e1ca *man/write.design.Rd
87a34022e793d118912165eaa4595f7b *vignettes/design-to-dataframe.Rmd
73a58c322b4ff038ac67271391045fd8 *vignettes/design-to-dataframe.Rmd
5 changes: 3 additions & 2 deletions R/classes.R
Expand Up @@ -43,6 +43,7 @@ setClass("factorDesign", slots=c(design="data.frame"), contains=c("list", "facto
#' @param name Name of the random factor as a character vector. Typically, this should be a length-1 vector (i.e., a single string) but you may pass multiple names of random factors whose interaction is to be nested in groups (see *Assignment Constraints*).
#' @param instances Number of times (as a single integer value) each level (instantiation) is to be replicated.
#' @param groups Names of fixed and random factors that are to be used as grouping (nesting/between) levels.
#' @param assign For random factor interactions, use this method for counterbalancing instance assignment (see Assignment Constraints)
#' @param ... Additional arguments to be stored as \code{extra} values.
#' @return An instance of the class \code{randomFactor}.
#'
Expand All @@ -69,13 +70,13 @@ setClass("factorDesign", slots=c(design="data.frame"), contains=c("list", "facto
#'
#' @seealso \code{\link[designr]{fixed.factor}}
#' @export
random.factor <- function(name, groups = character(0), instances = 1L, ...) {
random.factor <- function(name, groups = character(0), instances = 1L, assign = "latin.square", ...) {
check_argument(name, "character")
if(any(vapply(name, function(n) substr(n,1,1) == '*', logical(1)))) stop("Factor names must not start with an asterisk!")
check_argument(instances, "numeric", function(x) !x%%1, 1, expression(x >= 1))
check_argument(groups, "character")
levels <- do.call(data.frame, sapply(name, function(n) NA_integer_, USE.NAMES = TRUE, simplify = FALSE))
new("randomFactor", name = name, levels=levels, groups=groups, replications = as.integer(instances), extra = list(...))
new("randomFactor", name = name, levels=levels, groups=groups, replications = as.integer(instances), extra = list(assign = assign, ...))
}

#' Fixed factors
Expand Down
18 changes: 12 additions & 6 deletions R/methods.R
Expand Up @@ -213,7 +213,7 @@ design.units <- function(design, rename_random = TRUE, include_interactions = FA

#' @describeIn output.design Retrieve only the codes of planned observations of an experimental design
#' @export
design.codes <- function(design, group_by = NULL, order_by = NULL, randomize = FALSE, rename_random = TRUE) {
design.codes <- function(design, group_by = NULL, order_by = names(random.factors(design, include_interactions = FALSE)), randomize = FALSE, rename_random = TRUE) {
check_argument(group_by, c("NULL", "character"))
check_argument(order_by, c("NULL", "character"))
check_argument(randomize, "logical", 1)
Expand Down Expand Up @@ -243,6 +243,9 @@ design.codes <- function(design, group_by = NULL, order_by = NULL, randomize = F
data <- data[do.call(order, unname(as.list(data[, order_by, drop=FALSE]))), , drop=FALSE]
}
rownames(data) <- NULL
ranfac_names <- intersect(names(random.factors(design, include_interactions = FALSE)), colnames(data))
fixfac_names <- intersect(names(fixed.factors(design)), colnames(data))
data <- data[,c(ranfac_names, fixfac_names, setdiff(colnames(data), c(ranfac_names, fixfac_names)))]
for(ranfac in names(random.factors(design, include_interactions = FALSE))) {
if(isTRUE(rename_random)) {
data[,ranfac] <- rename_random_default(data[,ranfac], ranfac)
Expand Down Expand Up @@ -278,23 +281,26 @@ show.factorContainer <- function(object) {
check_argument(object, c("factorDesign","randomFactor","fixedFactor"))
if(is(object, "factorDesign")) {
cat(sprintf("Factor design with %d factor(s):\n", length(object)))
print.listof(object)
cat(sprintf("\nDesign matrix:\n"))
show(object@design)
for(fac in object) {
cat(" - ")
show(fac)
cat("\n")
}
codes <- design.codes(object)
cat(sprintf("\nDesign matrix with %d planned observations:\n", nrow(codes)))
show(codes)
} else if(is(object, "randomFactor")) {
cat(sprintf("Random factor `%s` with %d group(s) and %d instance(s) (%d level(s) in total)", paste(object@name, collapse=":"), nrow(object@levels), object@replications, nrow(object@levels)*object@replications))
if(length(object@groups)>0L) {
cat(", grouped by ")
cat(paste(object@groups, collapse=":"))
}
cat("\n")
} else if(is(object, "fixedFactor")) {
cat(sprintf("Fixed factor `%s` with %d level(s) (%s) and %d replication(s)", paste(object@name, collapse=":"), nrow(object@levels), paste(object@levels[,object@name], collapse=", "), object@replications))
if(length(object@groups)>0L) {
cat(", grouped by ")
cat(paste(object@groups, collapse=":"))
}
cat("\n")
} else {
stop("Not a design factor or factor list!")
}
Expand Down
185 changes: 183 additions & 2 deletions README.md
@@ -1,7 +1,188 @@

# designr

*designr* is an R package to create and simulate crossed factorial designs.

To install the latest development version in R using the `devtools` package, use:
## Installation

Install from CRAN within R using:


```r
install.packages("designr")
```

Install the development version in R using `devtools`:


```r
devtools::install_github("mmrabe/designr", build_vignettes = TRUE)
```

## Random and fixed factors

*designr* supports factorial designs with an arbitrary number of fixed and random factors. Fixed factors are factors for which levels are known and typically defined by the experimenter, e.g. an experimental condition or a quasi-experimental variable such as a subject’s age group. Conversely, the instances of random factors are usually not known before data collection. Examples for random factors are subjects or items in a typical psychological experiment, with the individual tested subjects and used items being the instances of those random factors.

## Simple fixed-effects design

A fixed-effects design without repeated measurement is created as easily as this:


```r
design1 <-
fixed.factor("Age", levels=c("young", "old")) +
fixed.factor("Material", levels=c("word", "image"))
design1
```

```
## Factor design with 2 factor(s):
## - Fixed factor `Age` with 2 level(s) (young, old) and 1 replication(s)
## - Fixed factor `Material` with 2 level(s) (word, image) and 1 replication(s)
##
## Design matrix with 4 planned observations:
## # A tibble: 4 x 2
## Age Material
## <fct> <fct>
## 1 young word
## 2 old word
## 3 young image
## 4 old image
```

As can be seen, this experimental design requires 4 observations.

## Adding random factors

Assume we want to test different groups of subjects. Each subject will only be `old` or `young` but be tested with stimuli of both categories `word` and `image`. In a typical behavioral experiment, `Age` would now be a between-subject/within-item factor and `Material` a within-subject/between-item factor. In other words, `Material` is now nested within the instances of `Subject`, whereas `Subject` is grouped by `Age`.


```r
design2 <-
fixed.factor("Age", levels=c("young", "old")) +
fixed.factor("Material", levels=c("word", "image")) +
random.factor("Subject", groups = "Age")
design.codes(design2)
```

```
## # A tibble: 4 x 3
## Subject Age Material
## <fct> <fct> <fct>
## 1 Subject1 old word
## 2 Subject1 old image
## 3 Subject2 young word
## 4 Subject2 young image
```

The minimal experimental design will still require 4 observations, assigning one subject to each level of the between-subject factor `Age`.

## Nested designs

Note that `design1` is nested within `design2`. This means that instead of defining `design2` like we did above, we can also derive it from the existing `design1` by adding the random factor `Subject` like so:


```r
design2 <-
design1 +
random.factor("Subject", groups = "Age")
```

## Crossed random factors

Oftentimes, experiments will have more than one random factor, for example `Subject` and `Item`. This is because items in behavioral experiments are often prepared upfront and not randomly generated upon presentation. In that case we would like to make sure that each item is presented equally often across all subjects and within-item conditions. Suppose that we are extending our example from above by a second random factor `Item`. Contrary to `Subject`, `Item` is grouped by `Material` because each item can only be a `word` or `image` but it may be presented to both `old` and `young` subjects.


```r
design3 <-
fixed.factor("Age", levels=c("young", "old")) +
fixed.factor("Material", levels=c("word", "image")) +
random.factor("Subject", groups = "Age") +
random.factor("Item", groups = "Material")
design.codes(design3)
```

```
## # A tibble: 4 x 4
## Subject Item Age Material
## <fct> <fct> <fct> <fct>
## 1 Subject1 Item1 old image
## 2 Subject1 Item2 old word
## 3 Subject2 Item1 young image
## 4 Subject2 Item2 young word
```

In this design, we plan to test 2 subjects, one `young` and one `old`, and each of them will be presented two items, an `image` and a `word`. The items will appear equally often in the levels of `Age` and subjects will see an equal number of items in all levels of `Material`.

## Counterbalancing

Note that in the example above, each item really only appears once per subject. However, suppose we introduce a third fixed factor, which varies within subjects and within items, i.e. it is neither a subject nor item level fixed property. This could be something like the contrast on the screen or some other experimental manipulation that is pseudo-randomly varied for each subject and each item.

The resulting design may look something like this:


```r
design4 <-
fixed.factor("Age", levels=c("young", "old")) +
fixed.factor("Material", levels=c("word", "image")) +
fixed.factor("Contrast", levels=c("high", "low")) +
random.factor("Subject", groups = "Age") +
random.factor("Item", groups = "Material")
design.codes(design4)
```

```
## # A tibble: 8 x 5
## Subject Item Age Material Contrast
## <fct> <fct> <fct> <fct> <fct>
## 1 Subject1 Item1 old image high
## 2 Subject1 Item1 old image low
## 3 Subject1 Item2 old word high
## 4 Subject1 Item2 old word low
## 5 Subject2 Item1 young image high
## 6 Subject2 Item1 young image low
## 7 Subject2 Item2 young word high
## 8 Subject2 Item2 young word low
```

In a fully crossed and balanced experimental design, each item would now be presented twice per subject, once with `high` and once with `low` contrast. This can be absolutely legitimate, depending on the research question. In many behavioral experiments, however, the experimenter may wish to prevent the same item from being presented twice because that could introduce unwanted effects.

Essentially, what we want to do is to group each `Subject`×`Item` pairing by `Contrast`, i.e. we want to ensure that each item assigned to a subject is only assigned in either `high` or `low` contrast. We can therefore add the interaction of `Subject` and `Item` as a random factor, grouped by `Contrast`:


```r
design5 <-
fixed.factor("Age", levels=c("young", "old")) +
fixed.factor("Material", levels=c("word", "image")) +
fixed.factor("Contrast", levels=c("high", "low")) +
random.factor("Subject", groups = "Age") +
random.factor("Item", groups = "Material") +
random.factor(c("Subject","Item"), groups = "Contrast")
design.codes(design5)
```

```
## # A tibble: 16 x 5
## Subject Item Age Material Contrast
## <fct> <fct> <fct> <fct> <fct>
## 1 Subject1 Item1 old image high
## 2 Subject1 Item2 old image low
## 3 Subject1 Item3 old word high
## 4 Subject1 Item4 old word low
## 5 Subject2 Item1 old image low
## 6 Subject2 Item2 old image high
## 7 Subject2 Item3 old word low
## 8 Subject2 Item4 old word high
## 9 Subject3 Item1 young image high
## 10 Subject3 Item2 young image low
## 11 Subject3 Item3 young word high
## 12 Subject3 Item4 young word low
## 13 Subject4 Item1 young image low
## 14 Subject4 Item2 young image high
## 15 Subject4 Item3 young word low
## 16 Subject4 Item4 young word high
```

The design now contains 16 planned observations for 4 subjects and 4 items. Each subject will be presented each item exactly once and an equal number of items (1) in each combination of `Material`×`Contrast`. Moreover, each item will be presented equally often in each combination of `Age`×`Contrast`.

`devtools::install_github("mmrabe/designr", build_vignettes = TRUE)`
For a more detailed example, see the `design-to-dataframe` vignette (by executing `vignette("design-to-dataframe")`) and the manual pages of the package.
2 changes: 1 addition & 1 deletion inst/doc/design-to-dataframe.R
@@ -1,7 +1,7 @@
## ----setup, include=FALSE------------------------------------------------
knitr::opts_chunk$set(echo = TRUE)

library(tidyverse)
library(dplyr)
library(designr)

# Set a "seed" for the random numnber generator
Expand Down
2 changes: 1 addition & 1 deletion inst/doc/design-to-dataframe.Rmd
Expand Up @@ -22,7 +22,7 @@ vignette: >
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(dplyr)
library(designr)
# Set a "seed" for the random numnber generator
Expand Down

0 comments on commit 809b93c

Please sign in to comment.