简体   繁体   English

将矩阵转换为R中的特定列表

[英]Convert a matrix into a specific list in R

"a" is a matrix and "b" is a numeric. “ a”是矩阵,“ b”是数字。 The row number of "a" is the same with the length of "b". 行号“ a”与长度“ 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". 我想将“ a”转换为列表,其中每个对象中的元素数量与“ 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! 非常感谢你的帮助!

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. 这是一个根据b拆分a的选项,由于这将返回原子向量列表,因此我们lapply遍历以再次转换为matrix

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: 或者,如果您不介意data.frame的列表,则可能是:

split(as.data.frame(a), rep(seq_along(b),b))

You could also use mapply() like this: 您也可以像这样使用mapply()

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. 与使用lapply(split(...))相比,此解决方案的速度提高了约1.5倍。

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

We could use split 我们可以使用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM