본문 바로가기

Data analysis story

[R프로그래밍-apply 계열 함수(implicit loop과 explicit loop의 차이, apply함수, lapply함수)] 쉽게 이해하기

여러분~! 안녕하세요! 오늘은 apply 계열 함수들에 대해 배워보도록 하겠습니다!!

 

다들 ‘apply’라는 영단어의 뜻을 알고 계신가요?

바로 적용하다라는 의미를 가지고 있죠!

 

apply 계열 함수도 단어 뜻 그대로 적용하는함수라고 이해하면 쉽습니다!

 

그렇다면 ‘무엇’에다가 ‘무엇’을 적용하는 것일까요?

 

결론부터 말하자면 바로 ‘데이터’에다가 ‘함수’를 적용합니다.

‘데이터’에다가 ‘함수’를 적용한다구요?

 

우리는 이때까지 데이터에 r 내장함수, 심지어는 사용자 지정 함수까지

적용해왔었는데요! 뭐가 다른걸까요?

 

바로 apply 계열 함수는 일련의 데이터에다 원하는 함수를 ‘반복적으로!!!’ 적용시켜준다는 점이죠!

 

이제껏 데이터에 함수를 적용했었지만 데이터 하나마다 각각 함수를 적용했었잖아요!

 

"이제는 일련의 데이터에 일괄적으로 원하는 함수를 적용시켜주는

그런 강력한 도구들을 배우는 겁니다!"

엄청 신나네요!!

 

apply 함수 계열에는 apply 함수와 apply와 유사한 이름을 가진 함수들,

예를 들어 sapply, mapply, lapply, tapply 등등이 있습니다.

 

오늘은 이 중 두 가지 apply sapply만을 다뤄보도록 할꺼에요! 준비되셨나요??

 

apply함수부터 본격적으로 다루기 전에 강력한 apply계열 함수의 쓰임을 예를 통해 보도록 합시다!

일단 먼저 저번 시간에 배운 사용자 지정 함수를 통해 입력된 값들 중

가장 큰 값과 가장 작은 값을 빼서 그 결과 값을 리턴해주는 함수를 만들어 봅시다.

이렇게 말이죠!

다들 이 정도의 사용자 지정 함수는 이제 익숙하시죠?

((사용자 지정 함수에 대해 잘 모르겠다면 [R프로그래밍-사용자 지정 함수] 편을 참고해주세요!!)

그러면 이제 저 함수에 입력할 데이터! 매트릭스를 3 3열로 만들어보도록 하죠!

(매트릭스 만드는 법도 다 아시죠?? 잊어버리지 않게 꼭 복습해주세요!)

그러면 앞서 만든 사용자 지정 함수를 이 A라는 매트릭스 입력 값에다가 적용해 볼게요!

매트릭스의 최댓값 9에서 최솟값 1을 뺀 8이라는 결과가 나오겠죠?

그런데 여러분! 제가 매트릭스로 입력 값을 넣은 데에는 이유가 있는데요!

일단 A를 출력해보죠!

우리가 만약 A라는 매트릭스의 1열과 23열에 각각 maxMin이라는 함수를 적용하고 싶을 때에는 어떻게 했었죠?

그야 행렬의 1열을 [ ]연산으로 추출한 후 maxMin 함수의 인수로 넣어주면 됐었죠!

그러므로 1열을 함수에 적용, 2열을 함수에 적용, 3열을 함수에 적용하는 코드를 모두 입력해야 하니 이렇게 세 줄이

필요했었죠!

 

바로 이렇게 말이죠!

행 별로 함수를 적용하고 싶어도 마찬가지였죠!

숫자만 바뀌는 코드가 계속되니까 코드가 너무 지저분하지 않나요?

 

이 함수를 일련의 데이터에 한 번에 적용할 수 있는 방법은 없을까요?

그러면 이 세 줄이 한 줄에 완성될 테니 말이죠!

 

또 그리고 지금은 세 줄이지만 데이터가 많아진다면 수많은 줄을 딱 한 줄로 변신시켜줄 그런 강력한 함수가 없을까요?

 

바로 이 함수가 apply함수와 apply함수의 친구들이라는 겁니다!

이제 차차 apply함수와 apply함수의 친구들을 하나씩 설명할텐데

 

그 전에 먼저 이 maxMin함수를 A라는 매트릭스에

열 별로 또는 행 별로 한 번에 적용하는 코드를 보여드릴게요!

첫번째 코드는 A라는 매트릭스에 행 별로 maxMin이라는 함수를 적용한 것이고요

두번째 코드는 A라는 매트릭스에 열 별로 maxMin이라는 함수를 적용한 것입니다.

따라서

6 6 6의 결과값은

A 매트릭스의 행 별로 maxMin 함수를 적용한 결과이고 (3행이니까 결과 값 3)

2 2 2의 결과값은

A 매트릭스의 행 별로 maxMin 함수를 적용한 결과입니다!

 

결과들은 벡터로 출력이 되네요!

 

아직 잘은 모르겠지만 apply함수의 1이라는 인수는 행을

2라는 인수를 열을 나타내는 것 같은 느낌이 들죠?

 

이렇게 apply함수는 일련의 데이터에 ‘반복적으로’ 함수를 적용할 수 있게 만들어주는 함수입니다!

 

기본적으로 R에서 데이터는 여러 개로 구성이 되어 있잖아요!
그래서 여러 개로 이루어진 데이터를 반복적으로 함수에 적용할 필요가 있을 때가 많습니다.

 

다른 프로그래밍 언어를 같이 배우시는 분들이라면

데이터를 반복적으로 함수에 적용한다!!’는 말을 보면 for 반복문(loop)이 생각날 수 있을 것 같아요!

 

하지만 R에서는 for 반복문(loop) 같은 것을 쓰지 않아도

효율적으로데이터에 반복적으로 함수를 적용할 수 있게 해주는 강력한 도구가 있는데

그것이 바로 apply 함수입니다.

 

따라서 R에서는 for loop를 많이 사용하지 않는답니다.

강력한 apply 함수가 있기 때문이죠.

 

본인이 R에서 프로그램을 짜는데 forwhile과 같은 반복문을 많이 사용한다면

그것은 효율적으로 짜지 못하고 있는 것입니다.

 

forwhile과 같은 키워드를 사용해서 구현한 loop(반복문)explicit loop라고 하고요,

apply 계열 함수로 구현한 loopimplicit loop라고 합니다.

 

따라서 벡터라든가 리스트의 모든 구성요소에 특정 함수를 적용하고 싶을 때

for loop를 돌릴 필요가 전혀 없는 것이죠.

 

엑셀에서 마우스를 이용해 드래그 하여 똑 같은 함수를 여러 데이터에 적용시키는 것을 다들 아시죠?

그 드래그의 기능이 R에서는 apply 계열 함수라고 보면 되겠습니다!

 

하지만 apply 함수는 엑셀처럼 딱 깔끔하게 떨어지지는 않는데요!

 

입력 받는 데이터 타입에 따라서 사용해야 하는 함수가 달라질 수가 있기 때문이죠.

 

그래서 sapply, mapply, lapply, tapply 등등 apply 함수의 친구들이 다양하게 존재합니다.

 

apply 계열 함수는 쉬울 뿐만 아니라 빠르게 처리되기 때문에

R에서 데이터를 가지고 반복적으로 함수를 적용할 때는

가능한 apply 계열 함수를 쓰는 것이 좋습니다.

 

그러면 하나씩 보도록 합시다!

이번 포스팅에서 다루지 못한 apply 함수 친구들은 다음 포스팅에서 다룰게요!

 

① apply

apply 함수는 기본적으로 matrix나 array와 같은 데이터에 적용합니다.

왜냐하면 apply 함수에는 인수로 margin을 주어야 하는데

margin은 행이냐, 열이냐와 같은 조건을 주는 것입니다.

 

그래서 행과 열로 이루어진 데이터에 이 apply 함수를 적용하는 것입니다.

 

apply(data,margin(1 또는 2),function)

 

이렇게 apply 함수를 사용합니다.

margin 인수로는 1 또는 2를 사용하는데

1은 행, 2는 열을 의미합니다.

 

따라서 행이나 열의 합계, 평균 등을 일괄적으로 구할 수가 있는 것이죠!


apply
함수는 결과 값을 벡터로 돌려주는 것! 앞서 보았죠??

또 확인해봅시다!

한 번 사용해 보도록 하죠!

이렇게 열 별로 평균을 적용할 수도

행 별로 합을 적용할 수도 있네요!

 

apply 함수를 몰랐다면 20줄의 코드를

단 두 줄로 줄일 수 있게 되었네요!

결과를 볼까요?

결과 값을 벡터로 돌려주네요!

 

② lapply

아까는 매트릭스나 어레이에 적용하는 apply함수였다면

리스트에 함수를 적용할 때 바로 lapply를 사용합니다.

 

lapply를 사용하면 리스트 형의 데이터를 받아

key, value 쌍인 리스트 형태로 결과를 반환합니다.

 

lapply (data, function)

이렇게 사용하면 됩니다! 그러면 사용해봅시다!

x라는 리스트를 만들고

lapply함수를 적용해 평균을 리스트에 일괄 적용한다면

어떤 결과가 나올까요?

 

결과 값 또한 리스트로 돌려주네요!

 

그런데 리스트로 결과를 돌려주기 때문에

결과 값을 하나씩 가져와 쓰기는 조금 불편하기는 합니다!

 

결과 값을 하나씩 가져오려면

변수에 결과를 저장하고 $ 연산을 사용해서 하나씩 불러오면 되겠죠.

이렇게요!

그런데 데이터 프레임의 각 열도 리스트로 구성되어 있다는 점, 기억나시나요?

우리 이런 식으로 데이터 프레임을 직접 생성해 보았잖아요!

결과는 이렇게 나왔었죠!

 

test라는 데이터프레임에서 a, b, c 열이 모두 리스트로 구성되어 있기 때문에

이런 데이터프레임 데이터도 lapply 함수에 적용할 수가 있답니다!

 

만약에 그냥 mean(test)라고 써버리면

에러가 납니다.

 

mean에는 벡터가 적용되어야 하는데 test key value의 값으로 이루어져 있기 때문이죠.

 

바로 이 때 lapply를 쓰는 것이죠!

따라서 lapply 함수를 써서 각 열들의 평균 값을 구해보도록 합시다!

 

각 열 별로 mean함수가 적용되었고 리스트 형태로 값을 반환하네요!

 

오늘은 이렇게 해서 apply함수와 apply 계열 함수 중 lapply에 대해서 공부해봤습니다!

apply 계열 함수는 일단 일반적으로 일련의 데이터에 원하는 함수를 일괄 적용하고 싶을 때

사용하는 함수였죠!

이는 implicit loop라고도 하며 쉽고 빠른 처리가 가능한 강력한 도구였습니다!

 

apply 함수 하나만 있지 않고 apply 계열 함수들이 여러 개 존재하는 이유는

데이터 타입에 따라 apply를 적용할 수도 있고 lapply를 적용해야 할 수도 있고

또 다음 시간에 배울 sapply를 적용해야 할 수도 있기 때문이었죠!

 

매트릭스와 같이 행과 열이 존재할 때 썼던 함수인 apply

리스트로 입력 값을 넣어서 리스트로 결과를 반환해주는 lapply

 

두 가지 모두 열심히 공부한 후에

다음 포스팅에서는 sapply, mapply, tapply에 대해서도 배워보도록 합시다!!!