【问题标题】:R: operations between vectors inside of lists and vectors outsideR:列表内部的向量和外部向量之间的操作
【发布时间】:2016-06-01 15:37:13
【问题描述】:

假设我有一个包含 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 函数的解决方案。

【问题讨论】:

  • @Zheyuan 我想将种子设置在循环内部(而不是外部)没有好处。

标签: r list vector


【解决方案1】:

试试这个:

# 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 中的 '[[' 运算符(注意引号!)是一个函数,带有两个参数。第一个是vector类型的对象,比如vector/list;而第二个是您要引用的索引。对于以下示例:

a <- 1:4
a[2]  # 2
'[['(a, 2)  # 2

虽然我原来的答案比较容易理解,但并不是最有效的,因为对于每个列表元素,都会调用两个函数调用来取出向量。而如果我们直接使用'[[',只会调用一个函数调用。因此,我们通过减少函数调用开销来节省时间。当函数很小且不做太多工作时,函数调用开销可能会很明显。

R 中的运算符本质上是函数。 +*等是算术运算符,您可以通过?'+'找到它们。同样,您可以找到?'[['。如果您目前无法遵循此操作,请不要太担心。迟早你会得到它。


更新 2

我不明白它实际上是如何完成这项工作的。当我在控制台上简单地询问 [[1]] 时,我得到了列表的第一个元素(整数向量和 char 值),而不仅仅是向量。我想剩下的应该是 sapply 函数的魔力。

啊,如果您在理解sapply(或类似的lapply)方面有困难,请考虑以下内容。但我会从lapply开始。

output &lt;- 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 采用类似的想法,但返回一个向量/矩阵。您可能认为sapplylapply 的结果折叠为向量/矩阵。

当然,我的这部分解释只是为了让事情变得容易理解。 lapplysapply 并没有真正实现为 R 循环。它们更有效率。

【讨论】:

  • 仅供参考,您不需要编写完整的函数定义sapply(x, `[[`, 1) 工作
  • @Zheyuan:谢谢你这么完整的回答。它完美地工作。虽然我理解它是如何工作的——正如你所说,函数foo 提取列表中的向量——但我不明白它实际上是如何完成这项工作的。当我在控制台上简单地询问[[1]] 时,我得到了列表的第一个元素(整数向量和char 值),而不仅仅是向量。我想剩下的应该是sapply 函数的魔力。我会接受你的回答。谢谢。
  • @ZheyuanLi 是的,我现在了解了幕后发生的事情,并且使用sapplylapply 更加自信。很努力,很好的答案!
猜你喜欢
  • 1970-01-01
  • 2011-10-29
  • 1970-01-01
  • 2019-06-06
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多