Janhoo
Janhoo

Reputation: 597

cbind arbitrary length vectors with no warning

I would like to cbind different vectors of non-multiple length. The shorter ones are to be (partly) recycled as in vanilla cbind:

cbind(c(1,2,3),c(4,5))
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    4
Warning message:
In cbind(c(1, 2, 3), c(4, 5)) :
number of rows of result is not a multiple of vector length (arg 2)

The result is as desired, except for the warning. Since I want to use this in an extension, is there a possibility to suppress the warning or better: who knows a straightforeward solution producing the same results with no warning! -- thanks, S.

Upvotes: 0

Views: 615

Answers (2)

Gavin Simpson
Gavin Simpson

Reputation: 174778

Here is one option, wrapping the key concept into a function that arranges for things to just work. The simplest way is just to use rep() on each element of ... to repeat each input vecotr in ... to a common length (i.e. the length of the longest input vector).

This is what I do below using the length.out argument of rep().

CBIND <- function(..., deparse.level = 1) {
  dots <- list(...) ## grab the objects passed in via ... this is a list
  len <- sapply(dots, length) ## find lengths of individual vectors
  ## this applies rep() over dots extending each component vector to length
  ## of longest vector in ...
  dots <- lapply(seq_along(dots),
                 function(i, x, len) rep(x[[i]], length.out = len),
                 x = dots, len = max(len))
  ## need to put everything together so arrange for a call to cbind
  ## passing the extended list of vectors and passing along
  ## the deparse.level argument of cbind
  do.call(cbind, c(dots, deparse.level = deparse.level))
}

This gives:

R> CBIND(c(1,2,3),c(4,5))
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    4
R> CBIND(c(1,2,3),c(4,5), deparse.level = 2)
     c(1, 2, 3) c(4, 5, 4)
[1,]          1          4
[2,]          2          5
[3,]          3          4

I would certainly favour this over simply clobbering warnings with suppressWarnings() wrapped around the call. For production code you want to explicitly handle the cases you want to allow and let warnings propagate in circumstances where the user has done something you didn't account for.

Upvotes: 3

BenBarnes
BenBarnes

Reputation: 19454

You could use suppressWarnings, if you really want:

suppressWarnings(cbind(c(1,2,3),c(4,5)))
#      [,1] [,2]
# [1,]    1    4
# [2,]    2    5
# [3,]    3    4

Upvotes: 2

Related Questions