Imitate Matlab Matrix behavior

hfjn

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?

alexis_laz

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.

edited at
0

Comments

0 comments
Login to comment

Related