Reputation: 788
"a" is a matrix and "b" is a numeric. The row number of "a" is the same with the length of "b".
a<-matrix(1:24,6,4,byrow = T)
b<-c(3,1,2)
I want to convert "a" into a list of which the number of elements in each object is the same with "b". The expected result is as follows:
[[1]]
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[[2]]
[,1] [,2] [,3] [,4]
[1,] 13 14 15 16
[[3]]
[,1] [,2] [,3] [,4]
[1,] 17 18 19 20
[2,] 21 22 23 24
Thank you so much for your help!
Upvotes: 1
Views: 71
Reputation: 108593
You could also use mapply()
like this:
id <- mapply(seq, to=cumsum(b), length.out =b)
lapply(id, function(i) a[i,, drop = FALSE])
Or, if you want to do everything in one go:
mapply(function(i,j){a[seq(to=i, length.out = j),,drop=FALSE]},
i = cumsum(b),
j = b)
Compared to using lapply(split(...)), this solution is about 1.5 times faster.
a<-matrix(1:(87*400),87,400,byrow = TRUE)
b<-c(3, 1, 2, 5, 2, 2, 1, 11, 19, 12, 9, 20)
benchmark(
{
id <- mapply(seq, to=cumsum(b), length.out =b)
lapply(id, function(i)a[i,, drop = FALSE])
},
{
lapply(split(a, rep(seq_along(b),b)), matrix, ncol = ncol(a))
},
replications = 10000
)
gives
replications elapsed relative user.self sys.self user.child sys.child
1 10000 3.53 1.000 3.53 0 NA NA
2 10000 6.02 1.705 5.95 0 NA NA
Upvotes: 3
Reputation: 887851
We could use split
split(as.data.frame(a),cumsum(c(TRUE,diff(sequence(b))!=1)))
#$`1`
# V1 V2 V3 V4
#1 1 2 3 4
#2 5 6 7 8
#3 9 10 11 12
#$`2`
# V1 V2 V3 V4
#4 13 14 15 16
#$`3`
# V1 V2 V3 V4
#5 17 18 19 20
#6 21 22 23 24
Upvotes: 1
Reputation: 70336
Here's an option that will split a
according to b
and since that will return a list of atomic vectors, we lapply
over it to convert to matrix
again.
lapply(split(a, rep(seq_along(b),b)), matrix, ncol = ncol(a))
#$`1`
# [,1] [,2] [,3] [,4]
#[1,] 1 2 3 4
#[2,] 5 6 7 8
#[3,] 9 10 11 12
#
#$`2`
# [,1] [,2] [,3] [,4]
#[1,] 13 14 15 16
#
#$`3`
# [,1] [,2] [,3] [,4]
#[1,] 17 18 19 20
#[2,] 21 22 23 24
Or if you didn't mind a list of data.frame
s it could be:
split(as.data.frame(a), rep(seq_along(b),b))
Upvotes: 6