[r] ‘vapply’가 ‘sapply’보다 안전한 이유는 무엇입니까?
문서에 따르면
vapply
와 유사sapply
하지만 미리 지정된 반환 값 유형이 있으므로 사용하는 것이 더 안전 할 수 있습니다 […].
일반적으로 더 안전한 이유에 대해 설명해 주시겠습니까?
추신 : 나는 답을 알고 있고 이미 피하는 경향이 sapply
있습니다. 여기에 좋은 대답이 있었으면 좋겠어요. 그래서 동료들에게 그것을 가리킬 수 있습니다. 제발 “매뉴얼을 읽어라”라고 대답하지 마십시오.
답변
이미 언급했듯이 vapply
두 가지 작업을 수행합니다.
- 약간의 속도 향상
- 제한된 반환 유형 검사를 제공하여 일관성을 향상시킵니다.
두 번째 요점은 오류가 발생하기 전에 발견하고 더 강력한 코드로 이어지기 때문에 더 큰 이점입니다. 이 반환 값 검사 는 반환 값이 예상 한 것과 일치하는지 확인하기 위해 sapply
followed 를 사용하여 개별적으로 수행 할 수 stopifnot
있지만 vapply
조금 더 쉽습니다 (사용자 지정 오류 검사 코드가 범위 내의 값을 검사 할 수 있기 때문에 더 제한적일 경우 등). ).
다음 vapply
은 결과가 예상대로인지 확인 하는 예입니다 . 이것은 PDF 스크래핑 중에 방금 작업 한 것과 유사 findD
합니다.정규식원시 텍스트 데이터의 패턴을 일치시키기 위해 (예 : split
엔티티 별 목록이 있고 각 엔티티 내의 주소와 일치하는 정규식이 있습니다. 간혹 PDF가 순서가 맞지 않게 변환되어 불량을 일으킨 엔티티).
> input1 <- list( letters[1:5], letters[3:12], letters[c(5,2,4,7,1)] )
> input2 <- list( letters[1:5], letters[3:12], letters[c(2,5,4,7,15,4)] )
> findD <- function(x) x[x=="d"]
> sapply(input1, findD )
[1] "d" "d" "d"
> sapply(input2, findD )
[[1]]
[1] "d"
[[2]]
[1] "d"
[[3]]
[1] "d" "d"
> vapply(input1, findD, "" )
[1] "d" "d" "d"
> vapply(input2, findD, "" )
Error in vapply(input2, findD, "") : values must be length 1,
but FUN(X[[3]]) result is length 2
제가 학생들에게 말했듯이 프로그래머가되는 것은 당신의 사고 방식을 “오류는 성가시다”에서 “오류는 내 친구”로 바꾸는 것입니다.
길이가 0 인 입력
한 가지 관련된 점은 입력 길이가 0이면 sapply
입력 유형에 관계없이 항상 빈 목록을 반환한다는 것입니다. 비교:
sapply(1:5, identity)
## [1] 1 2 3 4 5
sapply(integer(), identity)
## list()
vapply(1:5, identity)
## [1] 1 2 3 4 5
vapply(integer(), identity)
## integer(0)
를 사용하면 vapply
특정 유형의 출력이 보장되므로 길이가 0 인 입력에 대해 추가 검사를 작성할 필요가 없습니다.
벤치 마크
vapply
결과가 예상되는 형식을 이미 알고 있기 때문에 조금 더 빠를 수 있습니다.
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx) # autoplot.microbenchmark is moving to the microbenchmark package in the next release so this should be unnecessary soon
autoplot(m)
답변
과 관련된 추가 키 입력 vapply
은 나중에 혼란스러운 결과를 디버깅하는 시간을 절약 할 수 있습니다. 호출하는 함수가 다른 데이터 유형을 반환 할 수 있다면 vapply
반드시 사용해야합니다.
떠오르는 한 가지 예 sqlQuery
는 RODBC
패키지에 있습니다. 쿼리를 실행하는 동안 오류가 발생하면이 함수는 character
메시지와 함께 벡터를 반환 합니다. 예를 들어, 테이블 이름 벡터를 반복하고 tnames
각 테이블의 숫자 열 ‘NumCol’에서 최대 값을 다음과 같이 선택한다고 가정합니다.
sapply(tnames,
function(tname) sqlQuery(cnxn, paste("SELECT MAX(NumCol) FROM", tname))[[1]])
모든 테이블 이름이 유효하면 numeric
벡터 가 생성됩니다 . 그러나 테이블 이름 중 하나가 데이터베이스에서 변경되고 쿼리가 실패하면 결과가 모드로 강제 변환됩니다 character
. 그러나 vapply
with를 사용하면 FUN.VALUE=numeric(1)
여기에서 오류가 중지되고 줄 아래 어딘가에 표시되는 것을 방지 할 수 있습니다.
답변
당신이 항상 당신의 결과가 특별한 무언가가되기를 원한다면… vapply
이것이 발생하는지 확인하지만 sapply
반드시 그런 것은 아닙니다.
a<-vapply(NULL, is.factor, FUN.VALUE=logical(1))
b<-sapply(NULL, is.factor)
is.logical(a)
is.logical(b)