1) base Create a matrix of NA values of the requisite dimensions and then fill it with cv
up to its length. Transpose that and convert to a data frame.
mat <- t(replace(matrix(NA, 6, ceiling(length(cv) / 6)), seq_along(cv), cv))
as.data.frame(mat, stringsAsFactors = FALSE)
2) another base solution Using the cv2
copy of cv
expand its length to that required and then reshape it into a matrix. We used cv2
in order to preserve the original cv
but if you don't mind adding NAs to the end of cv
then you could just use it instead of creating cv2
reducing the code by one line (two lines if we can use mat
rather than needing a data frame). This solution avoids needing to use transpose by making use of the byrow
argument of matrix
.
cv2 <- cv
length(cv2) <- 6 * ceiling(length(cv) / 6)
mat <- matrix(cv2,, 6, byrow = TRUE)
as.data.frame(mat, stringsAsFactors = FALSE)
3) base solution using ts This one gets the row and column indexes by extracting them from the times of a ts
object rather than calculating the dimensions via numeric calculation. To do that create the times, tt
, of a ts
object from cv
. tt
itself is a ts
object for which as.integer(tt)
is the row index numbers and cycle(tt)
is the column index numbers. Finally use tapply
with that:
tt <- time(ts(cv, frequency = 6))
mat <- tapply(cv, list(as.integer(tt), cycle(tt)), c)
as.data.frame(mat, stringsAsFactors = FALSE)
4) rollapply Like (3) this one does not explicitly calculate the dimensions of mat
. It uses rollapply
in the zoo package with a simple function, Fill
r to avoid this. The Fill
function returns its argument x
padded out with NAs on the right to a length of 6.
library(zoo)
Fill <- function(x) { length(x) <- 6; x }
mat <- rollapplyr(cv, 6, by = 6, Fill, align = "left", partial = TRUE)
as.data.frame(mat, stringsAsFactors = FALSE)
In all alternatives above omit the last line if a matrix mat
is adequate as the result.
Added
As of R 4.0 stringsAsFaactors=FALSE
is the default so it could be omitted above.