R提供了两种不同的方法来访问list或data.frame中的元素:[]和[[]]。
这两者之间的区别是什么,什么时候我应该使用其中一个而不是另一个?
R提供了两种不同的方法来访问list或data.frame中的元素:[]和[[]]。
这两者之间的区别是什么,什么时候我应该使用其中一个而不是另一个?
当前回答
请参考以下详细说明。
我使用了R中的内置数据框架,称为mtcars。
> mtcars
mpg cyl disp hp drat wt ...
Mazda RX4 21.0 6 160 110 3.90 2.62 ...
Mazda RX4 Wag 21.0 6 160 110 3.90 2.88 ...
Datsun 710 22.8 4 108 93 3.85 2.32 ...
............
表的顶部行称为标题,其中包含列名。之后的每条水平线表示一个数据行,它以行名开始,然后跟着实际数据。 一行中的每个数据成员称为一个单元格。
单个方括号“[]”运算符
要检索单元格中的数据,可以在单个方括号“[]”操作符中输入它的行坐标和列坐标。这两个坐标用逗号分隔。换句话说,坐标以行位置开始,然后以逗号结尾,以列位置结束。顺序很重要。
例1:-这是mtcars的第一行第二列的单元格值。
> mtcars[1, 2]
[1] 6
例2:-此外,我们可以使用行名和列名来代替数字坐标。
> mtcars["Mazda RX4", "cyl"]
[1] 6
双方括号“[[]]”操作符
我们用双方括号“[[]]”操作符引用数据帧列。
例1:-为了检索内置数据集mtcars的第九列向量,我们编写mtcars[[9]]。
山地车[[9]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...
例2:-我们可以通过名称检索相同的列向量。
MTCARS[[“AM”]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...
其他回答
这两种方法之间的显著区别在于它们用于提取时返回的对象的类别,以及它们是否可以接受一个范围的值,或者在赋值时只接受一个值。
考虑以下列表中的数据提取情况:
foo <- list( str='R', vec=c(1,2,3), bool=TRUE )
假设我们想从foo中提取由bool存储的值,并在if()语句中使用它。这将说明在用于数据提取时[]和[[]]的返回值之间的差异。[]方法返回类list(或者data.frame,如果foo是data.frame)的对象,而[[]]方法返回类由其值的类型决定的对象。
因此,使用[]方法的结果如下:
if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical
class( foo[ 'bool' ] )
[1] "list"
这是因为[]方法返回了一个列表,而列表不是直接传递给if()语句的有效对象。在这种情况下,我们需要使用[[]],因为它将返回存储在'bool'中的“裸”对象,该对象将具有适当的类:
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中的槽保留了它们原来的名称。
R语言定义对于回答这些类型的问题很方便:
http://cran.r-project.org/doc/manuals/R-lang.html#Indexing
R has three basic indexing operators, with syntax displayed by the following examples x[i] x[i, j] x[[i]] x[[i, j]] x$a x$"a" For vectors and matrices the [[ forms are rarely used, although they have some slight semantic differences from the [ form (e.g. it drops any names or dimnames attribute, and that partial matching is used for character indices). When indexing multi-dimensional structures with a single index, x[[i]] or x[i] will return the ith sequential element of x. For lists, one generally uses [[ to select any single element, whereas [ returns a list of the selected elements. The [[ form allows only a single element to be selected using integer or character indices, whereas [ allows indexing by vectors. Note though that for a list, the index can be a vector and each element of the vector is applied in turn to the list, the selected component, the selected component of that component, and so on. The result is still a single element.
作为术语,[[操作符从列表中提取元素,而[操作符获取列表的子集。
哈德利·维克汉姆:
我(蹩脚的外观)修改显示使用tidyverse / purrr:
只是在这里添加[[也用于递归索引。
@JijoMatthew在回答中暗示了这一点,但没有深入探讨。
正如在?"[["中所指出的,像x[[y]]这样的语法,其中长度(y) > 1被解释为:
x[[ y[1] ]][[ y[2] ]][[ y[3] ]] ... [[ y[length(y)] ]]
注意,这并没有改变关于[和[[]之间的主要区别,即前者用于子集设置,后者用于提取单个列表元素。
例如,
x <- list(list(list(1), 2), list(list(list(3), 4), 5), 6)
x
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [1] 1
#
# [[1]][[2]]
# [1] 2
#
# [[2]]
# [[2]][[1]]
# [[2]][[1]][[1]]
# [[2]][[1]][[1]][[1]]
# [1] 3
#
# [[2]][[1]][[2]]
# [1] 4
#
# [[2]][[2]]
# [1] 5
#
# [[3]]
# [1] 6
要得到值3,我们可以这样做:
x[[c(2, 1, 1, 1)]]
# [1] 3
回到上面@JijoMatthew的答案,回想一下r:
r <- list(1:10, foo=1, far=2)
特别是,这解释了我们在误用[[时往往会得到的错误,即:
r[[1:3]]
r[[1:3]]中的错误:递归索引在级别2失败
由于这段代码实际上试图求值r[[1]][[2]][[3]],并且r的嵌套在第一级停止,因此通过递归索引提取的尝试在[[2]]失败,即在第2级。
r[[c("foo", "far")]]错误:下标越界
这里,R正在寻找R [["foo"]][["far"]],而R并不存在,所以我们得到了下标越界错误。
如果这两个错误给出相同的信息,可能会更有帮助/一致一些。