목록 또는 데이터 프레임의 요소에 액세스하기위한 대괄호 []와 이중 대괄호 [[]]의 차이점


521

R 목록 또는 data.frame의 요소를 액세스하는 두 다른 방법을 제공 []하고 [[]].

어떤 상황에서 다른 상황을 사용해야하는지 두 사람의 차이점은 무엇입니까?

답변:


327

R 언어 정의는 다음 유형의 질문에 대답하는 데 편리합니다.

R에는 세 가지 기본 색인 연산자가 있으며 다음 예제에서 구문이 표시됩니다.

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

벡터 및 행렬의 경우 [[형식과 약간의 의미 차이가 있지만 형식은 거의 사용되지 않습니다 [(예 : 이름 또는 dimnames 특성이 삭제되고 문자 색인에 부분 일치가 사용됨). 단일 인덱스 다차원 구조를 인덱싱하는 경우 x[[i]]또는 x[i]복귀한다 i토륨 순차 소자 x.

목록의 경우 일반적으로 [[단일 요소를 선택하는 데 사용 하는 반면 [선택한 요소의 목록을 반환합니다.

[[형식을 사용하면 정수 또는 문자 인덱스를 사용하여 단일 요소 만 선택할 [수 있지만 벡터를 사용하여 인덱싱 할 수 있습니다. 목록의 경우 인덱스는 벡터 일 수 있으며 벡터의 각 요소는 목록, 선택한 구성 요소, 해당 구성 요소의 선택된 구성 요소 등에 차례로 적용됩니다. 결과는 여전히 단일 요소입니다.


6
단일 숫자 대 벡터로 색인하기 위해 [[vs []를 사용하는 이유는 무엇입니까? 왜 둘 다에 [를 사용하지 않습니까? [[를 사용하여 단일 항목을 다시 가져올 수 있고 [하나의 색인으로 길이가 1 인 목록을 반환 할 수는 있지만] 목록 대신 하나의 색인으로 단일 항목을 반환하도록하는 이유는 무엇입니까? 왜 length-1 목록을 반환하고 싶습니까?
wordsforthewise

4
@words 따라서 프로그래밍 할 때 인덱싱에 사용하려는 정의되지 않은 길이의 벡터를 가질 수 있습니다. 데 [당신이 동일한 출력 클래스를 얻을 목록 수단 반환 항상 x[v]관계없이 길이를 v. 예를 들어, lapply목록의 하위 집합을 살펴 보고 싶을 수 있습니다 lapply(x[v], fun). 경우 [길이 하나의 벡터의 목록을 드롭 것,이 때마다 오류가 반환 v길이를 가지고 있습니다.
Axeman

1
나는 이것이 더 명확하게 설명되어 있다고 생각한다. adv-r.had.co.nz/Subsetting.html
The Red Pea

171

두 방법 사이의 중요한 차이점은 추출에 사용될 때 반환하는 객체의 클래스와 값의 범위를 허용하는지 또는 할당하는 동안 단일 값을 허용하는지 여부입니다.

다음 목록에서 데이터 추출의 경우를 고려하십시오.

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

foo에서 bool에 의해 저장된 값을 추출하여 if()명령문 내에서 사용한다고 가정하십시오 . 이것은 데이터 추출에 사용될 때 의 반환 값 []과 그 [[]]때 의 차이점을 보여줍니다 . 이 []메소드는 클래스 목록의 오브젝트 (또는 foo가 data.frame 인 경우 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'에 저장된 "bare"객체를 반환 하기 때문에 사용해야 합니다.

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) )

foo의 마지막 두 슬롯을 bar에 포함 된 데이터로 덮어 쓰려고합니다. [[]]연산자 를 사용하려고하면 다음 과 같이됩니다.

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의 슬롯은 원래 이름을 유지했습니다.


111

이중 괄호는 목록 요소에 액세스하는 반면 단일 괄호는 단일 요소가 포함 된 목록을 제공합니다.

lst <- list('one','two','three')

a <- lst[1]
class(a)
## returns "list"

a <- lst[[1]]
class(a)
## returns "character"


48

[]목록을 추출하고 목록 [[]]내의 요소를 추출합니다.

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"

18

재귀 색인 생성을[[ 위해 여기에 추가하기 만하면됩니다. 됩니다.

이것은 @JijoMatthew의 답변에서 암시되었지만 탐색되지 않았습니다.

에서 언급했듯이 , where ?"[["와 같은 구문은 다음과 같이 해석됩니다.x[[y]]length(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레벨 1에서 중지 되었기 때문에 순환 인덱싱을 통한 추출 시도 [[2]]는 레벨, 즉 레벨 2에서 실패했습니다 .

오류 r[[c("foo", "far")]]: 아래 첨자 범위를 벗어남

여기서 R은 찾고있었습니다 r[["foo"]][["far"]] 존재하지 않는 있었으므로 첨자 범위를 벗어났습니다.

이러한 오류가 모두 동일한 메시지를 표시하면 약간 더 도움이 될 수 있습니다.


안녕하세요 Micheal 선생님, 여러 인덱싱에 [[]]를 사용할 수 있습니까?
Therii

14

둘 다 하위 설정 방법입니다. 단일 괄호는 목록의 하위 집합을 반환하며 그 자체가 목록이됩니다. 즉, 둘 이상의 요소를 포함하거나 포함하지 않을 수 있습니다. 반면에 이중 괄호는 목록에서 단일 요소 만 반환합니다.

단일 괄호는 우리에게 목록을 제공합니다. 목록에서 여러 요소를 반환하려는 경우 단일 괄호를 사용할 수도 있습니다. 다음 목록을 고려하십시오.

>r<-list(c(1:10),foo=1,far=2);

이제 목록을 표시하려고 할 때 목록이 반환되는 방식에 유의하십시오. r을 입력하고 Enter 키를 누릅니다

>r

#the result is:-

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

$foo

[1] 1

$far

[1] 2

이제 우리는 단일 괄호의 마술을 볼 것입니다 :-

>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

화면에 r의 값을 표시하려고 할 때와 정확히 일치합니다. 즉, 단일 괄호를 사용하면 목록이 반환됩니다. 인덱스 1에는 벡터가 10 개의 요소가 있고 이름이 foo 인 요소가 두 개 더 있습니다. 그리고 지금까지. 단일 괄호에 대한 입력으로 단일 색인 또는 요소 이름을 제공 할 수도 있습니다. 예 :

> r[1]

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

이 예제에서 우리는 하나의 인덱스 "1"을 주었고 그에 따라 하나의 요소 (10 개의 숫자 배열)를 가진리스트를 얻었습니다.

> r[2]

$foo

[1] 1

위의 예제에서 우리는 하나의 인덱스 "2"를 주었고 그에 따라 하나의 요소를 가진리스트를 얻었습니다

> r["foo"];

$foo

[1] 1

이 예제에서 우리는 하나의 요소의 이름을 전달했고 그 결과로 하나의 요소와 함께 목록이 반환되었습니다.

다음과 같은 요소 이름의 벡터를 전달할 수도 있습니다.

> x<-c("foo","far")

> r[x];

$foo

[1] 1

$far
[1] 2

이 예에서는 "foo"및 "far"라는 두 요소 이름을 가진 벡터를 전달했습니다.

그 대가로 우리는 두 가지 요소가있는 목록을 얻었습니다.

짧은 단일 괄호는 항상 단일 괄호에 전달하는 요소 수 또는 색인 수와 동일한 요소 수를 가진 다른 목록을 반환합니다.

반대로 이중 괄호는 항상 하나의 요소 만 반환합니다. 이중 브래킷으로 이동하기 전에 명심해야 할 메모입니다. 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.

몇 가지 예를 들어 보겠습니다. 굵게 표시된 단어를 메모하고 아래 예를 수행 한 후에 다시 입력하십시오.

이중 괄호는 인덱스의 실제 값을 반환합니다 (목록을 반환 하지는 않음 ).

  > r[[1]]

     [1]  1  2  3  4  5  6  7  8  9 10


  >r[["foo"]]

    [1] 1

이중 괄호의 경우 벡터를 전달하여 둘 이상의 요소를 보려고하면 해당 요구를 충족시키지 않고 단일 요소를 반환하기 때문에 오류가 발생합니다.

다음을 고려하세요

> 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

1
"벡터를 전달하는 중 ... 그 요구를 충족시키기 위해 만들어지지 않았기 때문에 오류가 발생합니다." 내 새로운 답변을 참조하십시오.
MichaelChirico

1
"더블 브라켓은 절대로 목록을 반환하지 않는 동안"과 같은 강력한 주장을하기 때문에 공감. 사실이 아닙니다-리스트의리스트 인 객체가 있다면, 이중 괄호는 다른리스트를 반환합니다.
dabsingh

13

초보자가 수동 포그를 탐색하는 데 도움을주기 위해 [[ ... ]]표기법을 접는 기능 으로 보는 것이 도움이 될 수 있습니다. 즉, 명명 된 벡터, 목록 또는 데이터 프레임에서 '데이터를 가져 오기'를 원할 때입니다. 이러한 개체의 데이터를 계산에 사용하려면이 작업을 수행하는 것이 좋습니다. 이 간단한 예가 설명합니다.

(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]]

세 번째 예에서

> 2 * x[1]
  x
1 2
> 2 * x[[1]]
[1] 2

1
초보자로서, "<-"의 대상인 x와 혼동을 피하기 위해 x를 3으로 지정 ( "<-"사용)하여 x = 1을 w = 1로 바꾸는 것이 유용하다는 것을 알았습니다.
user36800

매우 간단하지만이 설명이 정말 마음에 듭니다. 또 다른 간단한 데모 : iris[[1]]벡터를 iris[1]반환 하지만
data.frame을

11

용어 적으로 [[연산자 목록에서 요소를 추출 하는 반면 [연산자는 목록의 하위 집합 을 가져옵니다 .


7

또 다른 구체적인 사용 사례의 경우 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"

-1

아래의 자세한 설명을 참조하십시오.

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 : 내장 데이터 세트 mtcar의 9 번째 열 벡터를 검색하기 위해 mtcars [[9]]를 작성합니다.

mtcars [[9]] [1] 110100000 ...

예 2 :-이름으로 같은 열 벡터를 검색 할 수 있습니다.

mtcars [[ "am"]] [1] 1 1 0 0 0 0 0 0 ...


-1

게다가:

답변링크 에 따라 여기.

다음은 다음 사항을 다루는 작은 예입니다.

x[i, j] vs x[[i, j]]

df1   <- data.frame(a = 1:3)
df1$b <- list(4:5, 6:7, 8:9)

df1[[1,2]]
df1[1,2]

str(df1[[1,2]])
str(df1[1,2])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.