`[`가`subset`보다 나은 이유는 무엇입니까?


400

data.frame을 필터링해야 할 때, 즉 특정 조건을 만족하는 행을 추출하려면 subset함수 를 사용하는 것이 좋습니다 .

subset(airquality, Month == 8 & Temp > 90)

[기능이 아닌 :

airquality[airquality$Month == 8 & airquality$Temp > 90, ]

내가 선호하는 두 가지 주요 이유가 있습니다.

  1. 왼쪽에서 오른쪽으로 코드가 더 잘 읽 힙니다. R에 대해 전혀 모르는 사람들조차도 subset위 의 진술이 무엇을하고 있는지 말할 수 있습니다.

  2. select표현식 에서 열을 변수 라고 할 수 있으므로 몇 가지 키 입력을 저장할 수 있습니다. 위의 예에서는로 airquality한 번만 입력 하고 subset로 세 번 입력해야했습니다 [.

그래서 나는 subset짧고 잘 읽히기 때문에 어디에서나 행복하게 살고 있었고, 동료 R 코더에게 아름다움을 옹호하기까지했습니다. 그러나 어제 세상은 무너졌습니다. subset설명서를 읽는 동안 이 섹션을 확인했습니다.

경고

대화식으로 사용하기위한 편리한 기능입니다. 프로그래밍의 경우에는 [와 같은 표준 하위 설정 기능을 사용하는 것이 좋으며, 특히 인수 하위 집합의 비표준 평가는 예상치 못한 결과를 초래할 수 있습니다.

저자가 무엇을 의미하는지 명확히하는 데 도움이 될 수 있습니까?

먼저, " 대화식으로 사용 "이란 무엇을 의미 합니까? BATCH 모드에서 실행되는 스크립트와 달리 대화 형 세션이 무엇인지 알고 있지만 어떤 차이가 있는지는 알 수 없습니다.

그런 다음 " 비표준 부분 집합의 비표준 평가 "를 설명 하고 왜 위험한지 설명해 주시겠습니까?


14
함께 사용하는 것이 약간 적습니다 (그러나 하위 집합보다 너트는 적음).with(airquality, airquality[Month == 8 & Temp > 90, ])
Tyler Rinker

7
'The R Inferno'의 Cirlces 8.2.31 및 8.2.32도 참조하십시오. burns-stat.com/pages/Tutor/R_inferno.pdf
Patrick Burns

9
대신 data.table을 사용하면 기본 구문은 airquality [Month == 8 & Temp> 90,]와 같이 매우 읽기 쉽고 훨씬 빠릅니다.
Stian Håklev

3
확인. 따라서 부분 집합이 사용하기에 좋지 않은 경우 [어떻게 dplyr :: filter ()?
userJT

4
궁금한 사람들도 dplyr::filter같은 문제가 있습니다. 즉, 환경에 해당 이름의 변수가 있으면 데이터 프레임의 변수 대신 변수를 사용합니다. 혼란스러운 디버깅을 만듭니다!
Deleet

답변:


241

이 질문의 위험 해들리 위컴의 탁월한 설명을 가리키는 @ 제임스에 의해 코멘트에 잘 대답했다 subset(그 같은 및 기능) [여기] . 읽어봐!

다소 오래 읽었으므로 Hadley가 "무엇이 잘못 될 수 있는가?"라는 질문을 가장 직접적으로 다루는 사례를 여기에 기록하면 도움이 될 수 있습니다.

Hadley는 다음 예제를 제안합니다. 다음 함수를 사용하여 데이터 프레임을 서브 세트 한 다음 재정렬하려고한다고 가정하십시오.

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
  scramble(subset(x, condition))
}

subscramble(mtcars, cyl == 4)

오류가 반환됩니다.

eval (expr, envir, enclos) 오류 : 'cyl'개체를 찾을 수 없습니다

R은 더 이상 'cyl'이라는 객체를 찾을 위치를 "알지"않기 때문입니다. 그는 또한 지구 환경에 'cyl'이라는 물체가 있으면 우연히 일어날 수있는 기괴한 점을 지적합니다.

cyl <- 4
subscramble(mtcars, cyl == 4)

cyl <- sample(10, 100, rep = T)
subscramble(mtcars, cyl == 4)

(그들을 실행하고 직접 참조하십시오, 그것은 꽤 미쳤습니다.)


2
설명을위한 몇 가지 초보자 질문이 있습니까? 우리가 subset(mtcars, cyl == 4)(최상위 수준에서) 글을 쓸 때 , R은 어디서 cyl을 찾습니까? 가에 보이는 경우 mtcars에 전달되는 객체 subset(), 찾을 수 없습니다해야 cyl하는 경우도 scramble있기 때문에, 다른 함수 내에 mtcars여전히 전달되고있다? 내 질문이 이해가되지 않으면 R이 더 이상 찾을 수없는 이유를 더 자세히 설명 할 수 있습니다 cyl. 감사!
Heisenberg

4
@Anh Inside subset.data.frame, 그 시점에서 우리가 평가하려고하는 것은 단지 condition입니다. 에 존재하지 않습니다 mtcars. 그래서 subset.data.frame사용 enclos = parent.frame()하는이 보장 condition올바르게으로 평가된다 cyl == 4. 그러나 우리는 둘러싸는 프레임으로 돌아 왔으며 이제 R이 찾을 때 cyl더 이상 내부를 찾지 않습니다 mtcars. 우리가 사용하지 않은 경우 enclos와 같은 일이 subset(mtcars,cyl == a)전혀 작동하지 않을 것입니다.
joran

왜 서브셋 ()이 더 빠르고 안전한 [,] 메소드를 구현하지 않는지 아는 사람이 있습니까?
Bjorks 최고의 팬

1
@MikePalmice 그렇습니다. 의 마지막 줄은 subset.data.frame입니다 x[r, vars, drop = drop]. 문제는 인용 부호 subsetselect인수에서 유효하게 전달할 수 있는 방법으로 얻는 방법 [.data.frame입니다.
joran

@joran, 감사합니다. dplyr의 필터를 대신 사용할지 어떻게 생각 []하십니까?
Bjorks 1 위 팬

30

또한 [더 빠릅니다.

require(microbenchmark)        
microbenchmark(subset(airquality, Month == 8 & Temp > 90),airquality[airquality$Month == 8 & airquality$Temp > 90,])
    Unit: microseconds
                                                           expr     min       lq   median       uq     max neval
                     subset(airquality, Month == 8 & Temp > 90) 301.994 312.1565 317.3600 349.4170 500.903   100
     airquality[airquality$Month == 8 & airquality$Temp > 90, ] 234.807 239.3125 244.2715 271.7885 340.058   100

36
예, 아니오 나는 당신이보고있는 시차가 두 가지 때문이라고 생각합니다. 1) 작은 (<100 마이크로 초) 오버 헤드 및 2) subset달리 [필터가로 평가되는 행을 제거합니다 NA. 이렇게하면 "공정하게"비교할 때 둘 다 빠르다는 것을 알 수 있습니다.x <- do.call(rbind, rep(list(airquality), 100)); microbenchmark(subset(x, Month == 8 & Temp > 90),{ i <- x$Month == 8 & x$Temp > 90; x[!is.na(i) & i ,] })
flodel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.