티스토리 뷰

반응형



magrittr 패키지 

  • tidyverse 패키지를 사용해 데이터를 정제하다보면 자연스레 %>% 연산자를 자주 사용하게 됩니다. 그리고 %>% 연산자는 따로 import 하지 않고 사용하기 때문에 그냥 dplyr 에 포함되어 있는 연산자인가보다 라고 생각하지만 사실 magrittr 이라는 패키지에 속해있는 연산자 입니다.

  • 파이프 연산자의 역사를 보다 자세히 알고 싶으신 분은 이 url 을 통해 더 공부하셔도 좋을 것 같습니다. %^^% 

  • https://www.datacamp.com/community/tutorials/pipe-r-tutorial

  • tidyverse 홈페이지에서 magrittr 관련 페이지에 접속하면 이 패키지에 대한 간단한 설명을 확인할 수 있습니다. 더 자세한 사항들은 Vignette 를 통해 알 수 있습니다.

  • https://cran.r-project.org/web/packages/magrittr/magrittr.pdf

  • 한 마디로 정의하면 magrittr 패키지는 코드의 가독성을 높이는 연산자들을 모아놓은 패키지 라고 할 수 있습니다. 그 중 자주 사용하는 3가지 연산자를 살펴볼 예정입니다.


%>% 연산자 사용법 

  • %>% 연산자는 tidyverse 패키지를 attach 하거나 magrittr 패키지를 직접 attach 하는 방법을 통해 사용할 수 있습니다.


  • 코드를 작성하다보면 위의 경우와 같이 계산한 결과값이 다른 함수의 argument 로 사용되는 경우가 빈번합니다. 그림을 살펴보면 x 값이 f 라는 함수의 인수로 사용되어 f( x ) 라는 결과값을 만들어내는데 그 f( x ) 가 g 함수의 인수로 다시 사용되고 그 결과값인 g( f( x ) ) 가 h 함수의 인수로 다시 사용되어 결과값 y 를 만들어 내는 것을 확인할 수 있습니다.

  • 이런 경우에 괄호의 중첩이 발생하는데 2~3회 까지는 큰 문제 없을 수 있으나 각 함수의 인수가 많아지고 괄호의 중첩 단계가 높아지면 코드를 작성하는 입장에서도 코드를 읽는 입장에서도 매우 혼란스러운 상황이 발생하곤 합니다.

  • 이런 상황을 개선하기 위해 나온 연산자가 %>% 연산자 입니다.

  • 위의 식 y = h( g( f( x ) ) ) 를 %>% 연산자를 사용하여 다시 표현하면 다음과 같이 표현이 가능합니다.

y = x %>% f( . ) %>% g( . ) %>% h( . )

  • 예시를 통해 더 자세히 살펴볼까요

  • runif 라는 함수를 사용하는 예시 입니다. runif 라는 함수는 난수를 발생시키는 함수로 인자로는 n (난수 발생 개수), min (난수의 최소값), max (난수의 최대값) 총 3개가 있습니다. 

  • random_number_count 라는 변수를 지정하고 random_numbers 를 만들어볼까요. 위의 3가지 방법은 모두 같은 결과값을 리턴합니다.

  • 1번 방법은 %>% 를 사용하지 않고 n 에 직접 random_number_count 를 대입하여 실행하는 방법입니다.

  • 2번 방법은 %>% 를 사용하여 n 자리에 . 을 사용하는 것을 확인할 수 있습니다.

  • 3번 방법은 %>% 를 사용하면서 n 값 자체를 명시하지 않는 방법입니다. 일반적으로 %>% 를 사용할 때는 이 방법을 이용합니다. . 을 작성하지 않는 것은 %>% 이전의 값이 다음 함수의 인자들 중 가장 앞에 있는 것에 해당한다는 의미입니다. 

  • 다음 예제를 통해서 더 . 에 대해 살펴볼까요

  • 위의 예시와 동일하지만 이번엔 min_value 를 통한 연산들 입니다.

  • 3번 예시를 보면 위의 예시와는 달리 . 을 중간에 사용한 것을 확인할 수 있습니다. 만약 위의 경우처럼 

min_value %>% runif( 10, 10 )

  • 이라고 작성한다면 runif 는 n 이 1 이고 min 이 10, max 가 10 이라고 판단할 것 입니다.



Why Pipe? 

  • 일단 %>% 연산자에 기능에 대해서는 알았지만 과연 이게 그렇게 필요한 것인가? 라는 의문이 생길 수 있습니다. 

  • pipe 연산자의 효용성을 알아보기 위해서 준비했습니다. 우리가 항상 사용하는 iris 라는 데이터를 이용할 예정입니다.

  • iris 중 Sepal.Length 가 5 이상인 데이터의 종류별 개수를 구하시오.




  • 파이프가 없는 경우 이렇게 중간중간 변수에 지정하면서 진행하신 분이 있을 수 있습니다. 이 방법은 3개의 추가 변수를 생성하게 되고 메모리 또한 추가로 소모하게 되는 방법입니다. 

  • 이렇게 작성했을 때 효용도 있지만 매 step 을 변수화 하는 것은 좋은 방법이라고 생각되진 않습니다.


  • 두번째 방법은 함수 안에 함수 안에 함수 안에 넣는 방법입니다. 이 예제야 그나마 간단하지만 만약 parameter 가 매우 많고 복잡한 상황이라면 가독성이 매우 떨어지겠죠.


  • 하지만 pipe 를 사용한다면 이렇게 작성이 가능합니다. 위에서 magrittr 의 효용중 연산의 흐름을 좌에서 우로 변경해준다는 것이 있었는데 바로 이를 뜻하는 것입니다.

  • %>% 사용시 글을 읽듯이 좌에서 우로 읽어나갈 수 있습니다.



  • 둘을 비교해보면 차이가 더 확실해지죠. 연산의 흐름대로 읽어나갈 수 있어 %>% 연산자 사용시 가독성이 훨씬 높아졌다는 것을 느낄 수 있을 겁니다.


  • mutate 라는 단계를 추가했습니다. 이 과정에서 실질적으로는 아무 의미 없지만 예시를 위해 추가하는 함수 입니다.

  • 또 하나의 장점으로 꼽히는 중간 단계에서 연산을 추가하는 부분입니다. 만약 함수 내에 함수를 넣는 방법으로 코드를 작성했을 때 새로운 연산을 추가한다면 일단 어떤 괄호 안에 넣어야할지 부터 찾아야겠죠. 

  • 실제로 긴 코드를 작성하다보면 괄호의 개수나 괄호의 위치 때문에 스크립트가 잘못 작동하는 경우가 수도 없이 많습니다. 하지만 %>% 를 사용한다면 어떨까요?



  • 읽다가 필요한 부분에 한 줄만 추가해주면 됩니다. 코드가 크게 오류날 부분도 없고 추가를 위해 전체 코드를 다시 읽을 필요성도 없습니다.

  • 하지만 모든 코드를 %>% 연산자를 통해 작성하는 것 또한 올바른 방법은 아닙니다. 언제 사용하지 않는 것이 좋은지에 대해서는 https://r4ds.had.co.nz/pipes.html 을 참고했습니다.

  • 한 연산에서 파이프가 10회 이상 나오는 경우는 끊어서 가주는 것이 좋다고 합니다. 하지만 이것은 사실 %>% 를 사용하지 않는 경우에도 동일하게 적용됩니다. 중간중간 임시변수를 만들어 가면서 작성하는 것이 코드 이해나 디버깅 측면에서 훨씬 도움되는 경우가 많습니다.

  • Pipe 연산자의 특징은 좌에서 우로 연산을 진행한다는 점입니다. 이는 다시 말해 선형적이지 않은 작업에 대해서는 적용하기 어려운 부분이 있을 수 있다는 것을 의미합니다. 예를 들어 1번 테이블과 2번 테이블을 각각 전처리한 뒤 합쳐서 새로운 연산을 진행하는 작업같은 경우는 %>% 를 통해 한번에 기술하는 것이 좋지 않다는 것입니다. 이런 경우에는 1번 테이블을 전처리, 2번을 전처리 한 뒤 합쳐주는 3개의 과정으로 나누어서 진행하는 것이 좋다는 말입니다.



Tee 파이프 %T>% 



  • Tee 파이프는 연산의 결과물을 출력하고 싶은 동시에 리턴 받고자 할 때 사용하는 파이프 입니다.

  • 예시를 보면 setosa 에 필터링된 iris 를 저장하고 싶으면서 View 하고 싶은 상황인데 이 코드로는 리턴은 안되고 View 만 실행되는 것을 확인하실 수 있습니다.

  • 이 때 %T>% 연산자를 사용하면 동시에 2가지 기능을 모두 실현할 수 있습니다.

setosa <- iris %>% filter(Species == 'setosa')
setosa %>% View()

  • 이 두 줄을 하나로 줄여주는 역할을 한다고 생각할 수 있겠네요.



병합 파이프 %<>% 


  • 저는 처음 R 을 사용할 때 1 번 방법처럼 작성하는 것이 너무 귀찮았습니다. 변수를 연산한 뒤 다시 그 변수에게 할당하는 과정이 많은데 매번 저렇게 작성하는 것이 좋을 때도 있었지만 귀찮았습니다.

  • 병합 파이프의 존재를 안 뒤로는 2 번 방법처럼 작성하는 것을 기본으로 했었습니다만 코드 관리 및 공유할 때 불편한점이 생기곤 해서 자주 사용하지는 않고 있습니다.



  • 추가로 %$% 라는 연산자가 있습니다만 이 연산자를 사용해서 줄이는 것보다 풀어서 작성하는 것이 가독성이 오히려 좋아지는 것 같아 사용하지 않고 있습니다. vignette 에 쉽게 설명되어 있으니 기회 되면 확인해보셔도 좋을 것 같습니다.








부족한 블로그에 방문해 주셔서 감사합니다.

잘못된 부분이나 질문이 있으시면 

댓글로 말씀해주세요.


금방 확인하고 피드백 드리겠습니다.


좋은 하루 되세요. ^^






반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함