R에서 표준 평가와 비표준 평가라는 용어가 사용되는 것을 들어본 적이 있을 것이다. 비표준 평가를 사용하는 대표적인 경우가 subset()이다.
> subset(mtcars,mpg>mean(mpg))
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
이런 비 표준 평가를 사용하면 대상이 되는 데이터 프레임의 이름과 $ 등을 반복적으로 사용해야 하는 불편을 줄일 수 있기 때문에 매우 편리하다. 해들리 위컴의 유명한 패키지인 ggplot2,dplyr 등에서도 이런 비표준 평가 함수들을 많이 볼 수 있다.
이런 함수들은 '비표준' 이라고 부르는 이유는 '표준적인' 방법을 따르지 않기 때문이다. 표준적 방법이란, R이 변수와 그에 대한 값을 찾아가는 일반적 방법인 '렉시컬 스코핑'을 말한다.
R에서 이름(name)과 그 값에 대한 바인딩은 환경(environment)이라는 객체에서 정의되기 때문에 렉시컬 스코핑은 이런 환경들의 체인을 따라서 값을 찾아나가는 방법을 말한다.
비표준 평가에서는 보통 주어진 데이터 프레임이나 리스트에 있는 요소들을 쉽게 사용할 수 있도록, 그 데이터 프레임이나 리스트를 마치 함수의 실행 환경처럼 사용할 수 있게 만든다. 예를 들면 위의 mtcars라는 데이터 프레임에 있는 mpg라는 열은 mtcars라는 환경에서 이미 존재하는 mpg 라는 변수로 보게 만들었기 때문에 굳이 다시 $등을 쓰지 않아도 사용할 수 있다.
이런 비표준 평가는 인터랙티브 환경에서는 타이핑의 양을 줄이기 때문에 매우 편리하다. 그러나 프로그래밍을 할 때는 다르다. 이를테면 사용자가 mtcars 데이터 프레임에서 어떤 숫자형 열을 선택하고 그 열의 평균보다 큰 값만을 서브세팅한다고 하면, 다음과 같이 해서는 원하는 결과를 얻지 못한다.
> subset(mtcars,input$sel>mean(input$sel))
그 이유는 input$sel은 문자열이 될 것이고, 이 문자열은 mtcars 열의 이름들과 아무런 관련이 없기 때문이다. 이런 위험을 피하기 위해서 subset() 함수의 도움말 페이지를 보면 다음과 같은 내용을 확인할 수 있다.
This is a convenience function intended for use interactively. For programming it is better to use the standard subsetting functions like [, and in particular the non-standard evaluation of argument subset can have unanticipated consequences.
도움말에서는 프로그램을 하는 경우에는 [를 쓸 것을 권한다. $가 아닌 이유는 앞 장에서 설명했다. 이렇게 비표준 함수가 있는데, 프로그래밍 환경에서 쓸 수 있게 만든 것을 해들리 위컴은 탈출구 (escape hatch)라고 표현했다. dylyr 패키지에서 사용하는 select_() 함수와 같은 탈출구에 대해서는 패키지 비니에트에 잘 소개되어 있으니 읽어보길 권한다.
http:adv-r.had.co.nz/Computing-on-the-language.html#calling-from-another-function
비니에트를 보면 이런 탈출구 역할을 하는 함수를 사용할 때 quote 라는 방법을 사용한다고 쓰여 있다. 이것은 R 함수의 quote() 에서 온 말이다. 우리말로 '인용하다'라는 뜻인데, '따로 평가하지 않고 그대로 가져온다' 라는 의미를 담고 있다. 다음 예를 보면서 알아보자.
> x <- quote(1+5)
> x
1 + 5
만약 1+5라는 것이 quote() 함수 안에 들어 있지 않았으면 R은 이것을 바로 6으로 평가한다. 평가하지 않고 그대로 가져와서 x라는 변수에 할당한다. 참고로 이것을 평가하여 값으로 변경하고 싶을 때는 eval()이라는 함수를 사용한다.
> eval(x)
[1] 6
비니에트를 보면 dplyr 패키지에서 탈출구 함수를 쓸 때 이런 quote 를 사용해야 한다고 설명한다. 패키지에서는 세 가지 방법을 쓸 수 있다.
1. ~ 사용
2. quote() 사용
3. 문자열 사용
> install.packages("dplyr") #dplyr 패키지를 다운한다.
> library(dplyr) #dplyr 패키지를 부착한다.
> summarise_(mtcars, ~mean(mpg)) # ~ 사용
mean(mpg)
1 20.09062
> summarise_(mtcars, quote(mean(mpg))) #quote()의 사용
mean(mpg)
1 20.09062
> summarise_(mtcars, "mean(mpg)") #문자열 사용
mean(mpg)
1 20.09062
샤이니 앱을 작성할 때는 (필요에 따라 다르긴 하지만) 주로 문자열 방법을 사용하는데, 이때 paste()나 paste0() 함수를 곁들여 쓰는 경우가 많다. 다음은 그러한 예이다.
> library(shiny)
> library(dplyr)
> ui <- fluidPage(
+ selectInput("sel","선택",c("mpg","cyl","am")),
+ verbatimTextOutput("txt")
+ )
> server <- function(input, output, session){
+ output$txt <- renderPrint({
+ summarise_(mtcars,"평군"=paste0("mean(",input$sel,")"))
+ })
+ }
> shinyApp(ui,server)
이제 문제는 샤이니에서 인기 있는 그래프 패키지인 ggplot2 패키지를 사용할 떄도 자주 접하게 된다. 다음 앱은 mtcars 를 사용한 산점도에서 사용자가 color 에스테틱(aesthetic)을 선택하여 플롯팅해 볼 수 있게 하는 것이다. aes() 함수를 시도해보면 원하는 결과를 잘 얻지 못한다. 이런 경우에 aes_string()이라는 탈출구 함수를 사용할 수 있다.
> ui <- fluidPage(
+ selectInput("sel","선택",c("cyl","am")),
+ plotOutput("plot")
+ )
> server <- function(input,output,session){
+ output$plot <- renderPlot({
+ ggplot(mtcars)+
+ geom_point(aes_string("wt","mpg",color = paste0("factor(",input$sel,")")))+
+ labs(color = input$sel)
+ })
+ }
> shinyApp(ui,server)
'전공 > R프로그래밍' 카테고리의 다른 글
R프로그래밍 21. 샤이니에서 유용한 함수들 (0) | 2019.08.16 |
---|---|
R프로그래밍 20. R에서 파일 다루기 (0) | 2019.08.14 |
R프로그래밍 18. 표현식의 사용 (0) | 2019.08.07 |
R프로그래밍 17. 느긋한 평가 조급한 평가 (0) | 2019.08.06 |
R프로그래밍 16.R 환경 (0) | 2019.08.01 |