Elegant indexing up to end of vector/matrix

111,090

Solution 1

Sometimes it's easier to tell R what you don't want. In other words, exclude columns from the matrix using negative indexing:

Here are two alternative ways that both produce the same results:

A[, -(1:2)]
A[, -seq_len(2)]

Results:

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    4    5    6    7    8
[2,]    3    4    5    6    7    8
[3,]    3    4    5    6    7    8
[4,]    3    4    5    6    7    8
[5,]    3    4    5    6    7    8

But to answer your question as asked: Use ncol to find the number of columns. (Similarly there is nrow to find the number of rows.)

A[, 3:ncol(A)]

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    4    5    6    7    8
[2,]    3    4    5    6    7    8
[3,]    3    4    5    6    7    8
[4,]    3    4    5    6    7    8
[5,]    3    4    5    6    7    8

Solution 2

For rows (not columns as per your example) then head() and tail() could be utilised.

A <- matrix(rep(1:8, each = 5), nrow = 5)
tail(A, 3)

is almost the same as

A[3:dim(A)[1],]

(the rownames/indices printed are different is all).

Those work for vectors and data frames too:

> tail(1:10, 4)
[1]  7  8  9 10
> tail(data.frame(A = 1:5, B = 1:5), 3)
  A B
3 3 3
4 4 4
5 5 5

For the column versions, you could adapt tail(), but it is a bit trickier. I wonder if NROW() and NCOL() might be useful here, rather than dim()?:

> A[, 3:NCOL(A)]
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    4    5    6    7    8
[2,]    3    4    5    6    7    8
[3,]    3    4    5    6    7    8
[4,]    3    4    5    6    7    8
[5,]    3    4    5    6    7    8

Or flip this on its head and instead of asking R for things, ask it to drop things instead. Here is a function that encapsulates this:

give <- function(x, i, dimen = 1L) {
    ind <- seq_len(i-1)
    if(isTRUE(all.equal(dimen, 1L))) { ## rows
        out <- x[-ind, ]
    } else if(isTRUE(all.equal(dimen, 2L))) { ## cols
        out <- x[, -ind]
    } else {
        stop("Only for 2d objects")
    }
    out
}

> give(A, 3)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    1    2    3    4    5    6    7    8
[2,]    1    2    3    4    5    6    7    8
[3,]    1    2    3    4    5    6    7    8
> give(A, 3, dimen = 2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    4    5    6    7    8
[2,]    3    4    5    6    7    8
[3,]    3    4    5    6    7    8
[4,]    3    4    5    6    7    8
[5,]    3    4    5    6    7    8

Solution 3

You can use the following instruction:

A[, 3:length(A[, 1])]
Share:
111,090

Related videos on Youtube

Tomas
Author by

Tomas

Updated on March 30, 2022

Comments

  • Tomas
    Tomas about 2 years

    Is it possible in R to say - I want all indices from position i to the end of vector/matrix? Say I want a submatrix from 3rd column onwards. I currently only know this way:

    A = matrix(rep(1:8, each = 5), nrow = 5) # just generate some example matrix...
    
    A[,3:ncol(A)] # get submatrix from 3rd column onwards
    

    But do I really need to write ncol(A)? Isn't there any elegant way how to say "from the 3rd column onwards"? Something like A[,3:]? (or A[,3:...])?

  • Carl Witthoft
    Carl Witthoft over 4 years
    If you're going to be doing a lot of subsetting, first create dima <- dim(A) and then just referenceit, e.g. ` A[,3:dima[1]]`
  • josephwb
    josephwb about 3 years
    Your length(A[, 1]) gives the number of rows, but you are indexing the columns. If you want to use this type of approach, it should instead be 3:length(A[1,])