Extracting multiple rows from a matrix depending on the identifier given by the vector

Suppose we have a matrix mwith 3 columns and a vector idwith identification for the rows:

m <- matrix(c(1,1,2,1,2,3,2,2,2,3,3,4,6,7,7,
          2,2,2,4,4,5,8,9,9),ncol=3,byrow=T)

# m
#     [,1] [,2] [,3]
#[1,]    1    1    2
#[2,]    1    2    3
#[3,]    2    2    2
#[4,]    3    3    4
#[5,]    6    7    7
#[6,]    2    2    2
#[7,]    4    4    5
#[8,]    8    9    9

id <- c(1,2,3,4,5,1,4,5)

What is the fastest way to extract strings from musing id?

As a result, I would like to have a vector for each unique identifier in id. Sort of:

##[1] 1 1 2 2 2 2
##[2] 1 2 3
##[3] 2 2 2
##[4] 3 3 4 4 4 5
##[5] 6 7 7 8 9 9

My pretty bad solution is too slow for my purposes:

pts_list <- list()
for (i in unique(id)){
  pts_list[[i]] <- as.vector(t(m[id==i,]))
}
pts_list

Here's a little script for checking speed (this is really ugly ...):

pts_list <- list()
m2 <- cbind(m,m,m,m)
m3 <- rbind(m2,m2,m2,m2,m2,m2,m2,m2,m2,m2)
m4 <- rbind(m3,m3,m3,m3,m3,m3,m3,m3,m3,m3)
m5 <- rbind(m4,m4,m4,m4,m4,m4,m4,m4,m4,m4)
m6 <- rbind(m5,m5,m5,m5,m5,m5,m5,m5,m5,m5)
id6 <- rep(1:8000,10)

system.time(
  for (i in unique(id6)){
    pts_list[[i]] <- as.vector(t(m6[id6==i,]))
  }
)

#   user  system elapsed 
#  8.094   1.524   9.617

Any suggestions?

+4
source share
2 answers

If you don't need the order of the values, you can just do

split(m, id)
# $`1`
# [1] 1 2 1 2 2 2
# 
# $`2`
# [1] 1 2 3
# 
# $`3`
# [1] 2 2 2
# 
# $`4`
# [1] 3 4 3 4 4 5
# 
# $`5`
# [1] 6 8 7 9 7 9

, lapply

lapply(split(as.data.frame(m), id), function(x) c(t(x)))
# $`1`
# [1] 1 1 2 2 2 2
# 
# $`2`
# [1] 1 2 3
# 
# $`3`
# [1] 2 2 2
# 
# $`4`
# [1] 3 3 4 4 4 5
# 
# $`5`
# [1] 6 7 7 8 9 9
+5

lapply for

> system.time(
     for (i in unique(id6)){
         pts_list[[i]] <- as.vector(t(m6[id6==i,]))
     }
 )
   user  system elapsed 
   4.74    0.67    5.45 

> system.time(
     pts_list <- lapply(unique(id6), function(x) as.vector(t(m6[id6==x,])))
  )
   user  system elapsed 
   3.92    0.66    4.65 
+2

All Articles