[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