Lovetoken

저는 개발 취향을 가진 데이터 분석가 Jr. 입니다.

Navigation
 » Home
 » About Me
 » Github

R에서 lubridate package 에 대해

18 Sep 2016 » R







lubridate package 는 Garrett Grolemund 와 Hadley Wickham 외 8명의 힘이 더해져 만들어진 날짜처리 생산성 패키지이다.

날짜(Date) & 시각(Time) 데이터는 전 세계 사람들에 의해 보편적으로 정해진 규칙이 있는데, 이 규칙을 정확하게 알지 못하고 데이터를 처리할 때 혼돈이 일어날 수 있다.
의외로 위에서 말한 규칙들은 따져볼수록 많고 복잡하여 사람이 실수할 수 있을 여지가 높다.
이런 예제랄까?

  • 어느 연도가 윤년이어서 2월 29일이 있는지 없는지 신경 쓰지 않으면 알 수 없다…
  • 4월 31일 데이터셋을 정의 (그런 날짜는 존재하지 않는데도 불구하고)

이런 것 외에도 우리가 접할 수 있는 여러 가지 상황을 가정 해 볼 수 있는데

  • 분석 시 기준 Timezone 이 변경될 경우
  • 날짜와 시각이 조합된 데이터의 산술연산이 필요할 경우 (시간별 평균, 요일별 평균, 월별 평균 등)
  • 공휴일, 주말을 제외한 날짜의 데이터만을 남김
  • 주기성 데이터의 주기를 맞추기 위한 시각 스케일링 (10분단위 주기라면 01:00, 01:10, 01:20, 01:30, 01:40 … 형태로 데이터가 있으면 하는 바램)
  • (정말 특이한 사례지만) 일광절약시간제에 해당되는 Time index 가 존재할 경우

등등 날짜시각 데이터셋에 대한 처리에 있어 위 이슈들이 별거 아닌것 처럼 보이지만
실전에서 우리를 괴롭힐 만한 요소들은 차고 넘친다.

이 실수들과 장애물들을 사전에 방지하기 위한 다양한 R 패키지가 제공되고 있다.
내가 아는 것을 기준으론 xts, zoo, lubridate, chron 의 패키지 정도를 알고 있으되, 자주 사용하는 패키지는 xts 이었다.

이번에 살펴볼 lubridate package 는 lubricate(기름을 치다, 기름을 바르다, 원활히 하다) 의 “lubri” 와 “date” 를 합성시킨 것으로 추측되는데
이처럼 날짜시각 데이터를 원활하게 가공하는 데 도움을 주기 위한 목적으로 특화된 느낌을 받는다.

xts, zoo 패키지 조합 역시 강력하지만 강력한 만큼 친숙함은 주지 못한 것 같다.
이러한 단점을 보완하고자 부가적으로 알아야 하겠다고 마음먹게 된 패키지 중 하나이었고,
R studio 의 Hadley Wickham 에 의해 유지보수 되고 있다고 해서 그 때문에 공부를 시작하기도 한 것 같다.

Lubridate is an R package that makes it easier to work with dates and times.
- Do more with dates and times in R with lubridate 1.3.0

얼마나 우리의 일을 쉽게 해 주는지 내가 겪었던 시행착오와 곁들여

library(lubridate)

를 실행 후 한 번 탐색해 보겠다.



dates & times 객체 만들기

Date 객체 만들기

R에서 2011년 6월 4일 날짜 데이터를 만들려면 가장 기본적인 방법이 아래의 코드일 것이다.

as.Date("2011-06-04")
## [1] "2011-06-04"
as.Date("2011-6-4")
## [1] "2011-06-04"
as.Date("2011/06/04")
## [1] "2011-06-04"
## 
## as.Date("20110604") # error

R의 가장 전통적인 날짜 데이터 class 는 Date 일 것이다.
마지막 코드 as.Date("20110604") 와 같이 에러가 나는 코드도 한번 작성해 보았는데
이처럼 날짜 데이터셋을 만들기 위해 문자열을 input 하는 방식으로 사용할 경우 문자열을 어떠한 양식에 따라 작성할 것인지도 사람마다 제각각이고 그에 따라 코드가 실행되지 않는 경우가 발생할 것이다.
그 양식 중 "20110604" 와 같이 딜리미터가 없는 문자열은 as.Date() 가 날짜로 변환할 때
어디가 year 이고 month 이며 day 인지 알 수 없어한다.

또한

as.Date("06-04-2011")
## [1] "0006-04-20"

처럼 미국식 날짜 표기법을 사용할 경우에도 마찬가지 문제가 발생한다.

이번엔 lubridate package 의 “y”, “m”, “d” 심볼을 이용한 함수들을 이용해 보겠다.

ymd("2011/06/04")
## [1] "2011-06-04"

“y”, “m”, “d” 심볼이라고 소개했는데 각각 year, month, day 로 이해할 수 있고
이 심볼의 순서를 바꾸어도 먹히는 함수들이 사전에 준비되어 있다.

mdy("06/04/2011")
## [1] "2011-06-04"

“06/04/2011” 은 2011년 6월 4일을 미국식으로 날짜 표기한 것인데, 이를 제대로 인식하기 위해서 심볼들의 순서를 그에 맞춘 함수를 이용하면 되겠다.

dmy("04/06/2011")
## [1] "2011-06-04"

문자열 양식에는 어느정도의 관용이 있는지 살펴보았다.

ymd("2011/06/04")
## [1] "2011-06-04"
ymd("2011-06-04")
## [1] "2011-06-04"
ymd("20110604")
## [1] "2011-06-04"
ymd("110604")
## [1] "2011-06-04"
ymd("11.06.04")
## [1] "2011-06-04"
ymd("11,06,04")
## [1] "2011-06-04"
ymd("11_06.04") # ?
## [1] "2011-06-04"
ymd("2011  06  04") # ㅋㅋ?
## [1] "2011-06-04"
ymd("2011!?06??!04") # !?
## [1] "2011-06-04"
ymd("2011 =06??04") # -_-?
## [1] "2011-06-04"
ymd("11 No 06 way 04") # No way!
## [1] "2011-06-04"

lubridate package 설명서에는
heterogeneous format(불균일한 양식)에 대한 다양한 준비들이 되어있음을 강조한 문구가 담겨 있는 걸 보았다.
이처럼 사람의 실수들은 웬만하면 커버할 듯한 위용이다.


Dates + Times 객체 만들기

“2011년 6월 4일” 에 구체적인 시각까지 더해서
“2011년 6월 4일 13시 30분 50초” 를 R에서 만들어 보겠다.
시각까지 더해진 정보는 Date class 로 정보를 담을 수 없다.
as.Date() 함수로 2011년 6월 4일 13시 30분 50초 정보를 만들 수 없다.

as.Date("2011-06-04 13:30:50") # 시각정보가 사라짐
## [1] "2011-06-04"

이때부턴 포직스(POSIX) 클래스를 대중적으로 이용하는것으로 알고 있다.

as.POSIXct("2011-06-04 13:30:50")
## [1] "2011-06-04 13:30:50 KST"
temp <- as.POSIXlt("2011-06-04 13:30:50") # list 기반

이번엔 lubridate package 의 경우이다.
lubridate package 에는 “y”, “m”, “d” 심볼 뿐만 아니라 “h”, “m”, “s” 역시 준비되어 있다.
각각 hour, minute, second 로 이해할 수 있다.
위의 설명했던 대로 “y”, “m”, “d” 와 “h”, “m”, “s” 를 잘 조합하여 사용하면
비교적 편하게 “2011년 6월 4일 13시 30분 50초” 정보를 담을 수 있다.

ymd_hms("2011-06-04 13:30:50")
## [1] "2011-06-04 13:30:50 UTC"

as.POSIXct() 와 비교해볼 때 날짜시각 객체를 만드는 방법이 별반 틀릴 것이 없다.
하지만 조금 더 융통성이 있게 사용할 수 있는 점들이 몇 가지 눈에 띈다.

만약 분, 초 단위의 정보가 없는 경우 “2011년 6월 4일 13시” 의 정보가 입력된다고 가정하면 어떨까?

ymd_h("2011-06-04 13")
## [1] "2011-06-04 13:00:00 UTC"

ymd_hms() 에서 “m”, “s” 심볼을 제외한 ymd_h() 함수를 이용해 파싱하면 된다.
하지만 as.POSIXct() 으로 "2011-06-04 13" 을 파싱하는 방법은 조금 고민을 해야하거나 투입되는 문자열 값 자체를 사전에 건드려야 하는 과정이 필요하다.

as.POSIXct("2011-06-04 13") # No
## [1] "2011-06-04 KST"
as.POSIXct("2011-06-04 13:00:00") # Yes
## [1] "2011-06-04 13:00:00 KST"

이런 예시로 볼 때 lubridate package 는 사용자 관점으로 친숙한 도구들이 여럿 준비되어 있다.
그외에도 heterogeneous format 에 대한 대비 역시 날짜 + 시각 데이터에도 적용되고 유효하다.



부분정보 추출 (Extracting information)

lubridate package 에는 부분정보를 추출하기 위한 간편 함수들이 여럿 준비되어 있다.
second(), minute(), hour(), day(), wday(), yday(), week(), month(), year() 처럼 함수명칭도 상식적이어서 피곤하지 않다.

ld1 <- ymd_hms("2011-06-04 13:30:50")

year(ld1)
## [1] 2011
month(ld1)
## [1] 6
day(ld1)
## [1] 4
wday(ld1)
## [1] 7
yday(ld1)
## [1] 155
hour(ld1)
## [1] 13
minute(ld1)
## [1] 30
second(ld1)
## [1] 50

특히 month, wday 의 경우 label 인자를 가지고 있는데 이를 TRUE 로 설정할 경우에

month(ld1, label = T)
## [1] Jun
## 12 Levels: Jan < Feb < Mar < Apr < May < Jun < Jul < Aug < Sep < ... < Dec
wday(ld1, label = T)
## [1] Sat
## Levels: Sun < Mon < Tue < Wed < Thu < Fri < Sat

월, 요일의 명칭을 factor 형으로 반환한다.


부분정보 수정

“2011년 6월 4일 13:30:50” 로 저장되어있던 ld1 에 대해 시각(hour)을 10시로 바꾸려면 어떻게 하여야 할까?
내가볼 때 가장 간단한 방법은 부분정보 추출시 사용했던 간편함수들과 assign 연산자를 조합시켜 변경하는 방법이다.
아래처럼 사용하면 된다.

hour(ld1) <- 10
ld1
## [1] "2011-06-04 10:30:50 UTC"

update() 제너릭 함수를 사용할 수도 있는데, 엄밀히 말하면 update.POSIXt() 를 이용하는 방법이다.
아래 코드는 update() 함수를 이용해 10시로 변경된 ld1 을 다시 13로 되돌리는 코드이다.

ld1 <- update(ld1, hour = 13)
ld1
## [1] "2011-06-04 13:30:50 UTC"

POSIXlt class 인 경우엔 $ 와 assign operator 를 조합해 사용할 수 있는데 이 또한 매력적인 방법이라 생각된다.
하지만 아쉽게도 ld1 는 POSIXct class 이므로 $ 가 바로 먹히지는 않는다.

ld1$hour # error

굳이 $ 과 assign operator 를 조합해 사용하고 싶다면 as.POSIXlt() 를 한번 거쳐야 할 것이다.

ld2 <- as.POSIXlt(ld1)
ld2$hour <- 10
ld2
## [1] "2011-06-04 10:30:50 UTC"



날짜시각에 대한 산술연산

lubridate 와 같은 패키지를 공부하는 목적 중 가장 중요한 특징이 아닐까 싶다.
같은 날짜 + 시각의 데이터 대한 산술연산은 신경이 많이 쓰이는 문제이다.

사과 30개가 있는데, 사과 2개를 더하면 32개가 된다.
1월 30일인데, 2틀을 더하면(지나면) 32일이 될까?
개인적으론 32일이 되어버렸으면 좋겠지만 32일이란 건 존재하지 않는다. 2월 1일이 된다.

위에 든 예제가 엄청 쉬워 보이지만 날짜 데이터의 양이 많으면 많아질수록 결코 쉬운문제가 아니다.
어느시점부터 날짜 혹은 시각의 산술연산이 잘못 될 경우 도미노처럼 연속적으로 문제가 발생하고, 그 문제를 인지하고 추적하기 까지가 상당히 어려운 편이다.
이러한 이유로 인하여 일반 숫자에 대한 산술연산과 달리, 날짜 + 시각에 대한 산술연산은 많은 피로도를 줄 수 있다.
lubridate package 는 이를 예방할 수 있는 강력한 함수들이 많이 있다.

ymd("2016-01-30") + days(2)
## [1] "2016-02-01"

위의 코드는 1월 30일인데, 2틀을 더하면(지나면)
의 문제를 풀어주는 코드이다.

특정기간이 지나면 무슨날짜가 되는지 확인하기 위해 단순히 “더하기”를 하면 된다. 날짜의 산술연산이 가능하다.

지금까지는 단일시점 한개의 날짜시각 데이터를 가지고 놀았는데
이런 식으로 R의 Vectorization 특징을 활용하여 복수개의 시점을 만들 수도 있다.

ymd("2016-01-30") - days(1:30)
##  [1] "2016-01-29" "2016-01-28" "2016-01-27" "2016-01-26" "2016-01-25"
##  [6] "2016-01-24" "2016-01-23" "2016-01-22" "2016-01-21" "2016-01-20"
## [11] "2016-01-19" "2016-01-18" "2016-01-17" "2016-01-16" "2016-01-15"
## [16] "2016-01-14" "2016-01-13" "2016-01-12" "2016-01-11" "2016-01-10"
## [21] "2016-01-09" "2016-01-08" "2016-01-07" "2016-01-06" "2016-01-05"
## [26] "2016-01-04" "2016-01-03" "2016-01-02" "2016-01-01" "2015-12-31"

잠깐 days() 함수명칭을 살펴보자.
위에서 부분정보 추출 간편함수중 day() 가 있었는데 마지막에 “s” 가 붙음으로써 쓰임이 달라진 것을 볼 수 있다.
days() 뿐만 아니라 seconds(), minutes(), hours(), weeks(), years(), milliseconds(), microseconds(), nanoseconds(), picoseconds() 의 함수들이 이와 같은 산술연산에서 사용할 수 있는 패밀리이다.

Do more with dates and times in R with lubridate 1.3.0 에서 꽤 감명깊은(?) 예제를 발견했는데

ymd("2013-01-31") + months(0:11)
##  [1] "2013-01-31" NA           "2013-03-31" NA           "2013-05-31"
##  [6] NA           "2013-07-31" "2013-08-31" NA           "2013-10-31"
## [11] NA           "2013-12-31"

위 결과를 통해
월 중에 31일이 존재하지 않는 월이 어디인지를 알 수 있게 된다.



lubridate 와 dplyr 간의 조합

lubridate 패키지는 결국 Time index 정보들이 담긴 Table 형태에 정보들을 가공하고 처리하게 될 가능성이 실전에서 높을 것이다.
dplyr package 와 조합하여 현업에서 어떻게 시너지를 일으킬 지를 보잘것없는 예제를 통해 조금이나마 확인해 볼 필요가 있겠다.
lubridate package 에 내장된 데이터셋 lakers 를 이용해 보았다.

library(dplyr)
data(lakers)

lakers <- lakers %>% tbl_df
lakers
## # A tibble: 34,624 x 13
##        date opponent game_type  time period      etype  team
##       <int>    <chr>     <chr> <chr>  <int>      <chr> <chr>
##  1 20081028      POR      home 12:00      1  jump ball   OFF
##  2 20081028      POR      home 11:39      1       shot   LAL
##  3 20081028      POR      home 11:37      1    rebound   LAL
##  4 20081028      POR      home 11:25      1       shot   LAL
##  5 20081028      POR      home 11:23      1    rebound   LAL
##  6 20081028      POR      home 11:22      1       shot   LAL
##  7 20081028      POR      home 11:22      1       foul   POR
##  8 20081028      POR      home 11:22      1 free throw   LAL
##  9 20081028      POR      home 11:00      1       foul   LAL
## 10 20081028      POR      home 10:53      1       shot   POR
## # ... with 34,614 more rows, and 6 more variables: player <chr>,
## #   result <chr>, points <int>, type <chr>, x <int>, y <int>

잘 보면 date, time 변수가 서로 나뉘어 있다.
이를 지금까지 배운 lubridate 함수들을 이용하여 통합시켜 관리해보고 싶었다.

lakers <- lakers %>% 
    mutate(date = paste(date, time) %>% ymd_hm) %>% 
    rename(time_index = date) %>% 
    select(-time)

lakers
## # A tibble: 34,624 x 12
##             time_index opponent game_type period      etype  team
##                 <dttm>    <chr>     <chr>  <int>      <chr> <chr>
##  1 2008-10-28 12:00:00      POR      home      1  jump ball   OFF
##  2 2008-10-28 11:39:00      POR      home      1       shot   LAL
##  3 2008-10-28 11:37:00      POR      home      1    rebound   LAL
##  4 2008-10-28 11:25:00      POR      home      1       shot   LAL
##  5 2008-10-28 11:23:00      POR      home      1    rebound   LAL
##  6 2008-10-28 11:22:00      POR      home      1       shot   LAL
##  7 2008-10-28 11:22:00      POR      home      1       foul   POR
##  8 2008-10-28 11:22:00      POR      home      1 free throw   LAL
##  9 2008-10-28 11:00:00      POR      home      1       foul   LAL
## 10 2008-10-28 10:53:00      POR      home      1       shot   POR
## # ... with 34,614 more rows, and 6 more variables: player <chr>,
## #   result <chr>, points <int>, type <chr>, x <int>, y <int>

위의 코드를 설명하면

  1. date, time 두변수를 붙인 문자열에 대해 ymd_hm() 함수로 넘긴 후
  2. time_index 라는 변수에 담고,
  3. date, time 두 변수를 제외한 것이다.

이렇게 알맞게 변형된 lakers 를 이용해 좀 더 의미가 있을만한 탐색을 해보겠다.


Group by 연산

첫번째는 Group by 연산이다.
월별 평균을 x, y 변수에 대해서 계산해보겠다.
month() 함수를 이용하면 아주 간편하게 할 수 있겠다.

lakers %>% 
    group_by(month(time_index)) %>% 
    summarize(mean_x = mean(x, na.rm = T), mean_y = mean(y, na.rm = T))
## # A tibble: 7 x 3
##   `month(time_index)`   mean_x   mean_y
##                 <dbl>    <dbl>    <dbl>
## 1                   1 25.49382 13.89279
## 2                   2 25.01759 13.17499
## 3                   3 25.51587 13.20571
## 4                   4 25.38344 13.46396
## 5                  10 24.92188 13.12500
## 6                  11 25.47463 13.36926
## 7                  12 25.05895 13.48262

연별 평균을 계산하고 싶다면 year() 이용하면 된다.

lakers %>% 
    group_by(year(time_index)) %>% 
    summarize(mean_x = mean(x, na.rm = T), mean_y = mean(y, na.rm = T))
## # A tibble: 2 x 3
##   `year(time_index)`   mean_x   mean_y
##                <dbl>    <dbl>    <dbl>
## 1               2008 25.23402 13.40776
## 2               2009 25.36407 13.44319


Filter

두번째는 dplyr::filter() 를 이용해 분석에 사용할 기간을 서브세팅 해보는 예제를 만들어 보고 싶었다.
아래 코드는 “2008-10-28 12:00:00” 이전의 기간을 서브세팅 하는 코드이다.

lakers %>% 
    filter(time_index <= ymd_hms("2008-10-28 12:00:00"))
## # A tibble: 416 x 12
##             time_index opponent game_type period      etype  team
##                 <dttm>    <chr>     <chr>  <int>      <chr> <chr>
##  1 2008-10-28 12:00:00      POR      home      1  jump ball   OFF
##  2 2008-10-28 11:39:00      POR      home      1       shot   LAL
##  3 2008-10-28 11:37:00      POR      home      1    rebound   LAL
##  4 2008-10-28 11:25:00      POR      home      1       shot   LAL
##  5 2008-10-28 11:23:00      POR      home      1    rebound   LAL
##  6 2008-10-28 11:22:00      POR      home      1       shot   LAL
##  7 2008-10-28 11:22:00      POR      home      1       foul   POR
##  8 2008-10-28 11:22:00      POR      home      1 free throw   LAL
##  9 2008-10-28 11:00:00      POR      home      1       foul   LAL
## 10 2008-10-28 10:53:00      POR      home      1       shot   POR
## # ... with 406 more rows, and 6 more variables: player <chr>,
## #   result <chr>, points <int>, type <chr>, x <int>, y <int>

잘 보면 기존에 레코드는 34624 개 였지만, 서브세팅 된 후 레코드는 416 개로 줄어든 것을 확인할 수 있다.

만약 “2008-10-28 12:00:00” ~ “2009-03-09 00:33:00” 의 기간에 대해서 서브세팅을 하고싶다면 어떻게 하여야 할까?
물론 filter() 안에 조건을 하나 더 넣으면 된다.

lakers %>% 
    filter(time_index >= ymd_hms("2008-10-28 12:00:00"), time_index <= ymd_hms("2009-03-09 00:33:00"))
## # A tibble: 25,554 x 12
##             time_index opponent game_type period     etype  team
##                 <dttm>    <chr>     <chr>  <int>     <chr> <chr>
##  1 2008-10-28 12:00:00      POR      home      1 jump ball   OFF
##  2 2008-10-29 12:00:00      LAC      away      1 jump ball   OFF
##  3 2008-10-29 11:36:00      LAC      away      1      shot   LAL
##  4 2008-10-29 11:24:00      LAC      away      1      shot   LAC
##  5 2008-10-29 11:24:00      LAC      away      1   rebound   LAL
##  6 2008-10-29 11:08:00      LAC      away      1      shot   LAL
##  7 2008-10-29 10:58:00      LAC      away      1      shot   LAC
##  8 2008-10-29 10:57:00      LAC      away      1   rebound   LAL
##  9 2008-10-29 10:41:00      LAC      away      1      shot   LAL
## 10 2008-10-29 10:40:00      LAC      away      1   rebound   LAC
## # ... with 25,544 more rows, and 6 more variables: player <chr>,
## #   result <chr>, points <int>, type <chr>, x <int>, y <int>

그런데 lubridate package 에는 기간(Time intervals) 에 대해 조금 더 세련된 방법으로 처리할 수 있는 함수들을 제공해 주고 있다.
interval() 함수와 %within% 연산자를 이용하면 조금 더 직관적인 서브세팅을 할 수 있다.
아래처럼 말이다.

inter <- interval(ymd_hms("2008-10-28 12:00:00"), ymd_hms("2009-03-09 00:33:00"))
lakers %>% 
    filter(time_index %within% inter)
## # A tibble: 25,554 x 12
##             time_index opponent game_type period     etype  team
##                 <dttm>    <chr>     <chr>  <int>     <chr> <chr>
##  1 2008-10-28 12:00:00      POR      home      1 jump ball   OFF
##  2 2008-10-29 12:00:00      LAC      away      1 jump ball   OFF
##  3 2008-10-29 11:36:00      LAC      away      1      shot   LAL
##  4 2008-10-29 11:24:00      LAC      away      1      shot   LAC
##  5 2008-10-29 11:24:00      LAC      away      1   rebound   LAL
##  6 2008-10-29 11:08:00      LAC      away      1      shot   LAL
##  7 2008-10-29 10:58:00      LAC      away      1      shot   LAC
##  8 2008-10-29 10:57:00      LAC      away      1   rebound   LAL
##  9 2008-10-29 10:41:00      LAC      away      1      shot   LAL
## 10 2008-10-29 10:40:00      LAC      away      1   rebound   LAC
## # ... with 25,544 more rows, and 6 more variables: player <chr>,
## #   result <chr>, points <int>, type <chr>, x <int>, y <int>

2개의 조건을 머리아프게 정의하는것 보단
interval() 를 사용한 방법이 훨씬 직관적일 수 있겠다.

참고로 덧붙이면 interval() 함수대신 %--% 연산자를 써도 된다.
%--% 를 “~” 처럼 생각하면 편할 것 같다.

inter <- ymd_hms("2008-10-28 12:00:00") %--% ymd_hms("2009-03-09 00:33:00")
lakers %>% 
    filter(time_index %within% inter)
## # A tibble: 25,554 x 12
##             time_index opponent game_type period     etype  team
##                 <dttm>    <chr>     <chr>  <int>     <chr> <chr>
##  1 2008-10-28 12:00:00      POR      home      1 jump ball   OFF
##  2 2008-10-29 12:00:00      LAC      away      1 jump ball   OFF
##  3 2008-10-29 11:36:00      LAC      away      1      shot   LAL
##  4 2008-10-29 11:24:00      LAC      away      1      shot   LAC
##  5 2008-10-29 11:24:00      LAC      away      1   rebound   LAL
##  6 2008-10-29 11:08:00      LAC      away      1      shot   LAL
##  7 2008-10-29 10:58:00      LAC      away      1      shot   LAC
##  8 2008-10-29 10:57:00      LAC      away      1   rebound   LAL
##  9 2008-10-29 10:41:00      LAC      away      1      shot   LAL
## 10 2008-10-29 10:40:00      LAC      away      1   rebound   LAC
## # ... with 25,544 more rows, and 6 more variables: player <chr>,
## #   result <chr>, points <int>, type <chr>, x <int>, y <int>



기타 간편 기능 함수들

Timezone 인자를 받을 수 있는 now()

now()
## [1] "2017-12-11 00:10:20 KST"

now() 함수는 Sys.time() 와 거의 기능이 똑같다.

now("America/New_York")
## [1] "2017-12-10 10:10:20 EST"
now("UTC")
## [1] "2017-12-10 15:10:20 UTC"

단 위의 예제처럼
Timezone 변경에 대해서 Sys.time() 과는 다르게 now() 는 이를 반영한 날짜 + 시각을 반환할 수 있다는 차이가 있다.


오전? 오후? : am(), pm()

지금 시간이 오후인지 오전인지 확인하기 위해서

now()
## [1] "2017-12-11 00:10:20 KST"
hour(now()) >= 12
## [1] FALSE

와 같은 코드를 사용하기 보단

am(now())
## [1] TRUE
pm(now())
## [1] FALSE

요런식으로 활용해 볼 수 있겠다.


시각에 대한 올림, 내림, 반올림

제목대로 시각에 대한 올림, 내림, 반올림은 생각만해도 끔찍하다.
round_date(), floor_date(), ceiling_date() 함수를 활용하는게 정서상 좋을 것이다.

ld1
## [1] "2011-06-04 13:30:50 UTC"

round_date(ld1, "hour")
## [1] "2011-06-04 14:00:00 UTC"
round_date(ld1, "day")
## [1] "2011-06-05 UTC"

floor_date(ld1, "hour")
## [1] "2011-06-04 13:00:00 UTC"
floor_date(ld1, "day")
## [1] "2011-06-04 UTC"

ceiling_date(ld1, "hour")
## [1] "2011-06-04 14:00:00 UTC"
ceiling_date(ld1, "day")
## [1] "2011-06-05 UTC"



Reference