R$ pipe (%>%) 없이 pipe (->.;)를 써보자: Bizzaro pipe
by Youngjun Na
*본 포스팅은 Win-Vector Blog의 글, magrittr’s Doppelgänger를 참고하여 작성하였습니다.
magrittr 패키지의 파이프(%>%) 연산자
dplyr
패키지(정확히는magrittr
패키지)에서는 파이프 연산자(%>%
)를 제공합니다. R studio를 사용한다면 shift+ctrl+M 단축키로 쉽게 이용할 수 있습니다. 제 경우 파이프 연산자는 R 프로그래밍을 할 때 수많은 괄호로 쌓여진 소스를 컴퓨터가 아닌 인간의 입장에서 보기 편하게 만드는 Syntactic sugar의 역할을 해주기 때문에 편하게 사용하고 있습니다.모든 R에서 tidyverse를 로딩하게 만드려는 Hadley Wickham의 빅픽쳐.
예를 들어
sqrt(tan(cos(sin(7))))
## [1] 1.006459
요런 코드를
library("magrittr")
7 %>% sin() %>% cos() %>% tan() %>% sqrt()
## [1] 1.006459
요렇게 표현할 수 있습니다. 아마도 magrittr
패키지의 pipe
는 Rene Magritte의 작품 <이미지의 배반>에 적힌 “Ceci n’est pas un pipe(이것은 파이프가 아니다)”를 패러디(?)한 것 같습니다.
<이미지의 배반, 르네 마그리트>
파이프 연산자에 대한 자세한 설명은 이미 많은분들이 작성해 놓았으니 아래부터는 magrittr
패키지 로딩 없이 pipe
연산자를 사용하는 방법에 대한 이야기를 해보겠습니다. 바로 Bizzaro pipe (->.;
)를 이용하는 것입니다(Bizzaro는 슈퍼맨의 복제 빌런 이름입니다).
Bizzaro pipe (->.;)
7 ->.; sin(.) ->.; cos(.) ->.; tan(.) ->.; sqrt(.)
## [1] 1.006459
간단하게 이야기 하자면 7
을 .
으로 정의한 이후(;
), sin
함수 안에 .
을 넣는 과정이라고 생각하면 될 것 같습니다. 사실 .
을 사용하지 않고 아래와 같이 해도 문제 없습니다.
7 ->a; sin(a) ->a; cos(a) ->a; tan(a) ->a; sqrt(a)
## [1] 1.006459
Bizzaro pipe를 이용한 속도개선
굳이 Bizzaro pipe의 장점을 이야기 하자면 아주미미한속도개선이라 할 수 있겠습니다. 먼저 함수를 상황에 따라 네가지로 정의하고 비교해 보겠습니다.
fbasic <- function(d) {
sqrt(tan(cos(sin(d))))
}
fmagrittr <- function(d) {
(d %>% sin() %>% cos() %>% tan() %>% sqrt())
}
fmagrittrdot <- function(d) {
d %>% sin(.) %>% cos(.) %>% tan(.) %>% sqrt(.)
}
fsemicolon <- function(d) {
d ->.; sin(.) ->.; cos(.) ->.; tan(.) ->.; sqrt(.)
}
앞서 system.time()
함수를 사용해 속도를 비교해 봤지만 모든 결과가 0으로 나왔습니다. 더 작은 단위를 비교하기 위해 microbenchmark
패키지를 이용해 보겠습니다.
library(microbenchmark)
set.seed(160415) #Birthday of my son :)
bm <- microbenchmark(
fbasic(7),
fmagrittr(7),
fmagrittrdot(7),
fsemicolon(7),
control=list(warmup=100L,
order='random'),
times=10000L
)
print(bm)
## Unit: nanoseconds
## expr min lq mean median uq max neval cld
## fbasic(7) 0 321 1598.471 641 962 4615465 10000 a
## fmagrittr(7) 146578 162295 222494.085 171276 200463 51596344 10000 c
## fmagrittrdot(7) 135673 149144 199278.335 157484 184747 16283707 10000 b
## fsemicolon(7) 0 641 1764.496 642 962 3268673 10000 a
산술평균적으로 보았을 때 기존 파이프 연산자에 비해 Bizzaro 파이프가 181,058 나노초(0.000181058초) 빠릅니다. 시각화를 시키면 다음과 같습니다.
library(ggplot2)
highcut <- quantile(bm$time,probs=0.95)
ggplot(data=as.data.frame(bm),aes(x=time,color=expr)) +
geom_density(adjust=0.3) +
facet_wrap(~expr,ncol=1,scales = 'free_y') +
scale_x_continuous(limits = c(min(bm$time),highcut))
Subscribe via RSS