데이터 과학

시간데이터

학습 목표

  • 날짜 및 시간 데이터를 이해하고 처리한다.

lubridate 팩키지 1

날짜-시간 데이터는 작업하기 까다로운데 이유는 형식이 너무나 다양해서, 날짜-시간 정보를 담긴 데이터를 파싱해서 R에 인식시키기가 손이 많이 가기 때문이다.

이런 문제를 해결하기 위해서 다양한 팩키지들이 개발되어 활용되고 있다. 예를 들어, chron, timeDate, zoo, xts, its, tis, timeSeries, fts, tseries 팩키지가 날짜-시간 데이터를 처리하지만, lubridate 를 활용하여 살펴본다.

기본 R 메쏘드와 lubridate 메쏘드 구문 비교

기본 R 메쏘드 lubridate 메쏘드
date <- as.POSIXct(“01-01-2010”, format = “%d-%m-%Y”, tz = “UTC”) date <- dmy(“01-01-2010”)
as.numeric(format(date, “%m”)) or as.POSIXlt(date)$month + 1 month(date)
date <- as.POSIXct(format(date, “%Y-2-%d”), tz = “UTC”) month(date) <- 2
date <- seq(date, length = 2, by = “-1 day”)[2] date <- date - days(1)
as.POSIXct(format(as.POSIXct(date), tz = “UTC”), tz = “GMT”) with_tz(date, “GMT”)

날짜-시간 데이터 파싱 2

ymd 함수를 사용해서 연도, 월, 일 문자열 정보를 인자로 넘겨 날짜-시간 자료형으로 변형한다.

library(lubridate)
ymd("20110604")
FALSE [1] "2011-06-04"
mdy("06-04-2011")
FALSE [1] "2011-06-04"

날짜 시간 형식으로 전환하는데 ymd_hms 함수가 가장 흔히 사용된다. 시간대를 특정하는데 tz 인자를 사용한다.

arrive <- ymd_hms("2011-06-04 12:00:00", tz = "Pacific/Auckland")
arrive
FALSE [1] "2011-06-04 12:00:00 NZST"
leave <- ymd_hms("2011-08-10 14:00:00", tz = "Pacific/Auckland")
leave
FALSE [1] "2011-08-10 14:00:00 NZST"

날짜-시간 정보 추출

second, minute, hour, day, wday, yday, week, month, year, tz 함수를 사용해서 날짜와 시간 정보를 데이터에서 추출한다. wday함수와 month함수는 선택옵션으로 label 인자를 갖게 되어 숫자를 요일과 월명으로 출력할 수 있다.

second(arrive)
FALSE [1] 0
second(arrive) <- 25
arrive
FALSE [1] "2011-06-04 12:00:25 NZST"
second(arrive) <- 0
wday(arrive)
FALSE [1] 7
wday(arrive, label = TRUE)
FALSE [1] Sat
FALSE Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat

시간대 제어

with_tzforce_tz 함수로 시간대 관리 작업을 제어한다.

meeting <- ymd_hms("2011-07-01 09:00:00", tz = "Pacific/Auckland")
with_tz(meeting, "America/Chicago")
FALSE [1] "2011-06-30 16:00:00 CDT"

약속시간을 잘못알아 시간대를 변경할 경우 force_tz 함수로 시간대를 변경한다.

mistake <- force_tz(meeting, "America/Chicago")
with_tz(mistake, "Pacific/Auckland")
FALSE [1] "2011-07-02 02:00:00 NZST"

시간 간격

interval 함수를 사용해서 시간 간격(time interval)을 계산할 수 있다.

auckland <- interval(arrive, leave) 
auckland
FALSE [1] 2011-06-04 12:00:00 NZST--2011-08-10 14:00:00 NZST

동일하게 %--% 함수를 사용해서도 가능하다.

auckland <- arrive %--% leave
auckland
FALSE [1] 2011-06-04 12:00:00 NZST--2011-08-10 14:00:00 NZST

시간 간격이 겹치는지 확인하고자 새로운 시간 간격 객체를 생성하자.

jsm <- interval(ymd(20110720, tz = "Pacific/Auckland"), ymd(20110831, tz = "Pacific/Auckland"))
jsm
FALSE [1] 2011-07-20 NZST--2011-08-31 NZST

두 시간 간격이 겹치는지 확인해 보자.

int_overlaps(jsm, auckland)
FALSE [1] TRUE

그 외에도 setdiff, int_start, int_end, int_flip, int_shift, int_aligns, union, intersect, setdiff, %within% 다양한 함수를 통해 작업이 가능하다.

setdiff(auckland, jsm)
FALSE [1] 2011-06-04 12:00:00 NZST--2011-07-20 NZST

날짜 시간 산술 연산

기간(interval)은 특정 기간이다. 즉, 특정된 날짜에 구속된다. lubridate 함수는 durationperiod 클래스를 제공한다.

minutes(2) ## period
FALSE [1] "2M 0S"
dminutes(2) ## duration
FALSE [1] "120s (~2 minutes)"

기간(duration)의 경우 1년은 항상 365일이 되지만, 시기(Period)는 시각표가 직관적으로 제시하는 것과 같은 방식으로 변동하게 된다. 예를 들어, 기간은 윤년이 있는 경우 정직하게 숫자를 제시하지만, 시기는 예상하는 바를 제시하게 된다.

leap_year(2011) ## regular year
FALSE [1] FALSE
ymd(20110101) + dyears(1)
FALSE [1] "2012-01-01"
ymd(20110101) + years(1)
FALSE [1] "2012-01-01"
leap_year(2012) ## leap year
FALSE [1] TRUE
ymd(20120101) + dyears(1)
FALSE [1] "2012-12-31"
ymd(20120101) + years(1)
FALSE [1] "2013-01-01"

기간과 시기를 사용해서 날짜-시간에 대한 기본 연산도 할 수 있다.

meetings <- meeting + weeks(0:5)
meetings %within% jsm
FALSE [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE

오클랜드에 얼마나 머무를까?

auckland / ddays(1)
FALSE [1] 67.08333
auckland / ddays(2)
FALSE [1] 33.54167
auckland / dminutes(1)
FALSE [1] 96600

나머지 연산자와 정수 나눗셈을 할 수도 있다.

auckland %/% months(1)
FALSE [1] 2
auckland %% months(1)
FALSE [1] 2011-08-04 12:00:00 NZST--2011-08-10 14:00:00 NZST
as.period(auckland %% months(1))
FALSE [1] "6d 2H 0M 0S"
as.period(auckland)
FALSE [1] "2m 6d 2H 0M 0S"

벡터화

lubridate는 벡터화가 되어 있어 바로 함수와 인터랙티브한 방식으로 적용이 가능하다.

last_day <- function(date) {
  ceiling_date(date, "month") - days(1)
}