[TIP] R User Defined Function 관련

Tea_Tasting_Lady
2022-04-04
조회수 224

얼마 전에 끝난 회사 통계분석 프로젝트에서는 

하위군 분석을 위해 작성하는 R script에서 

이전 프로젝트보다 개선된 점들이 

여럿 있었다.  


전체 dataset에 대한 분석과 달리 하위군 분석은 
전체 dataset에서 하위군 분석을 위한 특성별로 
data를 나눠서 분석(가령 성별이면 여자 data, 
남자 data로 나눠서 각각 분석)하게 된다. 


하위군 분석에 적용하는 특성이 여럿이니까 
user defined function을 사용하면 반복작업이 
줄어들어 훨씬 코드가 단순해진다. 


전전 직장에서 Biostat 팀의 팀원으로써 SAS를 

사용해서 통계분석을 했었는데 대학원 때 접했던 

R을 이번 직장에서야 본격적으로 

사용해야할 때 고민이 많았다.


초기에 고민을 했던 것은 SAS Macro 쓰는 

것처럼 R로 분석 code를 어떻게 짜야 

하는 걸까 하는 것이었다. 


SAS Macro와 R에서 User Defined 
Function을 사용하는 용례가 많이 달랐던 걸 
처음에 잘 몰랐어서 엄청 헤맸었다.


R의 UDF(User Defined Function)에서는
i = 1 부터 k까지 작업을 반복한다고
할 때, 돌리고 싶은 k개의  항목을
미리 vector에 넣어놓고 UDF 안에서는 그
vector의 첫번째부터 k번째 항목이
차례로 반영되어 돌아가도록 하는 게 해야하고, 


SAS Macro는 vector의 첫번째 element부터 
k번째 element가 MACRO 안에서 돌아가는
형식이 아니라 항목이름을 k개 정의하면 
그 개별 항목에 대해 Macro 안에서 
function이 돌아가는 형식이었다.


이 차이에 대한 감을 익히는데 초반에 시간이 꽤 걸렸었다.


구체적으로 R에서 user defined function을 
적용해보려고 하다보면 특히 어려웠던 점은


1. 하위군 set을 어떻게 UDF(user defined
function) 내에서 subset 해야 할 지


2. 각 하위군 set마다 다른 값(가령 n수라던지)을 
어떻게 general? 하게 표현해야 할지


3. iteration 이후 전체 분석 결과 table을 
어떻게 하나로 합쳐야 하는 지 였다.


이번 작업에서의 하위군 항목은 우선 

vector subgrp에 아래와 같이 정의되었다. 


subgrp <- c("gendertype", "devicesub", "agesub")


전체 dataset에선 하위군 항목에 대해

gendertype == 1이면 남성, 2이면 여성

devicesub == 1이면 device A, 2이면 device B 

agesub == 1이면 연령대 < 60, 2 이면 연령대 >= 60 인 것으로

미리 정리를 해놓았다.  


1. 하위군 set을 어떻게 UDF(user defined
function) 내에서 subset 해야 할 지 


for_type1_anlaysis <- function(i) {

 RTsub1 <- total[total[,subgrp[i]] == 1,]

... 분석 코드 생략....return(analysis_results)}


RTsub1을 첫 단계에서 미리 정의하면

i  in 1:3에서 

i = 1 에서는

전체 dataset 중 gendertype == 1인 data만이

RTsub1으로 정의되고 이 RTsub1 dataset에 대한

분석이 이루어진다. 

i = 2 에선 devicesub == 1,

i = 3에선 agesub == 1 인 subset에 대한

분석이 진행된다.


2. 각 하위군 set마다 다른 값(가령 n수라던지)을 

어떻게 general? 하게 표현해야 할지


RTsub1$Test <- rep.int(1,length(RTsub1$CaseID))


위에서 정의된 subset RTsub1의 n수만큼 값이 

1인 변수 Test를 새로 생성해야할 때, 이 n수는 각

하위군 set마다 다르다. 

이 경우에 자료 ID의 length가 이 n수와 동일하므로, 

length(RTsub1$CaseID)를 UDF내에서 사용하면 된다. 


3. iteration 이후 전체 분석 결과 table을 

어떻게 하나로 합쳐야 하는 지


for_type1_anlaysis_results  = data.frame()

for (i in 1:3)

{analysis_results  

<- rbind(analysis_results , for_type1_anlaysis (i))}


분석을 위해 작성된 UDF 외에 이 UDF 결과를

합치기 위한 UDF를 하나 더 정의하였다. 

위의 UDF for_type1_analysis 에서 하위군 3종류

("gendertype", "devicesub", "agesub") 의 분석결과가

for_type1_analysis_results를 사용하면 

차례로 합쳐지게 된다. 


영어를 배우고 사용하는 데 공이 많이 들었듯이 
컴퓨터 언어인 R도 능숙하게 사용하려면 결국 
시간과 노력을 더 많이 
들여야겠단 생각도 든다. 


Reference

https://data-flair.training/blogs/r-function/?fbclid=IwAR2xBd8VkQ55k3-4P3cAgpb_oUNQowsI6GJp20bTHMa2tyz1aat3exxDi4I

https://www.datacamp.com/community/tutorials/functions-in-r-a-tutorial


0 0

Data Chef.

datachef00@gmail.com

ⓒ 2020 Data Chef.

Hosting by I'M Datachef

Data Chef.
e-Mail

datachef00@gmail.com


Seoul, Korea  ㅣ  Biz License 000-00-00000  ㅣ Hosting by Datachef.