Skip to contents

Applies centering, scaling, and/or orthogonalization to a pre-existing numeric contrast matrix.

Usage

transform_contrasts(
  C,
  centre = TRUE,
  scale = c("none", "sd", "l2"),
  orth = FALSE,
  keep_attr = TRUE
)

Arguments

C

A numeric matrix representing the contrasts (conditions x contrasts). Row names, if present, should correspond to condition labels and will be preserved. Column names, if present, will be used for the `"source"` attribute if `orth = TRUE` and `keep_attr = TRUE`.

centre

Logical. If TRUE (default), columns of the matrix are mean-centered.

scale

Character string specifying scaling method after centering (if `orth=FALSE`). Options: `"none"` (default), `"sd"` (divide by sample standard deviation), `"l2"` (divide by L2 norm / vector length to get unit vectors). This argument is *ignored* if `orth = TRUE`.

orth

Logical. If FALSE (default), the matrix columns represent the specified contrasts directly (after centering/scaling). If TRUE, an orthonormal basis for the column space is computed via QR decomposition. Resulting columns will be orthogonal and have unit length (L2 norm = 1).

keep_attr

Logical. If TRUE (default) and `orth = TRUE`, the original column names (before orthogonalization) are stored in `attr(C_transformed, "source")`, and names of linearly dependent columns removed during orthogonalization are stored in `attr(C_transformed, "dropped")`.

Value

A transformed numeric matrix. If `orth = TRUE` and `keep_attr = TRUE`, it includes `"source"` and potentially `"dropped"` attributes.

Details

This function is useful for post-processing a contrast matrix, especially one that might have been created by combining outputs from different sources (e.g., theory-driven contrasts and data-driven contrasts) or by direct manual construction.

Scaling

Applied *after* centering if `orth=FALSE`.

  • `"none"`: No scaling.

  • `"sd"`: `scale(..., center=FALSE, scale=TRUE)`. Uses sample standard deviation (N-1 denominator). Note that for columns with few unique values (e.g., a centered +/-1 contrast), the SD can be slightly different depending on whether the number of items is even or odd, due to the N-1 denominator. This might lead to minor differences in scaled norms.

  • `"l2"`: Divides each column by its L2 norm (`sqrt(sum(x^2))`).

Orthogonalization

If `orth = TRUE`, uses `qr.Q(qr(C))` to find an orthonormal basis. The number of columns in the output will be the rank of the input matrix. Columns are renamed `Orth1`, `Orth2`, etc. Scaling is ignored as the columns already have unit L2 norm. If `keep_attr = TRUE`: `attr(C_orth, "source")` stores the names of the original columns that formed the basis for the orthogonalized matrix. `attr(C_orth, "dropped")` stores the names of original columns that were linearly dependent and thus not part of the basis, if any.

Specific Behaviors

  • If `orth = TRUE` and the input matrix has only one column after potential centering, that column is scaled to unit L2 norm. Centering still depends on the `centre` argument.

  • If `centre = FALSE` and `orth = TRUE`, the QR decomposition is performed on the *uncentered* columns.

  • If the mini-DSL `. ` notation is used for `levelsB` and `levelsA` already contains all `labels`, `levelsB` becomes empty, potentially resulting in a constant (zero) column before centering. A warning is issued in this case.

See also

[contrasts()], [make_feature_contrasts()]

Examples

C_manual <- matrix(c( 1,  1,  0,  0,
                     -1,  1,  0,  0,
                      0,  0,  1,  1,
                      0,  0, -1,  1), nrow = 4, byrow = TRUE,
                   dimnames = list(paste0("Cond", 1:4), c("MainA", "MainB")))
#> Error in matrix(c(1, 1, 0, 0, -1, 1, 0, 0, 0, 0, 1, 1, 0, 0, -1, 1), nrow = 4,     byrow = TRUE, dimnames = list(paste0("Cond", 1:4), c("MainA",         "MainB"))): length of 'dimnames' [2] not equal to array extent

# Center and make orthonormal
C_transformed <- transform_contrasts(C_manual, orth = TRUE)
#> Error: object 'C_manual' not found
print(C_transformed)
#> Error: object 'C_transformed' not found
print(attr(C_transformed, "source"))
#> Error: object 'C_transformed' not found

# Center and scale to unit L2 norm
C_l2 <- transform_contrasts(C_manual, scale = "l2")
#> Error: object 'C_manual' not found
print(round(colSums(C_l2^2), 5))
#> Error: object 'C_l2' not found