访问列表或数据框的元素时,使用方括号 [ ] 和双方括号 [[ ]] 的区别。

56 浏览
0 Comments

访问列表或数据框的元素时,使用方括号 [ ] 和双方括号 [[ ]] 的区别。

R提供了两种不同的方法来访问列表或数据框的元素:[][[]]

它们之间的区别是什么,我应该在什么情况下使用其中一种?

admin 更改状态以发布 2023年5月21日
0
0 Comments

这两种方法的显著区别在于它们在提取时返回的对象类别,以及它们在赋值期间是否可以接受一系列值或仅接受单个值。

考虑以下列表的数据提取情况:

foo <- list( str='R', vec=c(1,2,3), bool=TRUE )

假设我们想要从 foo 中提取 bool 存储的值,并在 if() 语句中使用它。这将说明使用 [][[]] 进行数据提取时返回值之间的差异。使用 [] 方法将返回 class list 的对象(如果 foo 是 data.frame,则为 class data.frame),而 [[]] 方法将返回其 class 受其值类型的影响的对象。

因此,使用 [] 方法会得到以下结果:

if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical
class( foo[ 'bool' ] )
[1] "list"

这是因为 [] 方法返回了一个列表,而列表不能直接传递给 if() 语句。在这种情况下,我们需要使用 [[]],因为它将返回存储在 'bool' 中的“裸”对象,它将具有适当的 class:

if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"
class( foo[[ 'bool' ]] )
[1] "logical"

第二个区别在于,[] 运算符可以用于访问列表中的一系列插槽或数据框中的列,而 [[]] 运算符仅限于访问单个插槽或列。考虑使用第二个列表 bar() 进行值分配的情况:

bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )

假设我们想要用 bar 中的数据覆盖 foo 的最后两个插槽。如果我们尝试使用 [[]] 运算符,会发生以下情况:

foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar : 
more elements supplied than there are to replace

这是因为[[]]只能访问单个元素。我们需要使用[]

foo[ 2:3 ] <- bar
print( foo )
$str
[1] "R"
$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0
$bool
[1] -0.6291121

请注意,尽管赋值成功了,但是foo中的插槽仍然保留其原始名称。

0
0 Comments

R 语言定义很方便回答这些类型的问题:

R 有三个基本的索引操作符,语法如下所示:

    x[i] 
    x[i, j] 
    x[[i]] 
    x[[i, j]] 
    x$a 
    x$"a"

对于向量和矩阵,[[ 形式很少使用,尽管它们与 [ 形式有一些轻微的语义差异(例如,它会删除任何名称或 dimnames 属性,并且使用字符索引来进行部分匹配)。当使用单个索引索引多维结构时,x[[i]]x[i] 将返回 x 的第 i 个连续元素。

对于列表,一般使用 [[ 来选择任意单个元素,而 [ 返回所选元素的列表。

[[ 形式只允许使用整数或字符索引选择单个元素,而 [ 允许通过向量进行索引。但请注意,对于列表,索引可能是一个向量,并且该向量的每个元素依次应用于列表、所选组件、该组件的所选部分等。结果仍然是一个单一的元素。

0