[R] 2. tsibble

반응형

tsibble()

  • tsibble 객체는 아래와 같은 기본적인 원칙을 가집니다.
    • index: 과거부터 현재까지 순서화된 자료값의 관측 시간
    • key: 시간에 따른 관측값을 정의하는 변수의 집합
    • 각 관측치는 indexkey를 통해 유니크하게 식별되어야 합니다.
    • 각 관측치는 등간격으로 관측된 자료여야만 합니다.
  • 즉, tsibble 포맷으로 변환하기 위해서는 데이터에서 keyindex를 명시해주어야 합니다.
  • 아래 nycflights13 라이브러리의 weather 데이터를 활용해서 예시를 보이겠습니다.
weather_sample <- nycflights13::weather %>% 
  select(origin, time_hour, temp, humid, precip)

weather_sample
## # A tibble: 26,115 x 5
##    origin time_hour            temp humid precip
##    <chr>  <dttm>              <dbl> <dbl>  <dbl>
##  1 EWR    2013-01-01 01:00:00  39.0  59.4      0
##  2 EWR    2013-01-01 02:00:00  39.0  61.6      0
##  3 EWR    2013-01-01 03:00:00  39.0  64.4      0
##  4 EWR    2013-01-01 04:00:00  39.9  62.2      0
##  5 EWR    2013-01-01 05:00:00  39.0  64.4      0
##  6 EWR    2013-01-01 06:00:00  37.9  67.2      0
##  7 EWR    2013-01-01 07:00:00  39.0  64.4      0
##  8 EWR    2013-01-01 08:00:00  39.9  62.2      0
##  9 EWR    2013-01-01 09:00:00  39.9  62.2      0
## 10 EWR    2013-01-01 10:00:00  41    59.6      0
## # … with 26,105 more rows
  • origin 변수를 key로, time_hour 변수를 index로 잡습니다.
    • 다중 시계열이 아닌 단일 시계열이라면 key를 명시하지 않으셔도 됩니다.
    • 예시 데이터에서는 출발지(origin) 별로 관측된 다중 시계열에 해당됩니다.
weather_tsbl <- weather_sample %>% 
  as_tsibble(key = origin, index = time_hour)

weather_tsbl
## # A tsibble: 26,115 x 5 [1h] <America/New_York>
## # Key:       origin [3]
##    origin time_hour            temp humid precip
##    <chr>  <dttm>              <dbl> <dbl>  <dbl>
##  1 EWR    2013-01-01 01:00:00  39.0  59.4      0
##  2 EWR    2013-01-01 02:00:00  39.0  61.6      0
##  3 EWR    2013-01-01 03:00:00  39.0  64.4      0
##  4 EWR    2013-01-01 04:00:00  39.9  62.2      0
##  5 EWR    2013-01-01 05:00:00  39.0  64.4      0
##  6 EWR    2013-01-01 06:00:00  37.9  67.2      0
##  7 EWR    2013-01-01 07:00:00  39.0  64.4      0
##  8 EWR    2013-01-01 08:00:00  39.9  62.2      0
##  9 EWR    2013-01-01 09:00:00  39.9  62.2      0
## 10 EWR    2013-01-01 10:00:00  41    59.6      0
## # … with 26,105 more rows

 

  • 인덱스의 간격은 연도(year)부터 나노 초(nanosecond)까지 숫자로 정렬되는 요소로부터 계산됩니다.
  • 아래는 tsibble에서 인덱스의 클래스를 나타낸 표입니다.
Interval Class
Annual integer, double
Quaterly yearquarter
Monthly yearmonth
Weekly yearweek
Daily Date, difftime
Subdaily POSIXt, difftime, hms

 

  • 위에서 기본 가정으로 시계열의 인덱스는 등간격을 가정하였는데, 사실 tsibble() 함수는 등간격이 아닌 자료에 대해서도 적용이 가능합니다.
  • tsibble() 함수의 regular = FALSE arguments를 설정하면 됩니다. (기본값은 TRUE)
# make_datetime() 함수는 lubridate 라이브러리에 있는 함수로 지정된 timezone으로 timestamp를 생성하는 함수입니다.
nycflights13::flights %>% 
  mutate(sched_dep_datetime = make_datetime(year, month, day, hour, minute, tz = "America/New_York")) %>% 
  select(carrier, flight, sched_dep_datetime, air_time, distance) %>% 
  as_tsibble(
    key = c("carrier", "flight"),
    index = sched_dep_datetime,
    regular = FALSE
  )
## # A tsibble: 336,776 x 5 [!] <America/New_York>
## # Key:       carrier, flight [5,725]
##    carrier flight sched_dep_datetime  air_time distance
##    <chr>    <int> <dttm>                 <dbl>    <dbl>
##  1 9E        2900 2013-11-03 15:40:00      113      765
##  2 9E        2900 2013-11-04 15:40:00      117      765
##  3 9E        2900 2013-11-05 15:40:00      120      765
##  4 9E        2900 2013-11-06 15:40:00      118      765
##  5 9E        2900 2013-11-07 15:40:00      131      765
##  6 9E        2900 2013-11-08 15:40:00      114      765
##  7 9E        2900 2013-11-09 15:40:00      121      765
##  8 9E        2900 2013-11-10 15:40:00      115      765
##  9 9E        2900 2013-11-11 15:40:00      119      765
## 10 9E        2900 2013-11-12 15:40:00      118      765
## # … with 336,766 more rows
  • 이렇게 등간격이 아닌 tsibble 객체의 경우 출력물에 [ ! ] 표시를 통해 확인할 수 있습니다.



암묵적 결측값 명시하기: fill_gaps()

  • 시계열 데이터에서는 암묵적으로 결측값이 존재하는 케이스도 있습니다.
  • 이렇게 암묵적인 결측치가 존재하는 경우 fill_gaps() 함수를 사용하여 처리 또는 명시할 수 있습니다.
  • 아래 예시를 들어 살펴보겠습니다. 참고
harvest <- tsibble(
  year = c(2010, 2011, 2013, 2011, 2012, 2014),
  fruit = rep(c("kiwi", "cherry"), each = 3),
  kilo = sample(1:10, size = 6),
  key = fruit, 
  index = year
)

harvest
## # A tsibble: 6 x 3 [1Y]
## # Key:       fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2014 cherry     6
## 4  2010 kiwi       7
## 5  2011 kiwi       2
## 6  2013 kiwi       4
  • 위 데이터를 보면 체리(cherry)의 경우 2010년도와 2013년도 생산량이 없었기에 값으로 명시되어 있지 않습니다.
  • 이는 아래 코드로 NA 결측 명시 처리를 할 수 있습니다.
harvest %>% 
  fill_gaps(.full = TRUE)
## # A tsibble: 10 x 3 [1Y]
## # Key:       fruit [2]
##     year fruit   kilo
##    <dbl> <chr>  <int>
##  1  2010 cherry    NA
##  2  2011 cherry     8
##  3  2012 cherry     9
##  4  2013 cherry    NA
##  5  2014 cherry     6
##  6  2010 kiwi       7
##  7  2011 kiwi       2
##  8  2012 kiwi      NA
##  9  2013 kiwi       4
## 10  2014 kiwi      NA
  • .full = FALSE로 arguments를 설정하면 각 key의 index에서 발생한 결측에 대해서만 명시가 이루어집니다. (FALSE가 디폴트 옵션입니다)
harvest %>% 
  fill_gaps(.full = FALSE)
## # A tsibble: 8 x 3 [1Y]
## # Key:       fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2013 cherry    NA
## 4  2014 cherry     6
## 5  2010 kiwi       7
## 6  2011 kiwi       2
## 7  2012 kiwi      NA
## 8  2013 kiwi       4
  • 특정 값으로도 명시가 가능합니다.
harvest %>% 
  fill_gaps(kilo = 0)
## # A tsibble: 8 x 3 [1Y]
## # Key:       fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <dbl>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2013 cherry     0
## 4  2014 cherry     6
## 5  2010 kiwi       7
## 6  2011 kiwi       2
## 7  2012 kiwi       0
## 8  2013 kiwi       4
  • 사칙연산 등의 함수 적용도 가능합니다.
harvest %>% 
  fill_gaps(kilo = sum(kilo))
## # A tsibble: 8 x 3 [1Y]
## # Key:       fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2013 cherry    36
## 4  2014 cherry     6
## 5  2010 kiwi       7
## 6  2011 kiwi       2
## 7  2012 kiwi      36
## 8  2013 kiwi       4
# 각 key 별 중앙값으로 명시하기 위해 group_by_key() 함수 적용 (tidyverse의 group_by와 동일한 개념)
harvest %>% 
  group_by_key() %>% 
  fill_gaps(kilo = median(kilo, na.rm = TRUE))
## # A tsibble: 8 x 3 [1Y]
## # Key:       fruit [2]
## # Groups:    fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2013 cherry     8
## 4  2014 cherry     6
## 5  2010 kiwi       7
## 6  2011 kiwi       2
## 7  2012 kiwi       4
## 8  2013 kiwi       4
  • fill_gaps() 함수와 tidyr 라이브러리에 있는 fill() 함수를 함께 적용하면 암묵적 결측치를 이전 또는 다음 시점의 결측치로 대체할 수 있습니다.
harvest
## # A tsibble: 6 x 3 [1Y]
## # Key:       fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2014 cherry     6
## 4  2010 kiwi       7
## 5  2011 kiwi       2
## 6  2013 kiwi       4
# 이전 시점으로 대체
harvest %>% 
  group_by_key() %>% 
  fill_gaps() %>% 
  tidyr::fill(kilo, .direction = "down")
## # A tsibble: 8 x 3 [1Y]
## # Key:       fruit [2]
## # Groups:    fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2013 cherry     9
## 4  2014 cherry     6
## 5  2010 kiwi       7
## 6  2011 kiwi       2
## 7  2012 kiwi       2
## 8  2013 kiwi       4
# 다음 시점으로 대체
harvest %>% 
  group_by_key() %>% 
  fill_gaps() %>% 
  tidyr::fill(kilo, .direction = "up")
## # A tsibble: 8 x 3 [1Y]
## # Key:       fruit [2]
## # Groups:    fruit [2]
##    year fruit   kilo
##   <dbl> <chr>  <int>
## 1  2011 cherry     8
## 2  2012 cherry     9
## 3  2013 cherry     6
## 4  2014 cherry     6
## 5  2010 kiwi       7
## 6  2011 kiwi       2
## 7  2012 kiwi       4
## 8  2013 kiwi       4
# 맨 위에서 예시로 살펴본 데이터에도 적용
weather_tsbl %>% 
  filter(origin == "EWR") %>% 
  fill_gaps(precip = 0) %>% 
  group_by_key() %>% 
  tidyr::fill(temp, humid, .direction = "down")
## # A tsibble: 8,730 x 5 [1h] <America/New_York>
## # Key:       origin [1]
## # Groups:    origin [1]
##    origin time_hour            temp humid precip
##    <chr>  <dttm>              <dbl> <dbl>  <dbl>
##  1 EWR    2013-01-01 01:00:00  39.0  59.4      0
##  2 EWR    2013-01-01 02:00:00  39.0  61.6      0
##  3 EWR    2013-01-01 03:00:00  39.0  64.4      0
##  4 EWR    2013-01-01 04:00:00  39.9  62.2      0
##  5 EWR    2013-01-01 05:00:00  39.0  64.4      0
##  6 EWR    2013-01-01 06:00:00  37.9  67.2      0
##  7 EWR    2013-01-01 07:00:00  39.0  64.4      0
##  8 EWR    2013-01-01 08:00:00  39.9  62.2      0
##  9 EWR    2013-01-01 09:00:00  39.9  62.2      0
## 10 EWR    2013-01-01 10:00:00  41    59.6      0
## # … with 8,720 more rows



특정 인덱스에 대해 함수 적용하기: index_by() + summarise()

  • index_by() 함수는 lubridate 계열의 날짜/시간 클래스에도 적용 가능합니다.
  • 아래 예시처럼 월별 평균 기온과 총 강수량을 표현해보겠습니다.
  • map() 함수를 적용하는 것처럼 tsibble 객체의 index를 .으로 명시합니다.
weather_tsbl %>% 
  group_by_key() %>% 
  index_by(year_month = ~yearmonth(.)) %>% 
  summarise(
    avg_temp = mean(temp, na.rm = TRUE),
    total_precip = sum(precip, na.rm = TRUE)
  )
## # A tsibble: 36 x 4 [1M]
## # Key:       origin [3]
##    origin year_month avg_temp total_precip
##    <chr>       <mth>    <dbl>        <dbl>
##  1 EWR       2013  1     35.6         3.53
##  2 EWR       2013  2     34.3         3.83
##  3 EWR       2013  3     40.1         3   
##  4 EWR       2013  4     53.0         1.47
##  5 EWR       2013  5     63.3         5.44
##  6 EWR       2013  6     73.3         8.73
##  7 EWR       2013  7     80.7         3.74
##  8 EWR       2013  8     74.5         4.57
##  9 EWR       2013  9     67.3         1.54
## 10 EWR       2013 10     59.8         0.5 
## # … with 26 more rows
  • 이러한 조합의 함수는 등간격이 아닌 인덱스에서도 사용할 수 있다고 합니다.
    (This index_by() + summarise() combo can help with regularising a tsibble of irregular time space too.)
반응형

'time-series (tidy approach)' 카테고리의 다른 글

[R] 6. Exponential smoothing  (0) 2021.07.29
[R] 5. Time-series Regression  (0) 2021.07.29
[R] 4. feasts  (0) 2021.07.28
[R] 3. tsibbledata  (0) 2021.07.28
[R] 1. fpp3 간단한 소개  (0) 2021.07.27
TAGS.

Comments