코드의 반복을 줄이거나 코드의 가독성을 높이려면 함수를 작성해 코드를 추상화해야 한다. 또, 함수를 작성하면 유닛 테스트를 사용해 해당 함수의 동작을 검증할 수 있다는 장점이 있다. 이 절에서는 사용자 정의 함수를 작성하는 방법에 대해서 살펴본다.
기본 정의
함수는 다음과 같은 기본 문법을 사용해 정의한다.
fuction_name<-function(인자,인자,...){ 함수본문 return(반환 값) } |
예를 들어, 다음은 피보나치 함수를 구현한 예다.
>fibo<-function(n){ + if (n==1 || n == 2) { + return(1) + } + return(fibo(n-1)+fibo(n-2)) +} >fibo(1) [1] 1 >fibo(5) [1]5 |
함수를 호출할 때는 인자의 위치를 맞춰서 값을 넘겨주는 방식, 인자의 이름을 지정해서 넘겨주는 방식 두 가지 모두 가능하다. 다음은 이 두 가지 방식을 모두 보여주는 예다.
>f<-function(x,y){ + print(x) + print(y) +} >f(1,2) [1]1 [1]2 >f(y=1,x=2) [1]2 [1]1 |
그 외 함수 호출 방법을 대해 다양한 예를 '2.2 함수 호출 시 인자 지정' 절에서 다룬 바 있으니 해당 내용을 참고하기 바란다.
가변 길이 인자
R에서 함수들의 도움말을 살펴보면 '...'을 인자 목록에 적은 경우를 종종 볼 수 있다. ...은 개수를 알 수 없는 임의의 인자를 표현하는 데 사용하기도 하고, 내부에서 호출하는 다른 함수에 넘겨줄 인자를 푷시하는 데도 사용한다.
다음은 가변 인자로 ... 을 사용한 예다. 함수 f()에서 ...을 인자로 지정한 뒤 이를 하나씩 화면에 출력했다.
>f<-function(...){ + args<-list(...) + for (a in args) { + print(a) + } +} >f('3', '4') [1] "3" [1] "4" |
다음은 함수 g()가 인자 z와 ...을 인자로 받아서 인자 z는 자신이 처리하고 나머지 인자들은 함수 f로 넘겨 처리하는 예다. 코드에서 f()를 호출할 때 마치 명시적인 인자를 넘겨주듯이 ...을 인자로 지정했다.
>f<-function(x,y){ + print(x) + print(y) +} >g<-function(z,...){ + print(z) + f(...) +} >g(1,2,3) [1]1 [1]2 [1]3 |
중첩 함수
함수 안에 또 다른 함수를 정의하여 사용할 수 있다. 이를 중첩 함수(Nested Function)라고 부른다. 다음 코드는 함수 f() 안에 함수 g()를 정의하고, 함수 f() 안에서 이를 호출하여 사용하는 예를 보여준다.
>f<-function(x,y){ + print(x) + g<-function(y){ + pritn(y) + } + g(y) +} >f(1,2) [1]1 [1]2 |
중첩 함수를 사용하면 함수 안에서 반복되는 동작을 한 함수로 만들고 이를 호출하여 코드를 간결하게 표현할 수 있다는 장법이 있다. 또한, 내부 함수가 외부 함수에 정의된 변수를 접근할 수 있어 클로저(closure)로 사용할 수 있다.
>f<-function(x1){ + return(function(x2){ + return(x1+x2) + }) +} >g<-f(1) >g(2) #x1=1, x2=2 [1]3 >g2<-f(2) >g2(2) #x1=2, x2=2 [1]4 |
위 코드에서 함수g()에는 x1=1, 함수 g2()에는 x1=2가 지정되었다. 따라서 g(x2)는 1+x2를, g2(x2)는 2+x2를 계산한다.
R을 이용한 데이터 처리&분석 실무 中
'R > R을 이용한 데이터 처리&분석 실무' 카테고리의 다른 글
파일 입출력 (0) | 2020.01.31 |
---|---|
아이리스 데이터 (0) | 2020.01.31 |
연산 (0) | 2020.01.30 |
흐름 제어(조건문과 반복문) (0) | 2020.01.30 |
타입 판별, 타입변환 (0) | 2020.01.29 |