Supose我有一个包含3个元素的列表,每个元素是另外2个元素的列表。第一个是4维向量,第二个是char。以下代码将完全按照我刚才描述的方式生成一个列表:
x <- NULL
for(i in 1:3){
set.seed(i); a <- list(sample(1:4, 4, replace = T), LETTERS[i])
x <- c(x, list(a))
}
它的结构是以下类型的(由于我使用了示例函数,确切的值可能会变化):
> str(x)
List of 3
$ :List of 2
..$ : int [1:4] 2 2 3 4
..$ : chr "A"
$ :List of 2
..$ : int [1:4] 1 3 3 1
..$ : chr "B"
$ :List of 2
..$ : int [1:4] 1 4 2 2
..$ : chr "C"
现在,我有另一个4维向量,比如y
:
y <- 1:4
最后,我想创建一个矩阵,该矩阵由y
与列表中存储的每个4维向量之间的操作(比如总和)产生。对于给定的示例,此矩阵将给出以下结果:
[,1] [,2] [,3]
[1,] 3 2 2
[2,] 4 5 6
[3,] 6 6 5
[4,] 8 5 6
问题:如何以简单而优雅的方式创建上述矩阵?我正在寻找一些可以使用某些apply
函数的解决方案,或者可以以某种我不知道的方式直接使用sum
函数。
答案 0 :(得分:3)
试试这个:
# you can also simply write: sapply(x, function(x) x[[1]]) + y
foo <- function(x) x[[1]]
sapply(x, foo) + y
foo
提取列表中的向量; sapply
将这些向量作为矩阵返回; 更新1
好吧,因为@Frank提到了它。我可能会做一点解释。 R中的'[['
运算符(注意引用!)是一个函数,带有两个参数。第一个是矢量类型对象,如矢量/列表;而第二个是您想要引用的索引。对于以下示例:
a <- 1:4
a[2] # 2
'[['(a, 2) # 2
虽然我的原始答案更容易理解,但它并不是最有效的,因为对于每个列表元素,都会调用两个函数调用来取出向量。如果我们直接使用'[['
,则只调用一个函数调用。因此,我们通过减少函数调用开销来节省时间。当函数很小并且没有太多工作时,函数调用开销会很明显。
R中的运算符本质上是函数。 +
,*
等是算术运算符,您可以通过?'+'
找到它们。同样,您可以找到?'[['
。如果你现在无法做到这一点,请不要太担心。迟早你会得到它。
更新2
我不明白它是如何完成这项工作的。当我只是在控制台上询问[[1]]时,我得到列表的第一个元素(整数向量和char值),而不仅仅是向量。我猜其余部分应该是
sapply
函数的魔力。
啊,如果您难以理解sapply
(或类似lapply
),请考虑以下事项。但我会从lapply
开始。
output <- lapply(x, foo)
正在执行以下操作:
output <- vector("list", length = length(x))
for (i in 1:length(x)) output[[i]] <- foo(x[[i]])
所以lapply
返回一个列表:
> output
[[1]]
[1] 2 2 3 4
[[2]]
[1] 1 4 4 3
[[3]]
[1] 3 1 1 1
是的,lapply
遍历x
的元素,应用函数foo
,并将结果返回到另一个列表中。
sapply
采用了类似的想法,但返回了一个向量/矩阵。您可能认为sapply
将lapply
的结果折叠为矢量/矩阵。
当然,我的这部分解释只是为了让事情变得可以理解。 lapply
和sapply
并未真正实现为R循环。它们更有效率。