list 用于访问列表或数据框元素的方括号 [ ] 和双方括号 [[ ]] 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1169456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The difference between bracket [ ] and double bracket [[ ]] for accessing the elements of a list or dataframe
提问by Sharpie
R provides two different methods for accessing the elements of a list or data.frame: []
and [[]]
.
R 提供了两种不同的方法来访问列表或 data.frame 的元素:[]
和[[]]
。
What is the difference between the two an in which situations should I use one over the other?
两者之间有什么区别,在哪种情况下我应该使用一种而不是另一种?
采纳答案by ars
The R Language Definition is handy for answering these types of questions:
R语言定义对于回答这些类型的问题很方便:
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]]
orx[i]
will return thei
th sequential element ofx
.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.
R 具有三个基本的索引运算符,其语法由以下示例显示
x[i] x[i, j] x[[i]] x[[i, j]] x$a x$"a"
对于向量和矩阵,
[[
形式很少使用,尽管它们与形式有一些细微的语义差异[
(例如,它删除任何名称或dimnames 属性,并且部分匹配用于字符索引)。当使用单个索引索引多维结构时,x[[i]]
或x[i]
将返回 的i
第 th 个顺序元素x
。对于列表,通常用于
[[
选择任何单个元素,而[
返回所选元素的列表。该
[[
表单仅允许使用整数或字符索引选择单个元素,而[
允许按向量进行索引。但请注意,对于列表,索引可以是向量,向量的每个元素依次应用于列表、所选组件、该组件的所选组件等。结果仍然是单个元素。
回答by Sharpie
The significant differences between the two methods are the class of the objects they return when used for extraction and whether they may accept a range of values, or just a single value during assignment.
这两种方法之间的显着区别在于它们在用于提取时返回的对象的类,以及它们是否可以接受一系列值,或者在赋值期间仅接受单个值。
Consider the case of data extraction on the following list:
考虑以下列表中的数据提取情况:
foo <- list( str='R', vec=c(1,2,3), bool=TRUE )
Say we would like to extract the value stored by bool from foo and use it inside an if()
statement. This will illustrate the differences between the return values of []
and [[]]
when they are used for data extraction. The []
method returns objects of class list (or data.frame if foo was a data.frame) while the [[]]
method returns objects whose class is determined by the type of their values.
假设我们想从 foo 中提取 bool 存储的值并在if()
语句中使用它。这将说明用于数据提取的返回值[]
和[[]]
何时返回值之间的差异。该[]
方法返回类列表的对象(如果 foo 是 data.frame,则[[]]
返回data.frame),而该方法返回其类由其值的类型确定的对象。
So, using the []
method results in the following:
因此,使用该[]
方法会导致以下结果:
if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical
class( foo[ 'bool' ] )
[1] "list"
This is because the []
method returned a list and a list is not valid object to pass directly into an if()
statement. In this case we need to use [[]]
because it will return the "bare" object stored in 'bool' which will have the appropriate class:
这是因为该[]
方法返回了一个列表,而一个列表不是直接传递到if()
语句中的有效对象。在这种情况下,我们需要使用,[[]]
因为它将返回存储在 'bool' 中的“裸”对象,该对象将具有适当的类:
if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"
class( foo[[ 'bool' ]] )
[1] "logical"
The second difference is that the []
operator may be used to access a rangeof slots in a list or columns in a data frame while the [[]]
operator is limited to accessing a singleslot or column. Consider the case of value assignment using a second list, bar()
:
第二个区别是[]
运算符可用于访问列表中的一系列槽或数据帧中的列,而[[]]
运算符仅限于访问单个槽或列。考虑使用第二个列表赋值的情况bar()
:
bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )
Say we want to overwrite the last two slots of foo with the data contained in bar. If we try to use the [[]]
operator, this is what happens:
假设我们想用 bar 中包含的数据覆盖 foo 的最后两个槽。如果我们尝试使用[[]]
运算符,会发生以下情况:
foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar :
more elements supplied than there are to replace
This is because [[]]
is limited to accessing a single element. We need to use []
:
这是因为[[]]
仅限于访问单个元素。我们需要使用[]
:
foo[ 2:3 ] <- bar
print( foo )
$str
[1] "R"
$vec
[,1] [,2]
[1,] 0 0
[2,] 0 0
$bool
[1] -0.6291121
Note that while the assignment was successful, the slots in foo kept their original names.
请注意,虽然分配成功,但 foo 中的插槽保留了它们的原始名称。
回答by medriscoll
Double brackets accesses a list element, while a single bracket gives you back a list with a single element.
双括号访问列表元素,而单括号返回包含单个元素的列表。
lst <- list('one','two','three')
a <- lst[1]
class(a)
## returns "list"
a <- lst[[1]]
class(a)
## returns "character"
回答by jzadra
回答by jzadra
[]
extracts a list, [[]]
extracts elements within the list
[]
提取列表,[[]]
提取列表中的元素
alist <- list(c("a", "b", "c"), c(1,2,3,4), c(8e6, 5.2e9, -9.3e7))
str(alist[[1]])
chr [1:3] "a" "b" "c"
str(alist[1])
List of 1
$ : chr [1:3] "a" "b" "c"
str(alist[[1]][1])
chr "a"
回答by MichaelChirico
Just adding here that [[
also is equipped for recursive indexing.
只需在此处添加[[
也可用于递归索引。
This was hinted at in the answer by @JijoMatthew but not explored.
@JijoMatthew 在回答中暗示了这一点,但没有进行探讨。
As noted in ?"[["
, syntax like x[[y]]
, where length(y) > 1
, is interpreted as:
如 中所述?"[["
,像x[[y]]
, where 之类的语法length(y) > 1
被解释为:
x[[ y[1] ]][[ y[2] ]][[ y[3] ]] ... [[ y[length(y)] ]]
Note that this doesn'tchange what should be your main takeaway on the difference between [
and [[
-- namely, that the former is used for subsetting, and the latter is used for extractingsingle list elements.
请注意,这不会改变什么应该是关系到您主要的外卖[
和[[
-也就是,前者是用于子集化,而后者用于提取单个列表元素。
For example,
例如,
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
To get the value 3, we can do:
要获得值 3,我们可以执行以下操作:
x[[c(2, 1, 1, 1)]]
# [1] 3
Getting back to @JijoMatthew's answer above, recall r
:
回到上面@JijoMatthew 的回答,回想一下r
:
r <- list(1:10, foo=1, far=2)
In particular, this explains the errors we tend to get when mis-using [[
, namely:
特别是,这解释了我们在误用 时容易得到的错误[[
,即:
r[[1:3]]
Error in
r[[1:3]]
: recursive indexing failed at level 2
错误
r[[1:3]]
:递归索引在级别 2 失败
Since this code actually tried to evaluate r[[1]][[2]][[3]]
, and the nesting of r
stops at level one, the attempt to extract through recursive indexing failed at [[2]]
, i.e., at level 2.
由于此代码实际上尝试评估r[[1]][[2]][[3]]
,并且嵌套r
停止在级别 1,因此通过递归索引提取的尝试在[[2]]
,即级别 2失败。
Error in
r[[c("foo", "far")]]
: subscript out of bounds
错误
r[[c("foo", "far")]]
:下标越界
Here, R was looking for r[["foo"]][["far"]]
, which doesn't exist, so we get the subscript out of bounds error.
在这里,R 正在寻找r[["foo"]][["far"]]
不存在的 ,因此我们得到下标越界错误。
It probably would be a bit more helpful/consistent if both of these errors gave the same message.
如果这两个错误都给出相同的消息,可能会更有帮助/一致。
回答by Jijo Mathew
Both of them are ways of subsetting. The single bracket will return a subset of the list, which in itself will be a list. ie:It may or may not contain more than one elements. On the other hand a double bracket will return just a single element from the list.
它们都是子集的方法。单个括号将返回列表的一个子集,它本身就是一个列表。即:它可能包含也可能不包含多个元素。另一方面,双括号将只返回列表中的一个元素。
-Single bracket will give us a list. We can also use single bracket if we wish to return multiple elements from the list. consider the following list:-
- 单括号会给我们一个列表。如果我们希望从列表中返回多个元素,我们也可以使用单括号。考虑以下列表:-
>r<-list(c(1:10),foo=1,far=2);
Now please note the way the list is returned when I try to display it. I type r and press enter
现在请注意当我尝试显示列表时返回列表的方式。我输入 r 然后按回车
>r
#the result is:-
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
$foo
[1] 1
$far
[1] 2
Now we will see the magic of single bracket:-
现在我们将看到单括号的神奇之处:-
>r[c(1,2,3)]
#the above command will return a list with all three elements of the actual list r as below
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
$foo
[1] 1
$far
[1] 2
which is exactly the same as when we tried to display value of r on screen, which means the usage of single bracket has returned a list, where at index 1 we have a vector of 10 elements, then we have two more elements with names foo and far. We may also choose to give a single index or element name as input to the single bracket. eg:
这与我们尝试在屏幕上显示 r 的值时完全相同,这意味着使用单括号返回了一个列表,其中在索引 1 处我们有一个包含 10 个元素的向量,然后我们还有两个名称为 foo 的元素和远。我们也可以选择给单个索引或元素名称作为单个括号的输入。例如:
> r[1]
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
In this example we gave one index "1" and in return got a list with one element(which is an array of 10 numbers)
在这个例子中,我们给出了一个索引“1”,作为回报,我们得到了一个包含一个元素的列表(这是一个包含 10 个数字的数组)
> r[2]
$foo
[1] 1
In the above example we gave one index "2" and in return got a list with one element
在上面的例子中,我们给出了一个索引“2”,作为回报,我们得到了一个包含一个元素的列表
> r["foo"];
$foo
[1] 1
In this example we passed the name of one element and in return a list was returned with one element.
在这个例子中,我们传递了一个元素的名称,作为回报,返回了一个包含一个元素的列表。
You may also pass a vector of element names like:-
您还可以传递元素名称的向量,例如:-
> x<-c("foo","far")
> r[x];
$foo
[1] 1
$far
[1] 2
In this example we passed an vector with two element names "foo" and "far"
在这个例子中,我们传递了一个带有两个元素名称“foo”和“far”的向量
In return we got a list with two elements.
作为回报,我们得到了一个包含两个元素的列表。
In short single bracket will always return you another list with number of elements equal to the number of elements or number of indices you pass into the single bracket.
简而言之,单括号将始终返回另一个列表,其中元素数等于您传递到单括号中的元素数或索引数。
In contrast, a double bracket will always return only one element.
Before moving to double bracket a note to be kept in mind.
NOTE:THE MAJOR DIFFERENCE BETWEEN THE TWO IS THAT SINGLE BRACKET RETURNS YOU A LIST WITH AS MANY ELEMENTS AS YOU WISH WHILE A DOUBLE BRACKET WILL NEVER RETURN A LIST. RATHER A DOUBLE BRACKET WILL RETURN ONLY A SINGLE ELEMENT FROM THE LIST.
相比之下,双括号总是只返回一个元素。在移动到双括号之前,请记住一个注意事项。
NOTE:THE MAJOR DIFFERENCE BETWEEN THE TWO IS THAT SINGLE BRACKET RETURNS YOU A LIST WITH AS MANY ELEMENTS AS YOU WISH WHILE A DOUBLE BRACKET WILL NEVER RETURN A LIST. RATHER A DOUBLE BRACKET WILL RETURN ONLY A SINGLE ELEMENT FROM THE LIST.
I will site a few examples. Please keep a note of the words in bold and come back to it after you are done with the examples below:
我将在网站上举几个例子。请记下粗体字,并在完成以下示例后返回:
Double bracket will return you the actual value at the index.(It will NOTreturn a list)
双括号将返回索引处的实际值。(它不会返回列表)
> r[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
>r[["foo"]]
[1] 1
for double brackets if we try to view more than one elements by passing a vector it will result in an error just because it was not built to cater to that need, but just to return a single element.
对于双括号,如果我们试图通过传递一个向量来查看多个元素,它会导致错误,因为它不是为了满足这种需要而构建的,而只是为了返回一个元素。
Consider the following
考虑以下
> r[[c(1:3)]]
Error in r[[c(1:3)]] : recursive indexing failed at level 2
> r[[c(1,2,3)]]
Error in r[[c(1, 2, 3)]] : recursive indexing failed at level 2
> r[[c("foo","far")]]
Error in r[[c("foo", "far")]] : subscript out of bounds
回答by Redfoot
To help newbies navigate through the manual fog, it might be helpful to see the [[ ... ]]
notation as a collapsingfunction - in other words, it is when you just want to 'get the data' from a named vector, list or data frame. It is good to do this if you want to use data from these objects for calculations. These simple examples will illustrate.
为了帮助新手在手动迷雾中导航,将[[ ... ]]
表示法视为折叠函数可能会有所帮助- 换句话说,当您只想从命名向量、列表或数据框中“获取数据”时。如果您想使用来自这些对象的数据进行计算,最好这样做。这些简单的例子将说明。
(x <- c(x=1, y=2)); x[1]; x[[1]]
(x <- list(x=1, y=2, z=3)); x[1]; x[[1]]
(x <- data.frame(x=1, y=2, z=3)); x[1]; x[[1]]
So from the third example:
所以从第三个例子:
> 2 * x[1]
x
1 2
> 2 * x[[1]]
[1] 2
回答by submartingale
Being terminological, [[
operator extractsthe element from a list whereas [
operator takes subsetof a list.
从术语上讲,[[
运算符从列表中提取元素,而[
运算符则取列表的子集。
回答by Peter
For yet another concrete use case, use double brackets when you want to select a data frame created by the split()
function. If you don't know, split()
groups a list/data frame into subsets based on a key field. It's useful if when you want to operate on multiple groups, plot them, etc.
对于另一个具体用例,当您要选择由split()
函数创建的数据框时,请使用双括号。如果您不知道,请split()
根据关键字段将列表/数据框分组为子集。如果您想对多个组进行操作、绘制它们等,这将很有用。
> class(data)
[1] "data.frame"
> dsplit<-split(data, data$id)
> class(dsplit)
[1] "list"
> class(dsplit['ID-1'])
[1] "list"
> class(dsplit[['ID-1']])
[1] "data.frame"