챕터 8 손없는 날 판별하기 (함수)
손없는 날(損-)에서의 손은 사람의 활동을 방해하고 사람에게 해코지 한다는 악귀 또는 악신을 뜻하며, 나쁜 귀신이 돌아다니지 않아 인간에게 해를 끼치치 않는 길한 날을 의미한다. 음력 날짜로는 9와 0[1]으로 끝나는 날이며, 8개의 모든 방향으로 귀신이 활동하지 않는 길일이다. 따라서 이날에 수리, 이사, 혼례, 개업 등을 하면 상서롭다고 믿으며 주요행사의 날짜를 정하는 기준이 된다. datatoys
의 Kcalendar
데이터셋에서는 한국천문연구원에서 제공하는 날짜와 관련된 다양한 데이터를 제공한다. 이 중 날짜 별 손없는 날을 제공하는데, 손없는 날을 찾는 간단한 함수를 한번 만들어보자. 먼저 데이터는 아래와 같다.
## tibble [241,027 × 11] (S3: tbl_df/tbl/data.frame)
## $ 양력날짜 : Date[1:241027], format: "1391-02-05" "1391-02-06" "1391-02-07" "1391-02-08" ...
## $ 음력날짜 : Date[1:241027], format: "1391-01-01" "1391-01-02" "1391-01-03" "1391-01-04" ...
## $ 음력간지년한글: chr [1:241027] "신미" "신미" "신미" "신미" ...
## $ 음력간지월한글: chr [1:241027] "경인" "경인" "경인" "경인" ...
## $ 음력간지일한글: chr [1:241027] "기축" "경인" "신묘" "임진" ...
## $ 음력간지년한자: chr [1:241027] "辛未" "辛未" "辛未" "辛未" ...
## $ 음력간지월한자: chr [1:241027] "庚寅" "庚寅" "庚寅" "庚寅" ...
## $ 음력간지일한자: chr [1:241027] "己丑" "庚寅" "辛卯" "壬辰" ...
## $ 율리우스적일 : num [1:241027] 2229156 2229157 2229158 2229159 2229160 ...
## $ 손없는날 : logi [1:241027] FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ 손있는날 : chr [1:241027] "동" "동" "남" "남" ...
손없는날을 찾는 함수를 만들어보자.
find_son <- function(date) {
son <- datatoys::Kcalendar %>%
filter(양력날짜 == date) %>%
pull(손없는날)
return(son)
}
find_son(date = "2024-01-01")
## [1] TRUE
## [1] FALSE
임의의 날짜를 입력하면 손없는 날인지 아닌지를 판별해주는 함수를 만들었다. 하지만 TRUE 또는 FALSE로 표현되는 함수는 보기 친절하지 않다. 손없는 날이면 “손없는 날입니다.”라는 메시지를, 손없는 날이 아니면 “손없는 날이 아닙니다.”라는 메시지를 출력하는 함수를 만들어보자. if()
함수를 이용해 손없는 날인지 아닌지를 판별하고, paste0()
함수를 이용해 메시지를 출력한다. 만약 son == FALSE
라면 else{}
함수를 이용해 “손없는 날이 아닙니다.”라는 메시지를 출력한다.
find_son <- function(date) {
son <- datatoys::Kcalendar %>%
filter(양력날짜 == date) %>%
pull(손없는날)
if(son == TRUE) {
message <- paste0(date,"은 '손없는 날' 입니다.")
} else {
message <- paste0(date,"은 '손없는 날'이 아닙니다.")
}
return(message)
}
find_son(date = "2024-01-01")
## [1] "2024-01-01은 '손없는 날' 입니다."
## [1] "2024-01-02은 '손없는 날'이 아닙니다."
8.1 map() 함수
R에서 반복된 작업을 수행할 때 purrr
패키지의 여러 함수들을 사용할 수 있다. purrr
패키지는 함수형 프로그래밍 패러다임을 지원하는 패키지로, map()
함수를 이용해 반복된 작업을 수행할 수 있다. map()
함수는 리스트, 벡터, 데이터프레임 등의 객체에 함수를 적용해주는 함수로, map()
함수의 첫번째 인자에는 적용할 함수를, 두번째 인자에는 적용할 객체를 입력한다. map()
함수는 for
반복문과 유사한 기능을 수행한다.
map()
함수를 이용해 손없는 날인지 아닌지를 판별해보자.
library(purrr)
date <- c("2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05", "2024-01-06", "2024-01-07", "2024-01-08", "2024-01-09", "2024-01-10")
map(date, find_son)
## [[1]]
## [1] "2024-01-01은 '손없는 날' 입니다."
##
## [[2]]
## [1] "2024-01-02은 '손없는 날'이 아닙니다."
##
## [[3]]
## [1] "2024-01-03은 '손없는 날'이 아닙니다."
##
## [[4]]
## [1] "2024-01-04은 '손없는 날'이 아닙니다."
##
## [[5]]
## [1] "2024-01-05은 '손없는 날'이 아닙니다."
##
## [[6]]
## [1] "2024-01-06은 '손없는 날'이 아닙니다."
##
## [[7]]
## [1] "2024-01-07은 '손없는 날'이 아닙니다."
##
## [[8]]
## [1] "2024-01-08은 '손없는 날'이 아닙니다."
##
## [[9]]
## [1] "2024-01-09은 '손없는 날'이 아닙니다."
##
## [[10]]
## [1] "2024-01-10은 '손없는 날' 입니다."
map()
함수는 기본적으로 리스트(list) 형태의 값을 반환한다. 만약 데이터프레임 형태로 값을 반환하고 싶다면 map_df()
함수를 사용한다.
map_df(date, find_son)
아마도 아래와 같은 에러 메시지를 반환할 것이다.
> map_dfr(date, find_son)
Error in `dplyr::bind_rows()`:
! Argument 1 must have names.
Run `rlang::last_error()` to see where the error occurred.
이는 find_son()
함수가 데이터프레임 형태를 반환하지 않기 때문에 발생하는 에러이다. find_son()
함수를 수정해보자.
find_son <- function(date) {
son <- datatoys::Kcalendar %>%
filter(양력날짜 == date) %>%
pull(손없는날)
if(son == TRUE) {
message <- paste0(date,"은 '손없는 날' 입니다.")
} else {
message <- paste0(date,"은 '손없는 날'이 아닙니다.")
}
return(data.frame(date = date, message = message))
}
map_df(date, find_son)
## date message
## 1 2024-01-01 2024-01-01은 '손없는 날' 입니다.
## 2 2024-01-02 2024-01-02은 '손없는 날'이 아닙니다.
## 3 2024-01-03 2024-01-03은 '손없는 날'이 아닙니다.
## 4 2024-01-04 2024-01-04은 '손없는 날'이 아닙니다.
## 5 2024-01-05 2024-01-05은 '손없는 날'이 아닙니다.
## 6 2024-01-06 2024-01-06은 '손없는 날'이 아닙니다.
## 7 2024-01-07 2024-01-07은 '손없는 날'이 아닙니다.
## 8 2024-01-08 2024-01-08은 '손없는 날'이 아닙니다.
## 9 2024-01-09 2024-01-09은 '손없는 날'이 아닙니다.
## 10 2024-01-10 2024-01-10은 '손없는 날' 입니다.