rarraysmatrixrecycle

The recycling rule: proceeding from experience


The "Introduction to R" chapter 5.4.1 states:

The precise rule affecting element by element mixed calculations with vectors and arrays is somewhat quirky and hard to find in the references. From experience we have found the following to be a reliable guide.

  • The expression is scanned from left to right.
  • Any short vector operands are extended by recycling their values until they match the size of any other operands.
  • As long as short vectors and arrays only are encountered, the arrays must all have the same dim attribute or an error results.
  • Any vector operand longer than a matrix or array operand generates an error.
  • If array structures are present and no error or coercion to vector has been precipitated, the result is an array structure with the common dim attribute of its array operands.
  1. Am I correct in saying that one of the official guides for R is trying to assess the recycling rules by experience?

  2. What those rules mean in plain English? For instance, I have trouble with rule 4 to the extent we are comparing the length of a vector with the one of a matrix


Solution

  • 1.

    Yes, experience is invaluable to know how recycling works.

    2.

    In R, a matrix or array is a vector with a dim attribute, a folded vector. One of the documented ways of creating a matrix is precisely to assign a vector a dim attribute:

    x <- 1:4
    dim(x) <- c(2, 2)
    x
    #>      [,1] [,2]
    #> [1,]    1    3
    #> [2,]    2    4
    

    Created on 2025-06-01 with reprex v2.1.1

    So matrices do have a length, if A is a matrix, prod(dim(A)) is equal to length(A).
    If two vectors' lengths are not a multiple of one another and they are added, multiplied or otherwise operated, the shortest recycles and the operation result is the length of the longest, with a warning.
    What that part of R-Intro the OP quotes says is that there is an exception to the recycling rule. When one of the operands is a matrix or array, if recycling of the shortest operand (the matrix) doesn't perfectly fit the longest (the vector), then there is also an error.

    A <- matrix(1:6, nrow = 3L)
    length(A)
    #> [1] 6
    x <- 1:4
    A + x
    #> Warning in A + x: longer object length is not a multiple of shorter object
    #> length
    #>      [,1] [,2]
    #> [1,]    2    8
    #> [2,]    4    6
    #> [3,]    6    8
    x + A
    #> Warning in x + A: longer object length is not a multiple of shorter object
    #> length
    #>      [,1] [,2]
    #> [1,]    2    8
    #> [2,]    4    6
    #> [3,]    6    8
    

    Created on 2025-06-01 with reprex v2.1.1

    So far so good. Now with a vector whose length is not a multiple of 6 and is bigger than the matrix length, 6.

    y <- 1:10
    # both of these sums give errors
    A + y
    #> Warning in A + y: longer object length is not a multiple of shorter object
    #> length
    #> Error: dims [product 6] do not match the length of object [10]
    y + A
    #> Warning in y + A: longer object length is not a multiple of shorter object
    #> length
    #> Error: dims [product 6] do not match the length of object [10]
    
    # coerce to vector, no error, just a warning
    c(A) + y
    #> Warning in c(A) + y: longer object length is not a multiple of shorter object
    #> length
    #>  [1]  2  4  6  8 10 12  8 10 12 14
    

    Created on 2025-06-01 with reprex v2.1.1