【问题标题】:R use of lapply & sapply to interrogate list of matrices containing permuted dataR 使用 lapply 和 sapply 来询问包含置换数据的矩阵列表
【发布时间】:2013-11-02 03:19:42
【问题描述】:

我有 3 个数据集,我排列了 10 倍。数据集的每个排列在 3 个矩阵中构成一列(每个数据集一个矩阵)。这 3 个矩阵 (m1,m2,m3) 在列表 L 中。我想为每个条目(在本例中为 4)询问所有可能的组合(10x10x10=1000)。我已经使用 expand.grid 来提供跨另一个矩阵 M 行中的 3 个矩阵的所有列调用组合:

M<-expand.grid(seq(1:10),seq(1:10),seq(1:10))

这是我在列表中的数据:

m1<-matrix(c(1,2,1,0,3,2,1,2,3,4),nrow=4, ncol=10)
m2<-matrix(c(m1[1,]),nrow=4,ncol=10)
m3<-matrix(c(m1[2,]),nrow=4,ncol=10)
L<-list(m1, m2, m3)

你能帮我用do.call,cbind,lapply/sapply有效地从M中检索列坐标来询问L中包含的3个矩阵中的对应列并将它们绑定到一个新矩阵像这样:

m.res<-for (i in 1:nrow(M) { "get" L[[1:3]][M[i,]] }

对于i=1m.res 将产生:

1 1 2
2 3 2
1 3 4
0 1 0

我显然需要lapply/sapply 的教程,因为这应该不难。

【问题讨论】:

  • 我在您的代码中将 test 更改为 M。如果这不是您想要的,请为test 添加一个定义。
  • +1 例如输入数据和所需输出。下次还要展示您尝试过的方法以及如何它不起作用,这将是一个完美的问题。
  • @SimonO101 好点!我在这台笔记本电脑上没有我的 .Rhistory,但我记得我尝试了各种方案将元素从 M 直接传递到 L 以子集所需的列。然后我意识到我需要使用 apply
  • @nico 是的,你是对的,谢谢你解决这个问题!

标签: r list matrix permutation apply


【解决方案1】:

首先,我们应该获得检索单行的正确方法。 所以,对于第 1 行 (1,1,1)

我们想要遍历L 的三个元素并检索一个矩阵,其中包含M 中第1 行的索引

col.ids <- unlist(M[1,])
# sapply will already return the columns in a matrix
# We use seq_along rather than looping directly on L, because we also need the
# id for col.ids
sapply(seq_along(L), function(id){
                        L[[id]][ ,col.ids[id] ]
                        })

     [,1] [,2] [,3]
[1,]    1    1    2
[2,]    2    3    2
[3,]    1    3    4
[4,]    0    1    0

现在只需将其放入另一个 apply 语句中即可!

这次我们使用apply,直接循环M的行(从而消除了col.ids变量的需要)

# The second parameter is 1 for rows and 2 for columns
m.comb <- apply(M, 1, function(cols)
                      {
                      sapply(seq_along(L), function(id){
                                               L[[id]][ ,cols[id] ]
                                               })
                      })

现在,apply 给了我们一个 12 x 1000 的大矩阵,在这种情况下这很烦人,所以我们应该把它变成一个列表......我将把它留给读者作为练习......

... 或者更确切地说使用plyr 包的alply 函数,它的工作方式与apply 完全相同,但总是返回一个列表(参见Force apply to return a list

但是,在这种情况下,我们需要取消列出 cols

library(plyr)
m.comb.2 <- alply(M, 1, function(cols)
                       {
                       cols <- unlist(cols)
                       sapply(seq_along(L), function(id)
                              {
                              L[[id]][ ,cols[id] ]
                              })
                       })

最后……

m.comb.2[[1]]

     [,1] [,2] [,3]
[1,]    1    1    2
[2,]    2    3    2
[3,]    1    3    4
[4,]    0    1    0

m.comb.2[[10]]

     [,1] [,2] [,3]
[1,]    1    1    2
[2,]    2    3    2
[3,]    3    3    4
[4,]    4    1    0

【讨论】:

  • 效果很好,谢谢你解释得这么好!!最后我可能会使用 plyr 包,但我将首先尝试将 m.comb 强制放入列表中(明天第一件事 :-) 这是一个非常有用的答案,我希望我能多次投票!跨度>
  • 同时感谢@nico,我已经咨询了这个问题6819804 以使用split() 将矩阵转换为列表。这样我最终得到了一个包含 1000 个(4*3 大小)向量的列表,我可以通过适当的子集来处理,但是......
  • ...我现在意识到我遇到了一个新问题:24 个数据集 x 34000 个数据点 x 1000 个随机播放 x 8 个字节 = 6.6 Gb 仅用于随机播放的数据...缺少可用内存。我可能最终不得不将其作为一个单独的问题发布。呃 - 现在我也不得不担心内存管理。无论如何,这不是这个问题的一部分。
【解决方案2】:

[我会将其添加为@nico 答案的评论,但我希望它比评论更干净和扩展。如果@nico 觉得在他的详细答案中添加它有用,我的答案应该被删除。]

您也可以使用mapply,即您可以将检索函数应用于多个参数(因为只有 3 个参数),这在M 中已有。

#`M` is your dataframe of arguments and `L` is your list of matrices
#save all results to a list (`myls`)
myls <- mapply(function(colmat1, colmat2, colmat3) 
               { cbind(L[[1]][,colmat1], L[[2]][,colmat2], L[[3]][,colmat3]) }, 
                      M[,1], M[,2], M[,3], SIMPLIFY = F)

myls[[1]]
#     [,1] [,2] [,3]
#[1,]    1    1    2
#[2,]    2    3    2
#[3,]    1    3    4
#[4,]    0    1    0
myls[[10]]
#     [,1] [,2] [,3]
#[1,]    1    1    2
#[2,]    2    3    2
#[3,]    3    3    4
#[4,]    4    1    0

【讨论】:

  • 好答案!由于某种原因,我总是倾向于忘记mapply :)
  • @alexis_laz 谢谢你,这个解决方案,但我需要一些可以毫不费力地扩展到排列数量的东西。我没有在问题中包含此信息,但我想将数据洗牌 100 或 1000 次。这仍然非常有帮助,因为我以前没有使用过 mapply!谢谢!
猜你喜欢
  • 2018-02-03
  • 1970-01-01
  • 2021-09-21
  • 2023-03-06
  • 2021-05-08
  • 1970-01-01
  • 2019-11-17
  • 2020-01-25
  • 1970-01-01
相关资源
最近更新 更多