1 lubridate 팩키지 1

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

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

lubridate 팩키지 기능 요약

  • 날짜-시간 데이터를 식별하고 파싱한다.
  • 년, 월, 일, 시, 분, 초 같은 날짜-시간 구성요소를 추출하고 변형한다.
  • 날짜-시간 사이 기간을 정확하게 계산한다.
  • 시간대와 일광 절약 시간을 처리한다.

1.1 베이스 R 함수와 lubridate 함수 구문 비교

문자열을 날짜 자료형으로 변환하는 코드를 Base 메쏘드와 lubridate 함수를 비교하면 lubridate 팩키지를 사용할 경우 유용성이 쉽게 확인된다.

Base 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 날짜-시간 데이터 파싱 2

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

[1] "2011-06-04"
[1] "2011-06-04"

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

[1] "2011-06-04 12:00:00 KST"
[1] "2011-08-10 14:00:00 KST"

워낙 다양한 문자열로 다양한 방식으로 날짜/시간을 표시하기 때문에 format=인자로 파싱을 하는데 다음 날짜/기간 관련 기호를 활용한다.

문자 의미
d 일(day of month)
m
y 세기 없는 년도
Y 세기 있는 년도
H 시간(24기준)
M
S
a 축약된 요일명
A 전체 요일명
b 축약된 월명
B 전체 월명
I 시간(12기준)
p 오전/우호(AM/PM)
z 시간대

lubridate 팩키지 dmy_hms() 함수를 사용하는 것도 방법이고 parse_date_time() 함수로 orders=를 지정해서 푸는 것도 방법이다.

[1] "2017-01-25 22:17:30 UTC"
[1] "2017-01-25 10:17:30 UTC"

2.1 날짜/시간 다른 칼럼 -make_date()

경우에 따라서는 연도, 월, 일, 시, 분, 초가 각기 다른 칼럼에 담긴 경우도 있다. 이런 경우 make_date() 함수를 사용해서 날짜/시간 자료형으로 데이터를 변환시킨다.

# A tibble: 3 x 4
     년    월    일 날짜      
  <dbl> <dbl> <dbl> <date>    
1  2000    10    31 2000-10-31
2  2018     8     7 2018-08-07
3  1973    10     3 1973-10-03

2.2 날짜/시간 → 날짜

“연-월-일 시:분:초” 형태로 된 데이터를 “연-월-일” 형태로 변환하고자 하는 경우 as.Date() 함수를 사용해서 날짜/시간 자료형을 날짜 형태로 변환시킨다.

  1. 날짜시간 난수를 5개 발생시킨다.
  2. ymd_hms() 함수로 밀리초 단위 문자열을 날짜시간 자료형으로 변환시킨다.
  3. as.Date() 함수로 “날짜시간” 자료형을 시간은 떼내고 “날짜” 자료형으로 변환시킨다.
[1] "1985-04-25 14:38:28" "2012-11-13 17:04:47" "1980-02-03 21:50:44"
[4] "2014-03-27 10:56:33" "1989-02-05 01:17:52"
# A tibble: 5 x 2
  날짜시간            시간      
  <dttm>              <date>    
1 1985-04-25 14:38:28 1985-04-25
2 2012-11-13 17:04:47 2012-11-13
3 1980-02-03 21:50:44 1980-02-03
4 2014-03-27 10:56:33 2014-03-27
5 1989-02-05 01:17:52 1989-02-05

3 날짜-시간 정보 추출

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

[1] 0
[1] "2011-06-04 12:00:25 KST"
[1] 7
[1] 토
Levels: 일 < 월 < 화 < 수 < 목 < 금 < 토

3.1 시간대 제어

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

[1] "2011-06-30 19:00:00 CDT"

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

[1] "2011-07-01 23:00:00 KST"

4 시간 범위(time span)

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

[1] 2011-06-04 12:00:00 KST--2011-08-10 14:00:00 KST

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

[1] 2011-06-04 12:00:00 KST--2011-08-10 14:00:00 KST

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

[1] 2011-07-20 NZST--2011-08-31 NZST

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

[1] TRUE

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

[1] 2011-06-04 12:00:00 KST--2011-07-19 21:00:00 KST

5 날짜 시간 산술 연산

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

lubridate에서 시간 범위를 표현하는 두가지 다른 개념이 존재한다. PERIODDURATION이 그것이다.

period duration
사람이 인지하는 시간 범위 기계가 인지하는 시간 범위
가변적인 시간범위 고정된 시간 범위
minutes() = “1M 0S” dminutes() = “60s (~1 minutes)”

PERIODDURATION을 R에서 다루는 함수는 다음과 같다. PERIOD 함수에 앞에 d를 붙인다.

시간 범위 Duration Period
초(Second) dseconds() seconds()
분(Minute) dminutes() minutes()
시(Hour) dhours() hours()
일(Day) ddays() days()
주(Week) dweeks() weeks()
월(Month) months()
년(Year) dyears() years()
[1] "2M 0S"
[1] "120s (~2 minutes)"

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

[1] FALSE
[1] "2012-01-01"
[1] "2012-01-01"
[1] TRUE
[1] "2012-12-31"
[1] "2013-01-01"

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

[1] FALSE FALSE FALSE  TRUE  TRUE  TRUE

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

[1] 67.08333
[1] 33.54167
[1] 96600

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

[1] 2
[1] 2011-08-04 12:00:00 KST--2011-08-10 14:00:00 KST
[1] "6d 2H 0M 0S"
[1] "2m 6d 2H 0M 0S"

5.1 벡터화

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

6 사례: 대통령 재임기간 선거 3

위키백과사전에서 대한민국의 대통령 목록 확인된 대통령 재임기간은 다음과 같다.

  • 이승만: 4,273일 (11년 8개월 11일)
  • 윤보선: 588일 (1년 7개월 10일)
  • 박정희: 5,793일 (15년 10개월 9일)
  • 최규하: 255일 (8개월 10일)
  • 전두환: 2,733일 (7년 5개월 23일)
  • 박근혜: 1,475일 (4년 14일)

대통령 취임일과 종료일을 입력하고 시작일과 종료일을 날짜 자료형으로 변형시키게 되면 연산이 가능하다. 따라서 615선언 이후 즉, 노태우 대통령이후 대통령만 추려서 재임기간을 사람이 인식하는 일반적인 재임기간과 절대시간 기준으로 나눠본다. 그리고 나서 정렬을 해야 하는데 현재 interval 객체가 데이터프레임에 들어가면 정렬하는 기능은 지원되고 있지 않다. 따라서 다음과같은 표로 확인을 한다.

이름 시작일 종료일 시작종료 재임기간 절대시간 정렬키
노태우 1988-02-25 1993-02-24 1988-02-25 UTC–1993-02-24 UTC 4y 11m 30d 0H 0M 0S 157766400s (~5 years) 157766400
김영삼 1993-02-25 1998-02-24 1993-02-25 UTC–1998-02-24 UTC 4y 11m 30d 0H 0M 0S 157680000s (~5 years) 157680000
김대중 1998-02-25 2003-02-24 1998-02-25 UTC–2003-02-24 UTC 4y 11m 30d 0H 0M 0S 157680000s (~5 years) 157680000
노무현 2003-02-25 2008-02-24 2003-02-25 UTC–2008-02-24 UTC 4y 11m 30d 0H 0M 0S 157680000s (~5 years) 157680000
이명박 2008-02-25 2013-02-24 2008-02-25 UTC–2013-02-24 UTC 4y 11m 30d 0H 0M 0S 157766400s (~5 years) 157766400
박근혜 2013-02-25 2016-12-09 2013-02-25 UTC–2016-12-09 UTC 3y 9m 14d 0H 0M 0S 119491200s (~3.79 years) 119491200
문재인 2017-05-10 2022-05-10 2017-05-10 UTC–2022-05-10 UTC 5y 0m 0d 0H 0M 0S 157766400s (~5 years) 157766400

두번째로 총선과 지방선거를 넣고 재임기간동안 선거가 얼마나 많이 일어났는지 확인해보자. 위키백과사전, 대한민국의 선거에서 데이터를 받아 정리한다.

지방선거 시작된 이후 선거만 추출하고 재임기간 계산해서 반환하는 Helper 함수를 작성해서 각 대통령별로 해당 재임기간 있었던 선거를 개수한다.

# 1987년 이후 총선/대선/지선 선거일 
election_df <- tribble(~"선거", ~"선거일",
                       "1987년 개헌 국민투표", "1987-10-27",
                       "제13대 대통령 선거",   "1987-12-16",
                       "제13대 국회의원 선거", "1988-04-26",
                       "제14대 국회의원 선거", "1992-03-24",
                       "제14대 대통령 선거",   "1992-12-18",
                       "제1회 지방선거",       "1995-06-27",
                       "제15대 국회의원 선거", "1996-04-11",
                       "제15대 대통령 선거",   "1997-12-18",
                       "제2회 지방선거",       "1998-06-04",
                       "제16대 국회의원 선거", "2000-04-13",
                       "제3회 지방선거",       "2002-06-13",
                       "제16대 대통령 선거",   "2002-12-19",
                       "제17대 국회의원 선거", "2004-04-15",
                       "제4회 지방선거",       "2006-05-31",
                       "제17대 대통령 선거",   "2007-12-19",
                       "제18대 국회의원 선거", "2008-04-09",
                       "제5회 지방선거",       "2010-06-02",
                       "제19대 국회의원 선거", "2012-04-11",
                       "제18대 대통령 선거",   "2012-12-19",
                       "제6회 지방선거",       "2014-06-04",
                       "제20대 국회의원 선거", "2016-04-13",
                       "제19대 대통령 선거",   "2017-05-09",
                       "제7회 지방선거",       "2018-06-13")

# 지방선거 시작된 이후 선거만 추출
election_df <- election_df %>% 
  mutate(`선거일` = ymd(`선거일`)) %>% 
  filter(`선거일` > ymd("1995-01-01"))

# 재임기간 계산해서 반환하는 Helper 함수
get_reign <- function(president_name) {
  president_reign <- president_dat %>% 
    filter(`이름` == president_name) %>% 
    mutate(`시작일` = lubridate::ymd(`시작일`),
         `종료일` = lubridate::ymd(`종료일`)) %>% 
    mutate(`시작종료` = interval(`시작일`, `종료일`)) %>% 
    pull(`시작종료`)
  return(president_reign)
}

get_reign("노무현")
[1] 2003-02-25 UTC--2008-02-24 UTC
# A tibble: 18 x 8
   선거                선거일     김영삼 김대중 노무현 이명박 박근혜 문재인
   <chr>               <date>     <lgl>  <lgl>  <lgl>  <lgl>  <lgl>  <lgl> 
 1 제1회 지방선거      1995-06-27 TRUE   FALSE  FALSE  FALSE  FALSE  FALSE 
 2 제15대 국회의원 선거~ 1996-04-11 TRUE   FALSE  FALSE  FALSE  FALSE  FALSE 
 3 제15대 대통령 선거  1997-12-18 TRUE   FALSE  FALSE  FALSE  FALSE  FALSE 
 4 제2회 지방선거      1998-06-04 FALSE  TRUE   FALSE  FALSE  FALSE  FALSE 
 5 제16대 국회의원 선거~ 2000-04-13 FALSE  TRUE   FALSE  FALSE  FALSE  FALSE 
 6 제3회 지방선거      2002-06-13 FALSE  TRUE   FALSE  FALSE  FALSE  FALSE 
 7 제16대 대통령 선거  2002-12-19 FALSE  TRUE   FALSE  FALSE  FALSE  FALSE 
 8 제17대 국회의원 선거~ 2004-04-15 FALSE  FALSE  TRUE   FALSE  FALSE  FALSE 
 9 제4회 지방선거      2006-05-31 FALSE  FALSE  TRUE   FALSE  FALSE  FALSE 
10 제17대 대통령 선거  2007-12-19 FALSE  FALSE  TRUE   FALSE  FALSE  FALSE 
11 제18대 국회의원 선거~ 2008-04-09 FALSE  FALSE  FALSE  TRUE   FALSE  FALSE 
12 제5회 지방선거      2010-06-02 FALSE  FALSE  FALSE  TRUE   FALSE  FALSE 
13 제19대 국회의원 선거~ 2012-04-11 FALSE  FALSE  FALSE  TRUE   FALSE  FALSE 
14 제18대 대통령 선거  2012-12-19 FALSE  FALSE  FALSE  TRUE   FALSE  FALSE 
15 제6회 지방선거      2014-06-04 FALSE  FALSE  FALSE  FALSE  TRUE   FALSE 
16 제20대 국회의원 선거~ 2016-04-13 FALSE  FALSE  FALSE  FALSE  TRUE   FALSE 
17 제19대 대통령 선거  2017-05-09 FALSE  FALSE  FALSE  FALSE  FALSE  FALSE 
18 제7회 지방선거      2018-06-13 FALSE  FALSE  FALSE  FALSE  FALSE  TRUE  
# A tibble: 6 x 2
  대통령 선거횟수
  <chr>     <int>
1 김대중        4
2 이명박        4
3 김영삼        3
4 노무현        3
5 박근혜        2
6 문재인        1