I Matlab it is possible to add elements vertically to vector even though their index scope far beyond just the next row. For example:
test = 1:5;
test(5,:) = 1:5;
will return.
1 2 3 4 5
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 2 3 4 5
Is there a nice, not so hacky way to do this in R?
Although joran is probably right about altering your procedure when switching to R, you could exploit the fact that indexing a vector results in enlarging too, as Frank noted in the comments. Taking advantage that matrices are vectors with a "dim" attribute and -for convenience- using the by-column storage of matrices, you could use something like:
add_col = function(x, col, value)
{
nr = NROW(x)
nc = if(col > NCOL(x)) col else NCOL(x)
i1 = nr * (col - 1) + 1
i2 = i1 + length(value) - 1
x[i1:i2] = value
length(x) = nr * nc
dim(x) = c(nr, nc)
return(x)
}
test = 1:5
add_col(test, 3, 1:3)
# [,1] [,2] [,3]
#[1,] 1 NA 1
#[2,] 2 NA 2
#[3,] 3 NA 3
#[4,] 4 NA NA
#[5,] 5 NA NA
t(add_col(add_col(test, 3, 1:3), 6, 4:1))
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 2 3 4 5
#[2,] NA NA NA NA NA
#[3,] 1 2 3 NA NA
#[4,] NA NA NA NA NA
#[5,] NA NA NA NA NA
#[6,] 4 3 2 1 NA
This might be a bit hacky but is not much slower than, just, indexing a vector out of bounds:
X = seq_len(1e5)
microbenchmark::microbenchmark(add_col(X, 1e2, seq_along(X)),
t(add_col(X, 1e2, seq_along(X))), #with a transpose
"[<-"(X, (1e7 - (length(X) - 1)):1e7, seq_along(X)), #just vector out-of-bounds indexing
times = 50)
#Unit: milliseconds
# expr min lq median uq max neval
# add_col(X, 100, seq_along(X)) 34.79408 40.02492 45.61020 63.24266 78.48069 50
# t(add_col(X, 100, seq_along(X))) 79.81389 84.06544 87.57906 102.75845 110.72842 50
# `[<-`(X, (1e+07 - (length(X) - 1)):1e+07, seq_along(X)) 17.25123 18.06138 21.48956 24.69084 48.91988 50
identical(c(add_col(X, 1e2, seq_along(X))), "[<-"(X, (1e7 - (length(X) - 1)):1e7, seq_along(X)))
#[1] TRUE
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments