Data analysis story

[R 프로그래밍- 함수 만들기(사용자 지정 함수 문법, 함수를 부르는 방법, 함수 확인하기, 함수의 결과가 하나 이상일 때, 함수 안의 함수, 함수를 돌려주는 함수, 가변 길이 인자) ]

뚠바뜨 2020. 5. 22. 20:20

안녕하세요, 여러분!

오늘은 R프로그래밍 함수편에 대해서

학습해보겠습니다!

 

함수는 낯선 개념이 아니죠?

우리는 이때까지 R의 내장함수를 참 많이 사용해왔으니까요!

 

그 중 기억에 남는 내장함수가 있나요?

데이터프레임을 만드는 data.frame()이라는 함수, 결과값을 출력하는 print()라는 함수 등등 정말 많은 함수를 배웠죠?

 

이렇게 그동안 남들이 만든 함수를 사용했다면

이번에는 ‘내가 직접 함수를 어떻게 만들 것인가?’에 대해서 알아보는 시간을 가져봅시다!

 

R의 큰 장점 중 하나는 함수를 굉장히 유연하게 정의하고 사용할 수 있다는 점인데요!

그렇다면 대체 함수를 만드는 것이

어떤 장점을 가져다줄 수 있는 걸까요?

 

함수의 작성은 코드의 반복을 줄이거나 코드의 가독성을 높여줍니다.

 

또한 함수를 작성하면 유닛 테스트를 사용해 해당 함수의 동작을 검증할 수 있구요

 

아직은 잘 감이 오지 않아도 함수를 자유자재로 만들어 보게 된다면

이런 장점들을 몸소 체험할 수 있을 거에요!

 

이렇게 프로그램을 함수로 잘 쪼개 놓으면 재사용하기도 좋고 테스트하기도 좋은데요!

이번 시간에는 함수는 어떻게 만들 수 있는 것인지!

‘문법’에 대해 배워보도록 해요!

 

함수의 구조

일단 먼저, 내가 만들고자 하는 함수의 이름을 꼭 정해주어야 합니다.

그리고 어떤 입력이 들어갈지 매개변수를 정의해주고요!

마지막으로 결과로 무엇을 돌려주어야 할지까지 정의해주어야 합니다.

 

그러면 함수를 만드는 문법을 한눈에 살펴봅시다!

계산식 1과 계산식 2는 어떤 명령을 실행하는 함수를 만들지에 해당하는 부분입니다.

함수의 body라고도 하지요!

 

이렇게만 보면 무슨 말인지 감이 오지 않으니 예제를 통해 확인해봅시다!

두 수를 받으면 그 두 수를 곱해주는 func1이라는 함수를 만들어볼게요!

 

위의 예처럼 함수를 만든 후에 함수를 호출해서 사용할 때는

print(함수이름(인수)) 이렇게 입력하면 됩니다!

(print 함수는 꼭 쓰지 않아도 결과가 출력됩니다.)

 

함수 이름 func1, 매개 변수 a,b, 함수의 body 부분, 결과 값 c까지 모두 이해가 되시나요?

 

함수를 부르는 방법

앞서 print(함수이름(인수))로 함수를 불러봤는데요!

R에서 함수를 부르는 방법은 한 가지는 아닙니다. 여러 가지가 있어요!

인수 이름을 사용할 수도 있고, 사용하지 않을 수도 있거든요!!

 

아까 두 수를 곱해주는 함수 func1의 예를 통해서 확인해보죠!

함수를 사용할 때

그냥 숫자만 입력해도 되고

 

아니면 a=, b= 이렇게 인수 이름을 지정해주어도 되고

 

혹은 하나는 숫자만 입력하고 하나는 인수 이름을 지정해주어도 되네요!

 

그런데 이렇게 인수 이름을 사용하는 이유는 무엇일까요?

 

인수가 많은 함수의 경우, 인수의 순서를 꼭 지켜서 써야 하는데

이렇게 인수 이름을 줘버리면 순서를 안지켜도 되기 때문이죠!

무슨말이냐구요?

 

예를 통해 이해해봅시다.

두번째 숫자에 1을 더해서 첫번째 숫자와 곱한 값을 출력해주는 func2라는 함수가 있다고 해봅시다!

이 함수에서는 a와 b 매개변수의 값의 순서가 바뀌면 결과값이 바뀌겠죠?

 

위의 코드와 같이

fun2(2,3)a2b3으로 인식하고

func2(3,2) a3으로 b2로 인식하잖아요!

하지만 이럴 때 인수 이름을 지정해주면

2가 앞에오더라도 b=라고 이름을 붙여주었기 때문에 결과가 같게 되는 것이죠!

 

혹은 우리가 배웠던 read.csv()라는 함수 기억나시나요?

read.csv()에서 괄호 안에 들어가는 인수들은 굉장히 많은데요

이렇게 쳐보면 file, header, sep, quote 등등 인수가 정말 많죠?

이렇게 인수가 많을 때 인수들 중 몇 개만 선택적으로 주고 싶을 때도 있잖아요!

이럴 때 인수 이름을 주면 편리합니다.

예를 들어

이렇게요!!

file은 첫번째에 나오는 인수라는 것을 알고 있기 때문에 값만 넣어주었고

stringsAsFactors는 몇 번째에 나오는지 모르지만 file 인수 다음에 바로 쓰고 싶기 때문에 이렇게 이름을 준 것입니다!

 

인수가 많은 함수의 경우

인수의 이름을 주면 굉장히 편리하네요!!

 

함수 확인하기

 

앞서 만든 함수가 어떤 함수인지 보고 싶을 때는 어떻게 해야할까요?

괄호 없이 그냥 함수 이름만 타이핑하게 되면

어떤 함수인지 이렇게 보여주네요!

 

주의할 점은 함수 안의 변수는 함수 안에서만 인식이 된다는 것인데요!

함수 안의 변수는 함수 바깥에서는 접근할 수 없습니다.

, 지금 위의 c라는 변수는 func2라는 함수 안에서만 인식되는 것이죠!

이에 대해서는 다음 포스팅에서 더 자세히 다루도록 할게요!

 

함수의 결과가 하나일 때, 혹은 그 이상일 때

 

어떤 함수에서 return으로 돌려주는 값이

꼭 하나일때만 존재하는 것은 아닙니다.

두 개 혹은 그 이상일때도 있는데요.

 

하나를 돌려주는 함수를 만드는 법은 배웠는데

두 개 이상일 때는 어떻게 해야할까요?

먼저 결과를 하나만 돌려줄 때를 보겠습니다.

 

표준편차를 평균으로 나눈 하나의 값을 출력해주는 함수를 만들어볼게요!

(na.rm은 결측 값을 제외한다는 의미에요! 나중에 다루겠습니다!!)

 

앞서 배운 함수를 만드는 법과 별다른 차이가 없습니다!

 

그렇다면 값을 여러 개 받을 때는 어떻게 해야 할까요?

return안에 ,를 사용해서 여러 개를 넣으면 안되냐구요?

안됩니다. return 안에는 변수가 하나만 들어갈 수 있기 때문이죠.

 

그러면 어떻게 하죠? 다 방법이 있죠!

리스트나 데이터프레임으로 만들어서 돌려주면 됩니다.

바로 앞의 예에서 평균과 표준편차 두 개를 같이 돌려주는 함수를 만들어볼게요!

결과값이 리스트로 나오는 것을 확인할 수 있죠?

 

함수 안의 함수

 

함수 안에 함수를 만들 수 있을까요?

! 그럴 수 있습니다!

예를 보죠!

처음에 보면 굉장히 어렵기 때문에 차근차근 시간을 가지고 생각해야 하는데요!

제 설명을 천천히 읽어보세요!!

 

square.plus.cube라는 함수를 정의할 때

square.plus.cube라는 함수의 body에 또 두 가지 함수를 실행시키는 것입니다.

 

square라는 함수와 cube라는 함수가 square.plus.cube라는 함수 안에 존재하는 것인데요.

 

square.plus.cube라는 함수와

이 함수 안에서 실행되는 square라는 함수, cube라는 함수는 매개 변수가 다릅니다.

 

위의 예를 보면 square.plus.cube라는 함수의 매개변수는 y,

square라는 함수, cube라는 함수의 매개 변수는 x로 서로 다르죠?

 

위의 예시처럼 square.plus.cube(4)이렇게 타이핑하면

일단 y라는 매개 변수 안에 4가 들어가는 것입니다.

 

그런데 이 함수의 return값은 square(y)+cube(y)이므로

square(4)+cube(4)를 해서 반환하라는 말이 되겠죠.

 

그러면 square.plus.cube 함수 안에 정의된 square() 함수를 봅시다.

 

square 함수의 매개 변수는 x이고 x*x의 값을 return해주네요!

이 경우에는 그러면 y값인 4가 매개변수 x가 되겠네요!

 

그렇다면 square(4)의 결과 값은 4*4가 되겠죠!

똑같이 cube(4)4^3이 되겠죠!

 

따라서 16+64=80이 출력되는 것입니다.

 

좀 어렵죠?

가장 중요한 것은 함수 안의 함수를 정의하기 위해서는

매개 변수를 다르게해야 한다는 것입니다!!

이렇게 함수 안에 함수를 정의하는 것은 꽤 많이 쓰입니다.

 

그리고 square.plus.cube 함수에 안에서 실행하는 square함수와 cube함수는

square.plus.cube 함수 안에서만 실행됩니다!

 

따라서

이렇게 함수 바깥에서 사용한다면 찾을 수 없다고 나오니 유의하세요!!

 

함수를 돌려주는 함수

 

R에서는 함수 안에서 함수를 만들어서 돌려줄 수도 있어요!

위의 make.power라는 함수는 또 하나의 함수를 돌려줍니다.

‘pow라는 함수를 만들어서 돌려주는 것이죠.

make.power함수는 n을 받으면 ‘n제곱을 하는 함수를 만들어주는 함수인데요!

 

cube<-make.power(3)

을 하면 x3제곱을 해주는 cube라는 함수를 만드는 것이죠!

그래서 cube(3) 이렇게 x값을 넣어주면

3의 세제곱인 27을 돌려줍니다

cube(4)를 하면 43제곱인 64를 돌려주겠죠?

 

square<- make.power(2)

을 하면 x에 제곱을 해주는 square라는 함수를 만드는 것이죠! 이렇게 무한정 많은 함수를 만들 수 있겠습니다!

 

가변 길이 인자

이때까지 우리는 함수를 만들 때 매개 변수를 딱 지정해주었습니다.

하지만 꼭 내가 매개 변수의 수를 정하지 않아도 되는데요!

그럴 때는 어떻게 함수를 만들면 될까요?

밑의 예제와 같이 . . .을 사용하면 됩니다!

이렇게 해서 오늘은 R에서 사용자 지정 함수에 관한 것들을 공부해보았는데요

다음 포스팅에서는 함수 안의 변수의 효력 범위에 관해서 다루도록 하겠습니다!