특정 코드블록을 반복적으로 써야할 때 함수를 작성하면 코드의 반복을 줄일 수 있고, 코드의 가독성도 높일 수 있다.
함수를 실행하기 위해서는 반드시 호출을 해야한다. 호출하는 방법은 함수이름 뒤에 소괄호( )를 붙이는 것이다. 이를 함수호출(function call)이라고 한다.
◎ 함수정의
함수명 = function( 인자1, 인자2, ... ) { 실행문 return( 반환값 ) } |
- 인자가 없는 함수
> pi_1 = function() {
+ cat(3.141592653589793)
+ }
> pi_1()
3.141593
> x = pi_1()
3.141593
> x
NULL
인자가 없이 pi값을 출력하는 함수이다. return은 생략할 수 있지만 pi값을 x 객체로 받으려해도 x 객체에는 NULL 값이 저장되어버린다.
> pi_2 = function() {
+ return(3.141592653589793)
+ }
> pi_2()
[1] 3.141593
> x = pi_2()
> x
[1] 3.141593
return을 사용해주면 pi값을 x 객체로 받을 수 있게 된다.
- 인자가 있는 함수
> state = function(fname, data) {
+ switch(fname,
+ SUM = sum(data),
+ AVG = mean(data),
+ VAR = var(data),
+ SD = sd(data))
+ }
> state('SUM', 1:10)
[1] 55
swith() 함수를 사용해서 함수이름과 데이터를 인자로 받는 함수를 만들었다.
※ swith() 함수 더 알아보기
> state
function(fname, data) {
switch(fname,
SUM = sum(data),
AVG = mean(data),
VAR = var(data),
SD = sd(data))
}
> body(state)
{
switch(fname, SUM = sum(data), AVG = mean(data), VAR = var(data),
SD = sd(data))
}
어떤 함수의 몸체를 알고 싶다면 body(함수이름) or 함수이름을 입력한다.
- 리턴이 있는 함수
> calc = function(x, y) {
+ add = x + y; cat(x, '+', y, '=', add, '\n')
+ sub = x - y; cat(x, '-', y, '=', sub, '\n')
+ mul = x * y; cat(x, '*', y, '=', mul, '\n')
+ div = x / y; cat(x, '/', y, '=', div, '\n')
+
+ calc_df = data.frame(add, sub, mul, div, row.names='값')
+ return(calc_df)
+ }
> df = calc(100, 20)
100 + 20 = 120
100 - 20 = 80
100 * 20 = 2000
100 / 20 = 5
> df
add sub mul div
값 120 80 2000 5
return은 지정한 값을 외부로 반환하는 역할을 한다. 하지만 return(add, sub, mul, div) 같은 두 개 이상의 다중인자는 반환할 수 없고 error가 발생한다.
◎ 함수인자
- 위치 인자
> f1 = function(x, y, z) {
+ print(x)
+ print(y)
+ print(z)
+ }
> f1(1, 2, 3)
[1] 1
[1] 2
[1] 3
인자가 2개 이상이면 값은 인자의 위치에 따라 순서대로 할당된다.
- 이름 인자
> f1(z=1, x=2, y=3)
[1] 2
[1] 3
[1] 1
> f1(z=1, 2, 3)
[1] 2
[1] 3
[1] 1
> f1(1, z=2, x=3)
[1] 3
[1] 1
[1] 2
호출할 때 인자의 이름을 지정하면 순서에 상관없이 값을 할당할 수 있다.
인자의 위치와 이름에 의한 값할당을 혼용해서 사용할 수도 있다. 인자의 이름을 지정한 값이 먼저 할당되고 다음으로 이름이 지정되지 않은 값들이 순서대로 할당된다.
- 기본값 인자
> f2 = function(x, y, z=3) {
+ print(x)
+ print(y)
+ print(z)
+ }
> f2(1, 2)
[1] 1
[1] 2
[1] 3
함수를 정의할 떄 인자의 기본값(Default Value)을 지정할 수 있다. 인자이름에 등호를 사용하여 기본값을 지정한다.
세번째 인자 z에 3을 기본값으로 주었고, 함수를 호출할 때 두 개의 값만 입력한다면 z 인자는 기본값이 할당된다.
- 가변길이 인자
> f3 = function(...) {
+ cat(...)
+ }
> f3(1:10)
1 2 3 4 5 6 7 8 9 10
> f3('kim', 150, TRUE)
kim 150 TRUE
"..." 인자는 인자의 개수가 정해지지 않거나, 함수 안에서 다른 함수를 호출할 때 필요한 인자를 명시할 용도로 사용한다.
아래 예시는 이전에 정의한 f1 함수를 f4 함수 안에서 호출하여 정의하는 것이다.
> f4 = function(r, ...) {
+ cat('r =', r, '\n')
+ f1(...)
+ }
> f4(1, 2, 3, 4)
r = 1
[1] 2
[1] 3
[1] 4
◎ 함수안에 함수
- 재귀함수
> fact = function(n) {
+ if(n == 0) return(1)
+ return(n * fact(n-1))
+ }
> fact(5)
[1] 120
> 5 * 4 * 3 * 2 * 1
[1] 120
재귀함수(Recursive Function)는 함수안에서 자기자신을 호출하는 함수이다.
재귀함수에서 가장 많이 쓰이는 예시로 팩토리얼(Factorial)을 계산하는 함수를 작성하였다.
- 중첩함수
> func = function(x, y) {
+ print(x)
+
+ func_re = function(y) {
+ print(y^2)
+ }
+ func_re(y)
+ }
> func(10, 2)
[1] 10
[1] 4
새로운 함수를 정의할 때 함수안에서 또 다른 함수를 정의하여 사용할 수 있다.
외부함수 func에 인자를 두 개 전달하면 두번째 인자가 내부함수 func_re에 전달되어 코드를 실행한다.
> func2 = function(x) {
+ return(function(y) print(x + y))
+ }
> a = func2(1)
> a(2)
[1] 3
> class(a)
[1] "function"
>
> b = func2(2)
> b(2)
[1] 4
중첩함수의 또다른 예시로 return 안에 함수를 정의하고, func2 함수의 리턴값을 a 객체로 받게되면 a는 y 인자를 받을 수 있는 함수가 된다. class() 함수로 자료구조를 확인해보면 ''function" 이 출력되는 것을 알 수 있다.
<R 함수 Function - 함수정의/함수인자/재귀중첩함수>
'R > Data Operation' 카테고리의 다른 글
R apply 계열 함수/replicate/sweep/aggregate (0) | 2020.11.16 |
---|---|
R 벡터 Vector 관련 내장함수 (0) | 2020.11.10 |
R 산술/관계/비교/논리연산자와 벡터연산 (0) | 2020.11.05 |
R 반복문 - for/while/repeat/break와 next (0) | 2020.11.03 |
R 조건문 - if/ifelse/switch/which (0) | 2020.10.27 |
댓글