当使用$符号调用列表的属性时,lapply会生成不同的结果

时间:2014-07-24 12:32:27

标签: r list lapply

当我创建列表并使用“[]”运算符调用列表时,我得到了以下结果

x <- list(a=1:5, b=rnorm(5))
lapply(x[1], mean)
$a
[1] 3
lapply(x[2], sum)
$b
[1] 0.3653843

但是当我使用$ sign调用相同的列表时,我得到了不同的结果

> x <- list(a=1:5, b=rnorm(5))
> lapply(x$a, mean)
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
[1] 4

[[5]]
[1] 5

> lapply(x$b, sum)
[[1]]
[1] 0.7208679

[[2]]
[1] 1.367853

[[3]]
[1] -0.5799428

[[4]]
[1] -2.186257

[[5]]
[1] 0.1597629

无法理解为什么?

3 个答案:

答案 0 :(得分:1)

$[之间存在重大差异。当$返回list元素时,[返回包含一个元素的列表。

> x[1]
$a
[1] 1 2 3 4 5

> x$a
[1] 1 2 3 4 5

x$a的等效表达式为x[[1]][[也返回列表元素。

> x[[1]]
[1] 1 2 3 4 5

由于$[[都返回单个列表元素,因此您无法使用它们返回多个列表元素。但是,您可以使用[返回包含多个元素的列表。例如,

> x[1:2]
$a
[1] 1 2 3 4 5

$b
[1]  0.3465471  0.2955350  1.1292449  1.1136643 -0.9798430

答案 1 :(得分:0)

在第一种情况下,lapply的输入是一个列表,其中一个元素等于c(1:5)或rnorm(5)。在第二种情况下,laply的输入是具有5个元素的向量。因此,mean函数分别获取每个值1,2,3,4,5(在这种情况下不执行任何操作但返回相同的值)。

换句话说,x [1]给出一个元素的列表

> x <- list(a=1:5, b=rnorm(5))
> str(x[1])
List of 1
$ a: int [1:5] 1 2 3 4 5

然而,x $ a等于x [[“a”]]或x [[1]],并给出一个包含5个元素的向量:

str(x$a)
int [1:5] 1 2 3 4 5

答案 2 :(得分:0)

差异相对较小但非常有意义。列表a是向量的奇特单词,其中元素不必是相同类型(int,char,logical等)。实际上,列表的组件可以是任何内容,甚至是其他列表。

使用类比:

矢量是一个盒子。适用于此框的唯一规则是框中的所有内容都属于同一类型。我们放入框中的内容(例如数字或布尔值)称为元素。

列表是一个箱子。对于crates而言,唯一的规则是我们可以将框和其他包装箱放入包装箱而不包含我们放入包装箱中的物品称为组件。

为了从矢量/盒子或列表/板条箱中获取东西,我们使用三个函数(R中的所有内容都是函数),每个函数都有一些不同的含义:

  • 方括号 [k]。这些意味着“从向量中获取第k个元素”,或者在列表“获取列表中的第k个组件”的情况下。你可能会问有什么不同?请求向量中的元素将获得一个值(即TRUE,“john doe”,3),而从列表中请求组件可以使一个向量或另一个列表(在比喻:你从箱子里拿出来的唯一东西就是盒子或箱子)
  • 双方括号 [[k]]。这些意思是“从向量中获取第k个元素的内容”,或者在列表的情况下“获取第k个组件的内容”在列表中*。在向量的情况下,这些双括号不是很有用,因为向量不能包含某些东西反过来包含其他东西。在框中类比:你要求元素的内容。因为一个元素没有内容R选择返回元素本身。在列表的情况下,R转到列表中的第k个组件并返回其内容。使用类比:R转到crate拾取第k个框(或箱子)并返回所述盒子(或箱子)的内容
  • 美元符号 $。这是一个几乎专门用于列表上下文的符号,因为它允许从列表中调用命名组件。此符号的主要好处是,它允许您引用列表中的组件,就好像它们是工作区中的变量一样。

在你的例子中,有两件事情有点不对劲:

首先,lapply是一个apply函数,它希望接收一个list对象作为输入(即使它们没有明确说明)。您可以通过打印lapply代码来看到这一点:

lapply
function (X, FUN, ...) 
{
    FUN <- match.fun(FUN)
    if (!is.vector(X) || is.object(X)) 
        X <- as.list(X)
    .Internal(lapply(X, FUN))
}

请注意,输入R无论是否会将其转换为具有as.list功能的列表。这意味着该函数对组件而不是元素进行操作。

在你的第一个输入

lapply(x[1], mean)
lapply(x[2], sum)

你在第二个输入

给函数一个组件(一个盒子)
lapply(x$a, mean)
lapply(x$b, sum)

您正在提供功能元素。您可以看到R如何处理每个打印的差异。 x$a像矢量一样打印,x[1]像列表一样打印。一旦函数接收到元素,它就会将它们转换为一个列表,假设每个元素都应该是列表中的一个组件,如下面的函数所示:

as.list(x$a)

其中新列表中的每个组件都是具有1个元素的向量。

tl; dr:不要混淆组件和元素:)。

相关问题