기초

setwd('c:/users/is2js/R_da/')
#### 사용자 정의 함수(user defined function) ####
# - 사용자 정의 함수를 모은 것이 패키지
# - apply() 관련함수와 같이 사용시 연산 소요시간 단축

#### 사용자 정의 함수 기본 ####
aaa = function(x){} # 함수명 = function(변수){} --> env창에 올라간다
aaa() # 사용은 함수명()으로 사용
aaa   # ()파라미터 입력을 안열어주면, 사용자 정의함수 자체가 나옴
aaa(x=123) # {}안에 함수가 없기 때문에, NULL값이 나옴

# 예제 01 - 입력값을 받지 않은 함수 - (x)가 없이 ()만
bbb = function(){
   print("Hi!")
}
bbb()
bbb(123) # 만약 인자를 억지로 넣어주면, 에러가 난다.


# 예제 02 - 입력값을 그대로 출력
# function(x){ print(x) } 처럼 {}안에서 x가 사용되는 순간, 함수 호출시에 반드시 파라미터가 포함되어야한다.
ccc = function(echo){
   print(echo)
}
ccc
ccc()
ccc(echo = "asdf")


# 예제 03 - 단순계산
ddd = function(x){
   x + 5
}
ddd( x = 10)
ddd( x ="계산인데 문자열을?" ) # 에러나옴
# **** 숫자를 문자열로 가지는 것까지 계산되게 할려면
ddd_upgrade = function(x){
  as.numeric(x) + 5
}
ddd_upgrade(x = "25")


# 예제 04 - 파라미터에 기본값을 지정해주기
# - ()안에 아무값이 없어도 기본값으로 작동함. 새로운 값이 들어가면 새로운 값으로
eee = function(x = 5){
   x^2
}
eee() # 기본값이 계산됨
eee(2)


# 예제 05 - 2가지 파라미터 넣어주기.
fff = function(aa, bb){
   aa*bb
}
fff(aa = 1, bb = 3)


# 예제 06 - {}안에 여러개 함수 호출하기
ggg = function(aa, bb){
   print(paste0("aa = ", aa)) # paste0를 이용하여, print문에 설명도 넣어주기
   print(paste0("bb = ", bb))
   print(paste0("aa * bb = ", aa*bb))
}
ggg(aa = 1, bb= 2)


응용

setwd('c:/users/is2js/R_da/')
#### udf 응용 ####
#### 캡슐화 ####
# - 코드를 묶어주는 것 -> source()를 활용한다.


#### 1. 할당연산자를 활용한 udf ####

# - 할당연산자(<<-)를 이용하여 전역변수도 생성한다
# - return을 이용하여 값을 반환한다(print에서 벗어나...)
# 예제 1
# 1) 들어온 x를 3번 반복한다음, 각각을 "-"로 연결한 뒤, global_object에 넣어준다.
# 2) 들어온 x를 nchar()를 이용해 문자열 개수를 return하자.

udf = function(x){
   # paste()에서 collapse = 로 이어준다. <-> 구분자는 sep =
   global_object <<- paste(rep(x, 3), collapse = "-" ) # 할당연산자 = 를 사용하면 전역변수가 인식이 안된다..
   return(nchar(x))
}
udf("a")
global_object

udf("asdfasfda")
global_object # 하지만, 기존에 사용하던 변수를 덮어쓸 수 있으므로, 전역변수+할당연산자를 쓰는 것은 위험할 수 있다.


# 사용자 정의 함수 안에서, 여러 개의 자료형태를 반환해주고 싶을 때 list()를 사용하면 된다.
udf2 = function(x){
   aa = paste(rep(x, 3), collapse = "-")
   bb = nchar(x)
   cc = rep(x, 3)
   print(aa)
   print(bb)
   print(cc)
}
udf2("asdf") # 이런식이면, print는 3개가 될지라도, 변수에 할당시 마지막 값만 대입된다.
f = udf2("asdf")
f # 마지막 cc만 대입이 되어버린다. 묶여있는 구조가 아니라서..

# 여러 자료를 return시 list()를 이용하면 된다.
udf3 = function(x){
   aa = paste(rep(x, 3), collapse = "-")
   bb = nchar(x)
   cc = rep(x, 3)
   return(list(aa, bb, cc))
}
l = udf3("asdf")
l
l[[1]]
l[[3]]


#### 2. apply( FUN = "udf")함수를 활용한 udf ####
# 예제1) apply()없이.. udf로 들어온 x를 문자열로 바꾸고, 문자열 갯수를 반환하여 칼럼 생성
udf_noapply = function(x){
   return(nchar(as.character(x)))
}
data("iris")

iris[,"n_char"] = udf_noapply(iris$Species)
head(iris)

# 하지만, 여기서 문자열개수를 +1 정도 추가하려면 또 함수를 적어야한다
iris[,"n_char"] = udf_noapply(iris$Species) + 1
head(iris)
# 이때는, 사용자 정의 함수의 마지막 return 에 + 1 해주는 식으로 실수를 줄이자.

# 예제2)
# 1) 먼저 데이터를 df로 만든 다음(apply()에는 df를 넣더라)

df = head(iris)
# 2) 숫자정보만 빼낸 다음, 세로방향2으로 적용시키면
# FUN = 인자에 "사용자 정의함수" 를 적용시키면, df전체에 문자열 갯수가 반환되서 대입된다.
apply(X = df[1:4], MARGIN = 2, FUN = "udf_noapply" )

+ Recent posts