[R] How to extract from a matrix based on indices in a vector?

William Dunlap wdunlap at tibco.com
Thu Jun 11 02:05:13 CEST 2009


Subscripting by a 2-column matrix 
   M[cbind(v, seq_len(ncol(M)))]
uses much less space (hence time) than making
the ncol(M) by ncol(M) intermediate matrix just
to extract its diagonal.  E.g.

test <- function(n, seed) {
   if (!missing(seed))
      set.seed(seed)
   M <- matrix(sample(LETTERS, 2*n, replace = TRUE), 2)
   v <- sample(2, n, replace=T)
   t1<-system.time(r1<-M[cbind(v,seq_len(ncol(M)))])
   t2<-system.time(r2<-diag(M[v, 1:ncol(M)]))
   list(identical=identical(r1,r2), "time(matrix subscript)"=t1,
"time(diag(big matrix))"=t2)
}

>  test(100)
$identical
[1] TRUE

$`time(matrix subscript)`
   user  system elapsed
  0.000   0.000   0.001

$`time(diag(big matrix))`
   user  system elapsed
  0.001   0.000   0.001

> test(1000)
$identical
[1] TRUE

$`time(matrix subscript)`
   user  system elapsed
  0.000   0.000   0.001

$`time(diag(big matrix))`
   user  system elapsed
  0.082   0.021   0.103

> test(5000)
$identical
[1] TRUE

$`time(matrix subscript)`
   user  system elapsed
  0.001   0.000   0.001

$`time(diag(big matrix))`
   user  system elapsed
  3.379   0.552   3.932


Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com  

> -----Original Message-----
> From: r-help-bounces at r-project.org 
> [mailto:r-help-bounces at r-project.org] On Behalf Of Marc Schwartz
> Sent: Wednesday, June 10, 2009 4:42 PM
> To: Logickle
> Cc: rhelp help
> Subject: Re: [R] How to extract from a matrix based on 
> indices in a vector?
> 
> 
> On Jun 10, 2009, at 6:26 PM, Marc Schwartz wrote:
> 
> >
> > On Jun 10, 2009, at 12:36 PM, Logickle wrote:
> >
> >>
> >> Sorry, there may be some lingo for describing the extraction  
> >> problem I have,
> >> but I don't know it.
> >>
> >> I have a matrix of 2 rows and N columns, and a vector of N 
> 1s and 2s.
> >>
> >> Matrix M:
> >>
> >>     1     2     3      4   ...  N
> >> 1    A     C     D      G  ...
> >> 2    B     D     F      H   ...
> >>
> >> Vector v:
> >>
> >> 1  2  2  1  2  1  1 ... N
> >>
> >> I'd like to apply v to M to get
> >>
> >> Vector w:
> >>
> >> A  D  F  G ...
> >>
> >> I.e. each element of v is interpreted as a row-index used to  
> >> extract that
> >> row's value from the corresponding column in M into the  
> >> corresponding column
> >> of w.
> >>
> >> Also eventually nrow(M) > 2, in which case the value of the  
> >> elements of v
> >> would range over 1:nrow(M).
> >>
> >> Seems it should be simple, but maybe not?
> >>
> >> Thanks!
> >>
> >> Doug
> >
> > Doug,
> >
> > Try this:
> >
> > # M is a character matrix
> > > M
> >  1   2   3   4
> > 1 "A" "C" "D" "G"
> > 2 "B" "D" "F" "H"
> >
> > # v is a vector, equal in length to the number of columns in M
> > > v
> > [1] 1 2 2 1
> >
> > # Get the diagonal of the matrix that results from the 
> combinations  
> > of indices
> > > diag(M[v, 1:ncol(M)])
> > [1] "A" "D" "F" "G"
> >
> >
> > I created a larger 2 row matrix to test further:
> >
> > set.seed(1)
> > M <- matrix(sample(LETTERS, 40, replace = TRUE), 2, 20)
> >
> > > M
> >     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
> > [1,] "G"  "O"  "F"  "Y"  "Q"  "F"  "R"  "U"  "S"  "J"   "Y"   "Q"
> > [2,] "J"  "X"  "X"  "R"  "B"  "E"  "J"  "M"  "Z"  "U"   "F"   "D"
> >     [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20]
> > [1,] "G"   "A"   "W"   "M"   "M"   "V"   "U"   "S"
> > [2,] "K"   "J"   "I"   "P"   "E"   "R"   "C"   "K"
> >
> >
> > and 'v':
> >
> > set.seed(2)
> > v <- sample(2, 20, replace = TRUE)
> >
> > > v
> > [1] 1 2 2 1 2 2 1 2 1 2 2 1 2 1 1 2 2 1 1 1
> >
> >
> > Then:
> >
> > > diag(M[v, 1:ncol(M)])
> > [1] "G" "X" "X" "Y" "B" "E" "R" "M" "S" "U" "F" "Q" "K" "A" 
> "W" "P"  
> > "E"
> > [18] "V" "U" "S"
> >
> >
> > Looks like it might work.
> 
> 
> 
> Actually, the solution can be simplified further:
> 
> # Using the second 'M':
> 
>  > diag(M[v, ])
> [1] "G" "X" "X" "Y" "B" "E" "R" "M" "S" "U" "F" "Q" "K" "A" 
> "W" "P" "E"
> [18] "V" "U" "S"
> 
> Marc
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide 
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
> 




More information about the R-help mailing list