tidy時系列データに対する差分計算
以下の記事の通りで、差分計算することが多い方はすでにdplyr::lag
を使っていると思います。ここでは、差分計算と変化率、対数収益率を計算する場合についてと、最近少し調べていたtsibble
の中に含まれる関数に関するメモになります。
notchained.hatenablog.com
変化率
tibbletime
パッケージに含まれているFacebookの株価データを利用します。
> library(tidyverse) > library(tibbletime) > > data(FB) > FB # A tibble: 1,008 x 8 symbol date open high low close volume adjusted <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 FB 2013-01-02 27.4 28.2 27.4 28 69846400 28 2 FB 2013-01-03 27.9 28.5 27.6 27.8 63140600 27.8 3 FB 2013-01-04 28.0 28.9 27.8 28.8 72715400 28.8 4 FB 2013-01-07 28.7 29.8 28.6 29.4 83781800 29.4 5 FB 2013-01-08 29.5 29.6 28.9 29.1 45871300 29.1 6 FB 2013-01-09 29.7 30.6 29.5 30.6 104787700 30.6 7 FB 2013-01-10 30.6 31.5 30.3 31.3 95316400 31.3 8 FB 2013-01-11 31.3 32.0 31.1 31.7 89598000 31.7 9 FB 2013-01-14 32.1 32.2 30.6 31.0 98892800 31.0 10 FB 2013-01-15 30.6 31.7 29.9 30.1 173242600 30.1 # … with 998 more rows
diff
は差分計算できない最初の値を除いた値を返すため、mutate
で追加しようとしてもエラーが出ます。
> FB %>% + select(symbol, date, adjusted) %>% + mutate(d = diff(adjusted)) エラー: Column `d` must be length 1008 (the number of rows) or one, not 1007
dplyr::lag
を用いることで差分と変化率は以下のように計算できます。
> FB %>% + select(symbol, date, adjusted) %>% + mutate(d = adjusted - lag(adjusted), + cr = d / lag(adjusted) * 100) # A tibble: 1,008 x 5 symbol date adjusted d cr <chr> <date> <dbl> <dbl> <dbl> 1 FB 2013-01-02 28 NA NA 2 FB 2013-01-03 27.8 -0.23 -0.821 3 FB 2013-01-04 28.8 0.99 3.56 4 FB 2013-01-07 29.4 0.66 2.29 5 FB 2013-01-08 29.1 -0.360 -1.22 6 FB 2013-01-09 30.6 1.53 5.26 7 FB 2013-01-10 31.3 0.710 2.32 8 FB 2013-01-11 31.7 0.42 1.34 9 FB 2013-01-14 31.0 -0.770 -2.43 10 FB 2013-01-15 30.1 -0.850 -2.75 # … with 998 more rows
対数収益率
対数収益率については、diff(log(FB$adjusted))
という感じで計算できるということが巷でよく書かれていますが、こちらも上記と同じ理由でmutate
した場合にはエラーになります。
> FB %>% + select(symbol, date, adjusted) %>% + mutate(ld = diff(log(adjusted))) エラー: Column `ld` must be length 1008 (the number of rows) or one, not 1007
dplyr::lag
を用いた場合には、多少冗長の感じもしますが、それぞれ対数をとった値の差分を計算することになります。
> FB %>% + select(symbol, date, adjusted) %>% + mutate(ld = log(adjusted) - log(lag(adjusted))) # A tibble: 1,008 x 4 symbol date adjusted ld <chr> <date> <dbl> <dbl> 1 FB 2013-01-02 28 NA 2 FB 2013-01-03 27.8 -0.00825 3 FB 2013-01-04 28.8 0.0350 4 FB 2013-01-07 29.4 0.0227 5 FB 2013-01-08 29.1 -0.0123 6 FB 2013-01-09 30.6 0.0513 7 FB 2013-01-10 31.3 0.0229 8 FB 2013-01-11 31.7 0.0133 9 FB 2013-01-14 31.0 -0.0246 10 FB 2013-01-15 30.1 -0.0278 # … with 998 more rows
並び替え付きの差分計算
tsibble
パッケージにはdplyr::with_order
を利用したdifference
という関数が定義されており、時系列で順序が並び替えられていないデータでも並び替えた上で差分計算ができます。
> library(tsibble) > > set.seed(12345) > FB %<>% + select(symbol, date, adjusted) %>% + slice(sample(nrow(FB))) > FB %>% + mutate(d = difference(adjusted, order_by = date)) # A tibble: 1,008 x 4 symbol date adjusted d <chr> <date> <dbl> <dbl> 1 FB 2015-11-18 108. 2.64 2 FB 2016-07-01 114. -0.0900 3 FB 2016-01-15 95.0 -3.40 4 FB 2016-07-15 117. -0.43 5 FB 2014-10-27 80.3 -0.390 6 FB 2013-08-29 41.3 0.730 7 FB 2014-04-17 58.9 -0.780 8 FB 2015-01-09 77.7 -0.440 9 FB 2015-11-19 106. -1.51 10 FB 2016-12-02 115. 0.300 # … with 998 more rows
結局、この後arrange
を使って並び替えて確認したりすることが多そうなので、あまり使う場面は限られるかもしれません。